blob: 2d7c9344657762dad12e45c52ded1011e9c38e4e [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_
#include <stddef.h>
#include <map>
#include <memory>
#include <string>
#include <variant>
#include <vector>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "build/build_config.h"
#include "cc/trees/render_frame_metadata.h"
#include "content/browser/devtools/devtools_video_consumer.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/devtools_download_manager_delegate.h"
#include "content/browser/devtools/protocol/page.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_observer.h"
#include "content/public/common/javascript_dialog_type.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom-forward.h"
#include "url/gurl.h"
class SkBitmap;
namespace base {
class UnguessableToken;
}
namespace gfx {
class Image;
} // namespace gfx
namespace content {
class BackForwardCacheCanStoreDocumentResult;
class DevToolsAgentHostImpl;
class FrameTreeNode;
class NavigationRequest;
class RenderFrameHostImpl;
class WebContentsImpl;
namespace protocol {
class BrowserHandler;
class EmulationHandler;
class PageHandler : public DevToolsDomainHandler,
public Page::Backend,
public RenderWidgetHostObserver,
public download::DownloadItem::Observer {
public:
PageHandler(
EmulationHandler* emulation_handler,
BrowserHandler* browser_handler,
bool allow_unsafe_operations,
bool is_trusted,
std::optional<url::Origin> navigation_initiator_origin,
bool may_read_local_files,
base::RepeatingCallback<void(std::string)> prepare_for_reload_callback);
PageHandler(const PageHandler&) = delete;
PageHandler& operator=(const PageHandler&) = delete;
~PageHandler() override;
static std::vector<PageHandler*> EnabledForWebContents(
WebContentsImpl* contents);
static std::vector<PageHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
void Wire(UberDispatcher* dispatcher) override;
void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override;
// Instrumentation signals.
void DidAttachInterstitialPage();
void DidDetachInterstitialPage();
using JavaScriptDialogCallback =
content::JavaScriptDialogManager::DialogClosedCallback;
void DidRunJavaScriptDialog(const GURL& url,
const base::UnguessableToken& frame_id,
const std::u16string& message,
const std::u16string& default_prompt,
JavaScriptDialogType dialog_type,
bool has_non_devtools_handlers,
JavaScriptDialogCallback callback);
void DidRunBeforeUnloadConfirm(const GURL& url,
const base::UnguessableToken& frame_id,
bool has_non_devtools_handlers,
JavaScriptDialogCallback callback);
void DidCloseJavaScriptDialog(const base::UnguessableToken& frame_id,
bool success,
const std::u16string& user_input);
void NavigationReset(NavigationRequest* navigation_request);
void DownloadWillBegin(FrameTreeNode* ftn, download::DownloadItem* item);
void DidStartNavigating(FrameTreeNode& ftn,
const GURL& url,
const base::UnguessableToken& loader_id,
const blink::mojom::NavigationType& navigation_type);
void OnFrameDetached(const base::UnguessableToken& frame_id);
void DidChangeFrameLoadingState(const FrameTreeNode& ftn);
bool ShouldBypassCSP();
void BackForwardCacheNotUsed(
const NavigationRequest* nav_request,
const BackForwardCacheCanStoreDocumentResult* result,
const BackForwardCacheCanStoreTreeResult* tree_result);
void IsPrerenderingAllowed(bool& is_allowed);
void ReadyToCommitNavigation(NavigationRequest* navigation_request);
Response Enable(
std::optional<bool> enable_file_chooser_opened_event) override;
Response Disable() override;
Response Crash() override;
Response Close() override;
void Reload(std::optional<bool> bypassCache,
std::optional<std::string> script_to_evaluate_on_load,
std::optional<std::string> loader_id,
std::unique_ptr<ReloadCallback> callback) override;
void Navigate(const std::string& url,
std::optional<std::string> referrer,
std::optional<std::string> transition_type,
std::optional<std::string> frame_id,
std::optional<std::string> referrer_policy,
std::unique_ptr<NavigateCallback> callback) override;
Response StopLoading() override;
using NavigationEntries = protocol::Array<Page::NavigationEntry>;
Response GetNavigationHistory(
int* current_index,
std::unique_ptr<NavigationEntries>* entries) override;
Response NavigateToHistoryEntry(int entry_id) override;
Response ResetNavigationHistory() override;
void CaptureScreenshot(
std::optional<std::string> format,
std::optional<int> quality,
std::unique_ptr<Page::Viewport> clip,
std::optional<bool> from_surface,
std::optional<bool> capture_beyond_viewport,
std::optional<bool> optimize_for_speed,
std::unique_ptr<CaptureScreenshotCallback> callback) override;
void CaptureSnapshot(
std::optional<std::string> format,
std::unique_ptr<CaptureSnapshotCallback> callback) override;
Response StartScreencast(std::optional<std::string> format,
std::optional<int> quality,
std::optional<int> max_width,
std::optional<int> max_height,
std::optional<int> every_nth_frame) override;
Response StopScreencast() override;
Response ScreencastFrameAck(int session_id) override;
Response HandleJavaScriptDialog(
bool accept,
std::optional<std::string> prompt_text) override;
Response BringToFront() override;
Response SetDownloadBehavior(
const std::string& behavior,
std::optional<std::string> download_path) override;
void GetAppManifest(
std::optional<std::string> manifest_id,
std::unique_ptr<GetAppManifestCallback> callback) override;
Response SetWebLifecycleState(const std::string& state) override;
void GetInstallabilityErrors(
std::unique_ptr<GetInstallabilityErrorsCallback> callback) override;
void GetManifestIcons(
std::unique_ptr<GetManifestIconsCallback> callback) override;
void GetAppId(std::unique_ptr<GetAppIdCallback> callback) override;
Response SetBypassCSP(bool enabled) override;
Response AddCompilationCache(const std::string& url,
const Binary& data) override;
Response SetPrerenderingAllowed(bool is_allowed) override;
Response AssureTopLevelActiveFrame();
private:
struct PendingScreenshotRequest;
using BitmapEncoder =
base::RepeatingCallback<std::optional<std::vector<uint8_t>>(
const SkBitmap& bitmap)>;
void CaptureFullPageScreenshot(
std::optional<std::string> format,
std::optional<int> quality,
std::optional<bool> optimize_for_speed,
std::unique_ptr<CaptureScreenshotCallback> callback,
const gfx::Size& full_page_size);
bool ShouldCaptureNextScreencastFrame();
void NotifyScreencastVisibility(bool visible);
void OnFrameFromVideoConsumer(scoped_refptr<media::VideoFrame> frame);
void ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> metadata,
const SkBitmap& bitmap);
void ScreencastFrameEncoded(
std::unique_ptr<Page::ScreencastFrameMetadata> metadata,
std::optional<std::vector<uint8_t>> data);
void ScreenshotCaptured(std::unique_ptr<PendingScreenshotRequest> request,
const gfx::Image& image);
// RenderWidgetHostObserver overrides.
void RenderWidgetHostVisibilityChanged(RenderWidgetHost* widget_host,
bool became_visible) override;
void RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) override;
// DownloadItem::Observer overrides
void OnDownloadUpdated(download::DownloadItem* item) override;
void OnDownloadDestroyed(download::DownloadItem* item) override;
// Returns WebContents only if `host_` is a top level frame. Otherwise, it
// returns Response with an error.
using ResponseOrWebContents = std::variant<Response, WebContentsImpl*>;
ResponseOrWebContents GetWebContentsForTopLevelActiveFrame();
const bool allow_unsafe_operations_;
const bool is_trusted_;
const std::optional<url::Origin> navigation_initiator_origin_;
const bool may_read_local_files_;
bool enabled_;
bool bypass_csp_ = false;
BitmapEncoder screencast_encoder_;
int screencast_max_width_;
int screencast_max_height_;
int capture_every_nth_frame_;
int session_id_;
int frame_counter_;
int frames_in_flight_;
// |video_consumer_| consumes video frames from FrameSinkVideoCapturerImpl,
// and provides PageHandler with these frames via OnFrameFromVideoConsumer.
// This is only used if Viz is enabled and if OS is not Android.
std::unique_ptr<DevToolsVideoConsumer> video_consumer_;
// The last surface size used to determine if frames with new sizes need
// to be requested. This changes due to window resizing.
gfx::Size last_surface_size_;
raw_ptr<RenderFrameHostImpl> host_;
raw_ptr<EmulationHandler> emulation_handler_;
raw_ptr<BrowserHandler> browser_handler_;
std::unique_ptr<Page::Frontend> frontend_;
base::ScopedObservation<RenderWidgetHost, RenderWidgetHostObserver>
observation_{this};
JavaScriptDialogCallback pending_dialog_;
// Maps DevTools navigation tokens to pending NavigateCallbacks.
base::flat_map<base::UnguessableToken, std::unique_ptr<NavigateCallback>>
navigate_callbacks_;
base::flat_set<raw_ptr<download::DownloadItem, CtnExperimental>>
pending_downloads_;
bool is_prerendering_allowed_ = true;
base::RepeatingCallback<void(std::string)> prepare_for_reload_callback_;
bool have_pending_reload_ = false;
std::string pending_script_to_evaluate_on_load_;
base::WeakPtrFactory<PageHandler> weak_factory_{this};
};
} // namespace protocol
} // namespace content
#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_PAGE_HANDLER_H_