[go: nahoru, domu]

blob: 0f8cea14c8b4ab2fc6e7022495050b2a3082ac49 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_CLIENT_H_
#define COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_CLIENT_H_
#include <stdint.h>
#include <memory>
#include "base/callback.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/files/file_path.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "components/paint_preview/common/capture_result.h"
#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom-shared.h"
#include "components/paint_preview/common/mojom/paint_preview_recorder.mojom.h"
#include "components/paint_preview/common/proto/paint_preview.pb.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "ui/gfx/geometry/rect.h"
#include "url/gurl.h"
namespace paint_preview {
// Client responsible for making requests to the mojom::PaintPreviewRecorder. A
// client coordinates between multiple frames and handles capture and
// aggreagation of data from both the main frame and subframes.
//
// Should be created and accessed from the UI thread as WebContentsUserData
// requires this behavior.
class PaintPreviewClient
: public content::WebContentsUserData<PaintPreviewClient>,
public content::WebContentsObserver {
public:
using PaintPreviewCallback =
base::OnceCallback<void(base::UnguessableToken,
mojom::PaintPreviewStatus,
std::unique_ptr<CaptureResult>)>;
// Augmented version of mojom::PaintPreviewServiceParams.
struct PaintPreviewParams {
explicit PaintPreviewParams(RecordingPersistence persistence);
~PaintPreviewParams();
// Indicates where the PaintPreviewRecorder should store its intermediate
// artifacts.
RecordingPersistence persistence;
// The root directory in which to store paint_previews. This should be
// a subdirectory inside the active user profile's directory.
base::FilePath root_dir;
RecordingParams inner;
};
~PaintPreviewClient() override;
// IMPORTANT: The Capture* methods must be called on the UI thread!
// Captures a paint preview corresponding to the content of
// |render_frame_host|. This will work for capturing entire documents if
// passed the main frame or for just a specific subframe depending on
// |render_frame_host|. |callback| is invoked on completion.
void CapturePaintPreview(const PaintPreviewParams& params,
content::RenderFrameHost* render_frame_host,
PaintPreviewCallback callback);
// Captures a paint preview of the subframe corresponding to
// |render_subframe_host|.
void CaptureSubframePaintPreview(
const base::UnguessableToken& guid,
const gfx::Rect& rect,
content::RenderFrameHost* render_subframe_host);
// WebContentsObserver implementation ---------------------------------------
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
private:
explicit PaintPreviewClient(content::WebContents* web_contents);
friend class content::WebContentsUserData<PaintPreviewClient>;
// Internal Storage Classes -------------------------------------------------
// Ephemeral state for a document being captured. This will be accumulated to
// as the capture progresses and results in a |CaptureResult|.
struct InProgressDocumentCaptureState {
public:
InProgressDocumentCaptureState();
~InProgressDocumentCaptureState();
RecordingPersistence persistence;
// If |RecordingPersistence::kFileSystem|, the root directory to store
// artifacts to. Ignored if |RecordingPersistence::kMemoryBuffer|.
base::FilePath root_dir;
// This corresponds to RenderFrameHost::EmbeddingToken.
base::UnguessableToken root_frame_token;
// From the first recording params. Whether to capture links and the
// size limit per capture respectively.
bool capture_links = true;
size_t max_per_capture_size = 0;
uint64_t max_decoded_image_size_bytes{std::numeric_limits<uint64_t>::max()};
// UKM Source ID of the WebContent.
ukm::SourceId source_id;
// Main frame capture time.
base::TimeDelta main_frame_blink_recording_time;
// Callback that is invoked on completion of data.
PaintPreviewCallback callback;
// All the render frames that are still required.
base::flat_set<base::UnguessableToken> awaiting_subframes;
// All the render frames that have finished.
base::flat_set<base::UnguessableToken> finished_subframes;
// All the render frames that are allowed to be captured.
base::flat_set<base::UnguessableToken> accepted_tokens;
// If |RecordingPersistence::kMemoryBuffer|, this will contain the
// successful recordings. Empty if |RecordingPersistence::FileSystem|
base::flat_map<base::UnguessableToken, mojo_base::BigBuffer>
serialized_skps;
PaintPreviewProto proto;
// Indicates that at least one subframe finished unsuccessfully.
bool had_error = false;
// Indicates that at least one subframe finished successfully.
bool had_success = false;
// Indicates if we should clean up files associated with awaiting frames on
// destruction
bool should_clean_up_files = false;
// This flag will skip GPU accelerated content where applicable when
// capturing. This reduces hangs, capture time and may also reduce OOM
// crashes, but results in a lower fideltiy capture (i.e. the contents
// captured may not accurately reflect the content visible to the user at
// time of capture). See PaintPreviewBaseService::CaptureParams for a
// description of the effects of this flag.
bool skip_accelerated_content = false;
// Generates a file path based off |root_dir| and |frame_guid|. Will be in
// the form "{hexadecimal}.skp".
base::FilePath FilePathForFrame(const base::UnguessableToken& frame_guid);
// Record a successful recording into this capture state.
void RecordSuccessfulFrame(const base::UnguessableToken& frame_guid,
bool is_main_frame,
mojom::PaintPreviewCaptureResponsePtr response);
// Convert this capture state into a form that can be returned to the
// original paint preview capture request.
std::unique_ptr<CaptureResult> IntoCaptureResult() &&;
InProgressDocumentCaptureState& operator=(
InProgressDocumentCaptureState&& other) noexcept;
InProgressDocumentCaptureState(
InProgressDocumentCaptureState&& other) noexcept;
private:
InProgressDocumentCaptureState(const InProgressDocumentCaptureState&) =
delete;
InProgressDocumentCaptureState& operator=(
const InProgressDocumentCaptureState&) = delete;
};
// Sets up for a capture of a frame on |render_frame_host| according to
// |params|.
void CapturePaintPreviewInternal(const RecordingParams& params,
content::RenderFrameHost* render_frame_host);
// Initiates capture via the PaintPreviewRecorder associated with
// |render_frame_host| using |params| to configure the request. |frame_guid|
// is the GUID associated with the frame. |path| is file path associated with
// the File stored in |result| (base::File isn't aware of its file path).
void RequestCaptureOnUIThread(
const base::UnguessableToken& frame_guid,
const RecordingParams& params,
const content::GlobalRenderFrameHostId& render_frame_id,
mojom::PaintPreviewStatus status,
mojom::PaintPreviewCaptureParamsPtr capture_params);
// Handles recording the frame and updating client state when capture is
// complete.
void OnPaintPreviewCapturedCallback(
const base::UnguessableToken& frame_guid,
const RecordingParams& params,
const content::GlobalRenderFrameHostId& render_frame_id,
mojom::PaintPreviewStatus status,
mojom::PaintPreviewCaptureResponsePtr response);
// Marks a frame as having been processed, this should occur regardless of
// whether the processed frame is valid as there is no retry.
void MarkFrameAsProcessed(base::UnguessableToken guid,
const base::UnguessableToken& frame_guid);
// Handles finishing the capture once all frames are received.
void OnFinished(base::UnguessableToken guid,
InProgressDocumentCaptureState* document_data);
// Storage ------------------------------------------------------------------
// Maps a RenderFrameHost and document to a remote interface.
base::flat_map<base::UnguessableToken,
mojo::AssociatedRemote<mojom::PaintPreviewRecorder>>
interface_ptrs_;
// Maps render frame's GUID and document cookies that requested the frame.
base::flat_map<base::UnguessableToken, base::flat_set<base::UnguessableToken>>
pending_previews_on_subframe_;
// Maps a document GUID to its capture state while it is in-progress. Entries
// in this map should be cleaned up when a capture completes (either
// successfully or not).
base::flat_map<base::UnguessableToken, InProgressDocumentCaptureState>
all_document_data_;
base::WeakPtrFactory<PaintPreviewClient> weak_ptr_factory_{this};
WEB_CONTENTS_USER_DATA_KEY_DECL();
PaintPreviewClient(const PaintPreviewClient&) = delete;
PaintPreviewClient& operator=(const PaintPreviewClient&) = delete;
};
} // namespace paint_preview
#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_PAINT_PREVIEW_CLIENT_H_