#include "content/browser/devtools/protocol/page_handler.h"
#include <algorithm>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/process_handle.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/to_string.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/back_forward_cache/disabled_reason_id.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/devtools_agent_host_impl.h"
#include "content/browser/devtools/protocol/browser_handler.h"
#include "content/browser/devtools/protocol/devtools_mhtml_helper.h"
#include "content/browser/devtools/protocol/emulation_handler.h"
#include "content/browser/devtools/protocol/handler_helpers.h"
#include "content/browser/manifest/manifest_manager_host.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/renderer_host/back_forward_cache_can_store_document_result.h"
#include "content/browser/renderer_host/back_forward_cache_disable.h"
#include "content/browser/renderer_host/back_forward_cache_metrics.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/referrer.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/base/filename_util.h"
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h"
#include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom.h"
#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
#include "third_party/blink/public/mojom/script_source_location.mojom.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/page_transition_types.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/codec/webp_codec.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/skbitmap_operations.h"
#include "ui/snapshot/snapshot.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_ANDROID)
#include "content/browser/renderer_host/compositor_impl_android.h"
#endif
namespace content {
namespace protocol {
namespace {
constexpr const char* kMhtml = …;
constexpr int kDefaultScreenshotQuality = …;
constexpr int kMaxScreencastFramesInFlight = …;
constexpr char kCommandIsOnlyAvailableAtTopTarget[] = …;
constexpr char kErrorNotAttached[] = …;
constexpr char kErrorInactivePage[] = …;
BitmapEncoder;
bool EncodeBitmapAsPngSlow(const SkBitmap& bitmap,
std::vector<uint8_t>& output) { … }
bool EncodeBitmapAsPngFast(const SkBitmap& bitmap,
std::vector<uint8_t>& output) { … }
bool EncodeBitmapAsJpeg(int quality,
const SkBitmap& bitmap,
std::vector<uint8_t>& output) { … }
bool EncodeBitmapAsWebp(int quality,
const SkBitmap& bitmap,
std::vector<uint8_t>& output) { … }
absl::variant<protocol::Response, BitmapEncoder>
GetEncoder(const std::string& format, int quality, bool optimize_for_speed) { … }
std::unique_ptr<Page::ScreencastFrameMetadata> BuildScreencastFrameMetadata(
const gfx::Size& surface_size,
float device_scale_factor,
float page_scale_factor,
const gfx::PointF& root_scroll_offset,
float top_controls_visible_height) { … }
gfx::Size DetermineSnapshotSize(const gfx::Size& surface_size,
int screencast_max_width,
int screencast_max_height) { … }
void GetMetadataFromFrame(const media::VideoFrame& frame,
double* device_scale_factor,
double* page_scale_factor,
gfx::PointF* root_scroll_offset,
double* top_controls_visible_height) { … }
template <typename ProtocolCallback>
bool CanExecuteGlobalCommands(
PageHandler* page_handler,
const std::unique_ptr<ProtocolCallback>& callback) { … }
void GotManifest(protocol::Maybe<std::string> manifest_id,
std::unique_ptr<PageHandler::GetAppManifestCallback> callback,
const GURL& manifest_url,
::blink::mojom::ManifestPtr input_manifest,
blink::mojom::ManifestDebugInfoPtr debug_info) { … }
}
PageHandler::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)
: … { … }
PageHandler::~PageHandler() = default;
std::vector<PageHandler*> PageHandler::EnabledForWebContents(
WebContentsImpl* contents) { … }
std::vector<PageHandler*> PageHandler::ForAgentHost(
DevToolsAgentHostImpl* host) { … }
void PageHandler::SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) { … }
void PageHandler::Wire(UberDispatcher* dispatcher) { … }
void PageHandler::RenderWidgetHostVisibilityChanged(
RenderWidgetHost* widget_host,
bool became_visible) { … }
void PageHandler::RenderWidgetHostDestroyed(RenderWidgetHost* widget_host) { … }
void PageHandler::DidAttachInterstitialPage() { … }
void PageHandler::DidDetachInterstitialPage() { … }
void PageHandler::DidRunJavaScriptDialog(const GURL& url,
const std::u16string& message,
const std::u16string& default_prompt,
JavaScriptDialogType dialog_type,
bool has_non_devtools_handlers,
JavaScriptDialogCallback callback) { … }
void PageHandler::DidRunBeforeUnloadConfirm(const GURL& url,
bool has_non_devtools_handlers,
JavaScriptDialogCallback callback) { … }
void PageHandler::DidCloseJavaScriptDialog(bool success,
const std::u16string& user_input) { … }
Response PageHandler::Enable() { … }
Response PageHandler::Disable() { … }
Response PageHandler::Crash() { … }
Response PageHandler::Close() { … }
void PageHandler::Reload(Maybe<bool> bypassCache,
Maybe<std::string> script_to_evaluate_on_load,
Maybe<std::string> loader_id,
std::unique_ptr<ReloadCallback> callback) { … }
static network::mojom::ReferrerPolicy ParsePolicyFromString(
const std::string& policy) { … }
namespace {
void DispatchNavigateCallback(
NavigationRequest* request,
std::unique_ptr<PageHandler::NavigateCallback> callback) { … }
}
void PageHandler::Navigate(const std::string& url,
Maybe<std::string> referrer,
Maybe<std::string> maybe_transition_type,
Maybe<std::string> frame_id,
Maybe<std::string> referrer_policy,
std::unique_ptr<NavigateCallback> callback) { … }
void PageHandler::NavigationReset(NavigationRequest* navigation_request) { … }
void PageHandler::DownloadWillBegin(FrameTreeNode* ftn,
download::DownloadItem* item) { … }
void PageHandler::OnFrameDetached(const base::UnguessableToken& frame_id) { … }
void PageHandler::DidChangeFrameLoadingState(const FrameTreeNode& ftn) { … }
void PageHandler::OnDownloadDestroyed(download::DownloadItem* item) { … }
void PageHandler::OnDownloadUpdated(download::DownloadItem* item) { … }
static const char* TransitionTypeName(ui::PageTransition type) { … }
Response PageHandler::GetNavigationHistory(
int* current_index,
std::unique_ptr<NavigationEntries>* entries) { … }
Response PageHandler::NavigateToHistoryEntry(int entry_id) { … }
static bool ReturnTrue(NavigationEntry* entry) { … }
Response PageHandler::ResetNavigationHistory() { … }
void PageHandler::CaptureSnapshot(
Maybe<std::string> format,
std::unique_ptr<CaptureSnapshotCallback> callback) { … }
void PageHandler::CaptureFullPageScreenshot(
Maybe<std::string> format,
Maybe<int> quality,
Maybe<bool> optimize_for_speed,
std::unique_ptr<CaptureScreenshotCallback> callback,
const gfx::Size& full_page_size) { … }
void PageHandler::CaptureScreenshot(
Maybe<std::string> format,
Maybe<int> quality,
Maybe<Page::Viewport> clip,
Maybe<bool> from_surface,
Maybe<bool> capture_beyond_viewport,
Maybe<bool> optimize_for_speed,
std::unique_ptr<CaptureScreenshotCallback> callback) { … }
Response PageHandler::StartScreencast(Maybe<std::string> format,
Maybe<int> quality,
Maybe<int> max_width,
Maybe<int> max_height,
Maybe<int> every_nth_frame) { … }
Response PageHandler::StopScreencast() { … }
Response PageHandler::ScreencastFrameAck(int session_id) { … }
Response PageHandler::HandleJavaScriptDialog(bool accept,
Maybe<std::string> prompt_text) { … }
Response PageHandler::BringToFront() { … }
Response PageHandler::SetDownloadBehavior(const std::string& behavior,
Maybe<std::string> download_path) { … }
void PageHandler::GetAppManifest(
protocol::Maybe<std::string> manifest_id,
std::unique_ptr<GetAppManifestCallback> callback) { … }
PageHandler::ResponseOrWebContents
PageHandler::GetWebContentsForTopLevelActiveFrame() { … }
void PageHandler::NotifyScreencastVisibility(bool visible) { … }
bool PageHandler::ShouldCaptureNextScreencastFrame() { … }
void PageHandler::OnFrameFromVideoConsumer(
scoped_refptr<media::VideoFrame> frame) { … }
void PageHandler::ScreencastFrameCaptured(
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata,
const SkBitmap& bitmap) { … }
void PageHandler::ScreencastFrameEncoded(
std::unique_ptr<Page::ScreencastFrameMetadata> page_metadata,
std::vector<uint8_t> data) { … }
void PageHandler::ScreenshotCaptured(
std::unique_ptr<CaptureScreenshotCallback> callback,
BitmapEncoder encoder,
const gfx::Size& original_view_size,
const gfx::Size& requested_image_size,
const blink::DeviceEmulationParams& original_emulation_params,
const std::optional<blink::web_pref::WebPreferences>&
maybe_original_web_prefs,
const gfx::Image& image) { … }
Response PageHandler::StopLoading() { … }
Response PageHandler::SetWebLifecycleState(const std::string& state) { … }
void PageHandler::GetInstallabilityErrors(
std::unique_ptr<GetInstallabilityErrorsCallback> callback) { … }
void PageHandler::GetManifestIcons(
std::unique_ptr<GetManifestIconsCallback> callback) { … }
void PageHandler::GetAppId(std::unique_ptr<GetAppIdCallback> callback) { … }
Response PageHandler::SetBypassCSP(bool enabled) { … }
Page::BackForwardCacheNotRestoredReason NotRestoredReasonToProtocol(
BackForwardCacheMetrics::NotRestoredReason reason) { … }
WebSchedulerTrackedFeature;
Page::BackForwardCacheNotRestoredReason BlocklistedFeatureToProtocol(
WebSchedulerTrackedFeature feature) { … }
std::unique_ptr<Page::BackForwardCacheBlockingDetails> SourceLocationToProtocol(
const blink::mojom::ScriptSourceLocationPtr& source) { … }
Page::BackForwardCacheNotRestoredReason
DisableForRenderFrameHostReasonToProtocol(
BackForwardCache::DisabledReason reason) { … }
Page::BackForwardCacheNotRestoredReasonType MapNotRestoredReasonToType(
BackForwardCacheMetrics::NotRestoredReason reason) { … }
Page::BackForwardCacheNotRestoredReasonType MapBlocklistedFeatureToType(
WebSchedulerTrackedFeature feature) { … }
Page::BackForwardCacheNotRestoredReasonType
MapDisableForRenderFrameHostReasonToType(
BackForwardCache::DisabledReason reason) { … }
BlockingDetailsMap;
std::unique_ptr<protocol::Array<Page::BackForwardCacheNotRestoredExplanation>>
CreateNotRestoredExplanation(
const BackForwardCacheCanStoreDocumentResult::NotRestoredReasons
not_restored_reasons,
const blink::scheduler::WebSchedulerTrackedFeatures blocklisted_features,
const BackForwardCacheCanStoreDocumentResult::DisabledReasonsMap&
disabled_reasons,
const BlockingDetailsMap& details) { … }
std::unique_ptr<Page::BackForwardCacheNotRestoredExplanationTree>
CreateNotRestoredExplanationTree(
const BackForwardCacheCanStoreTreeResult& tree_result) { … }
Response PageHandler::AddCompilationCache(const std::string& url,
const Binary& data) { … }
void PageHandler::IsPrerenderingAllowed(bool& is_allowed) { … }
Response PageHandler::SetPrerenderingAllowed(bool is_allowed) { … }
Response PageHandler::AssureTopLevelActiveFrame() { … }
void PageHandler::BackForwardCacheNotUsed(
const NavigationRequest* navigation,
const BackForwardCacheCanStoreDocumentResult* result,
const BackForwardCacheCanStoreTreeResult* tree_result) { … }
bool PageHandler::ShouldBypassCSP() { … }
}
}