chromium/chrome/browser/devtools/devtools_window.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/devtools/devtools_window.h"

#include <memory>
#include <set>
#include <string_view>
#include <utility>

#include "aida_client.h"
#include "base/base64.h"
#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/not_fatal_until.h"
#include "base/ranges/algorithm.h"
#include "base/strings/escape.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/certificate_viewer.h"
#include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
#include "chrome/browser/devtools/devtools_eye_dropper.h"
#include "chrome/browser/devtools/process_sharing_infobar_delegate.h"
#include "chrome/browser/file_select_helper.h"
#include "chrome/browser/infobars/confirm_infobar_creator.h"
#include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
#include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/task_manager/web_contents_tags.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/prefs/prefs_tab_helper.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_strip_user_gesture_details.h"
#include "chrome/browser/ui/webui/devtools/devtools_ui.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "components/infobars/content/content_infobar_manager.h"
#include "components/infobars/core/infobar.h"
#include "components/input/native_web_keyboard_event.h"
#include "components/javascript_dialogs/app_modal_dialog_manager.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/language/core/browser/pref_names.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "components/search_engines/util.h"
#include "components/sessions/content/session_tab_helper.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "components/zoom/page_zoom.h"
#include "components/zoom/zoom_controller.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/color_chooser.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/keyboard_event_processing_result.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/navigation_throttle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/view_type_utils.h"
#include "extensions/common/constants.h"
#include "net/cert/x509_certificate.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/input/web_input_event.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
#include "third_party/blink/public/public_buildflags.h"
#include "ui/base/page_transition_types.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/keycodes/keyboard_codes.h"

// This should be after all other #includes.
#if defined(_WINDOWS_)  // Detect whether windows.h was included.
#include "base/win/windows_h_disallowed.h"
#endif  // defined(_WINDOWS_)

WebInputEvent;
BrowserThread;
DevToolsAgentHost;
WebContents;

namespace {

DevToolsWindows;
base::LazyInstance<DevToolsWindows>::Leaky g_devtools_window_instances =;

base::LazyInstance<
    std::vector<base::RepeatingCallback<void(DevToolsWindow*)>>>::Leaky
    g_creation_callbacks =;

static const char kKeyUpEventName[] =;
static const char kKeyDownEventName[] =;
static const char kDefaultFrontendURL[] =;
static const char kNodeFrontendURL[] =;
static const char kWorkerFrontendURL[] =;
static const char kJSFrontendURL[] =;
static const char kFallbackFrontendURL[] =;

bool FindInspectedBrowserAndTabIndex(
    WebContents* inspected_web_contents, Browser** browser, int* tab) {}

void SetPreferencesFromJson(Profile* profile, const std::string& json) {}

// DevToolsToolboxDelegate ----------------------------------------------------

class DevToolsToolboxDelegate
    : public content::WebContentsObserver,
      public content::WebContentsDelegate {};

DevToolsToolboxDelegate::DevToolsToolboxDelegate(WebContents* toolbox_contents,
                                                 WebContents* web_contents)
    :{}

DevToolsToolboxDelegate::~DevToolsToolboxDelegate() {}

content::WebContents* DevToolsToolboxDelegate::OpenURLFromTab(
    content::WebContents* source,
    const content::OpenURLParams& params,
    base::OnceCallback<void(content::NavigationHandle&)>
        navigation_handle_callback) {}

content::KeyboardEventProcessingResult
DevToolsToolboxDelegate::PreHandleKeyboardEvent(
    content::WebContents* source,
    const input::NativeWebKeyboardEvent& event) {}

bool DevToolsToolboxDelegate::HandleKeyboardEvent(
    content::WebContents* source,
    const input::NativeWebKeyboardEvent& event) {}

void DevToolsToolboxDelegate::WebContentsDestroyed() {}

BrowserWindow* DevToolsToolboxDelegate::GetInspectedBrowserWindow() {}

// static
GURL DecorateFrontendURL(const GURL& base_url) {}

}  // namespace

// DevToolsEventForwarder -----------------------------------------------------

class DevToolsEventForwarder {};

void DevToolsEventForwarder::SetWhitelistedShortcuts(
    const std::string& message) {}

bool DevToolsEventForwarder::ForwardEvent(
    const input::NativeWebKeyboardEvent& event) {}

int DevToolsEventForwarder::CombineKeyCodeAndModifiers(int key_code,
                                                       int modifiers) {}

bool DevToolsEventForwarder::KeyWhitelistingAllowed(int key_code,
                                                    int modifiers) {}

void DevToolsWindow::OpenNodeFrontend() {}

// DevToolsWindow::Throttle ------------------------------------------

class DevToolsWindow::Throttle : public content::NavigationThrottle {};

// Helper class that holds the owned main WebContents for the docked
// devtools window and maintains a keepalive object that keeps the browser
// main loop alive long enough for the WebContents to clean up properly.
class DevToolsWindow::OwnedMainWebContents {};

// DevToolsWindow -------------------------------------------------------------

const char DevToolsWindow::kDevToolsApp[] =;

// static
void DevToolsWindow::AddCreationCallbackForTest(
    const CreationCallback& callback) {}

// static
void DevToolsWindow::RemoveCreationCallbackForTest(
    const CreationCallback& callback) {}

DevToolsWindow::~DevToolsWindow() {}

// static
void DevToolsWindow::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {}

// static
content::WebContents* DevToolsWindow::GetInTabWebContents(
    WebContents* inspected_web_contents,
    DevToolsContentsResizingStrategy* out_strategy) {}

// static
DevToolsWindow* DevToolsWindow::GetInstanceForInspectedWebContents(
    WebContents* inspected_web_contents) {}

// static
bool DevToolsWindow::IsDevToolsWindow(content::WebContents* web_contents) {}

// static
void DevToolsWindow::OpenDevToolsWindowForWorker(
    Profile* profile,
    const scoped_refptr<DevToolsAgentHost>& worker_agent,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindow(
    content::WebContents* inspected_web_contents,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindow(
    content::WebContents* inspected_web_contents,
    Profile* profile,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindow(
    scoped_refptr<content::DevToolsAgentHost> agent_host,
    Profile* profile,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindowWithBundledFrontend(
    scoped_refptr<content::DevToolsAgentHost> agent_host,
    Profile* profile,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindow(
    scoped_refptr<content::DevToolsAgentHost> agent_host,
    Profile* profile,
    bool use_bundled_frontend,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindow(
    content::WebContents* inspected_web_contents,
    const DevToolsToggleAction& action,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenDevToolsWindowForFrame(
    Profile* profile,
    const scoped_refptr<content::DevToolsAgentHost>& agent_host,
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::ToggleDevToolsWindow(Browser* browser,
                                          const DevToolsToggleAction& action,
                                          DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::OpenExternalFrontend(
    Profile* profile,
    const std::string& frontend_url,
    const scoped_refptr<content::DevToolsAgentHost>& agent_host,
    bool use_bundled_frontend,
    DevToolsOpenedByAction opened_by) {}

// static
DevToolsWindow* DevToolsWindow::OpenNodeFrontendWindow(
    Profile* profile,
    DevToolsOpenedByAction opened_by) {}

// static
Profile* DevToolsWindow::GetProfileForDevToolsWindow(
    content::WebContents* web_contents) {}

namespace {

scoped_refptr<DevToolsAgentHost> GetOrCreateDevToolsHostForWebContents(
    WebContents* wc) {}

}  // namespace

// static
void DevToolsWindow::ToggleDevToolsWindow(
    content::WebContents* inspected_web_contents,
    Profile* profile,
    bool force_open,
    const DevToolsToggleAction& action,
    const std::string& settings,
    DevToolsOpenedByAction toggled_by) {}

// static
void DevToolsWindow::InspectElement(
    content::RenderFrameHost* inspected_frame_host,
    int x,
    int y) {}

// static
void DevToolsWindow::LogDevToolsOpenedByAction(
    DevToolsOpenedByAction opened_by) {}

// static
void DevToolsWindow::LogDevToolsOpenedUKM(content::WebContents* web_contents) {}

// static
std::unique_ptr<content::NavigationThrottle>
DevToolsWindow::MaybeCreateNavigationThrottle(
    content::NavigationHandle* handle) {}

void DevToolsWindow::ScheduleShow(const DevToolsToggleAction& action) {}

void DevToolsWindow::Show(const DevToolsToggleAction& action) {}

// static
bool DevToolsWindow::HandleBeforeUnload(WebContents* frontend_contents,
    bool proceed, bool* proceed_to_fire_unload) {}

// static
bool DevToolsWindow::InterceptPageBeforeUnload(WebContents* contents) {}

// static
bool DevToolsWindow::NeedsToInterceptBeforeUnload(
    WebContents* contents) {}

// static
bool DevToolsWindow::HasFiredBeforeUnloadEventForDevToolsBrowser(
    Browser* browser) {}

// static
void DevToolsWindow::OnPageCloseCanceled(WebContents* contents) {}

DevToolsWindow::DevToolsWindow(FrontendType frontend_type,
                               Profile* profile,
                               std::unique_ptr<WebContents> main_web_contents,
                               DevToolsUIBindings* bindings,
                               WebContents* inspected_web_contents,
                               bool can_dock,
                               DevToolsOpenedByAction opened_by)
    :{}

// static
bool DevToolsWindow::AllowDevToolsFor(Profile* profile,
                                      content::WebContents* web_contents) {}

// static
DevToolsWindow* DevToolsWindow::Create(
    Profile* profile,
    content::WebContents* inspected_web_contents,
    FrontendType frontend_type,
    const std::string& frontend_url,
    bool can_dock,
    const std::string& settings,
    const std::string& panel,
    bool has_other_clients,
    bool browser_connection,
    DevToolsOpenedByAction opened_by) {}

// static
GURL DevToolsWindow::GetDevToolsURL(Profile* profile,
                                    FrontendType frontend_type,
                                    const std::string& frontend_url,
                                    bool can_dock,
                                    const std::string& panel,
                                    bool has_other_clients,
                                    bool browser_connection) {}

// static
DevToolsWindow* DevToolsWindow::FindDevToolsWindow(
    DevToolsAgentHost* agent_host) {}

// static
DevToolsWindow* DevToolsWindow::AsDevToolsWindow(
    content::WebContents* web_contents) {}

// static
DevToolsWindow* DevToolsWindow::AsDevToolsWindow(Browser* browser) {}

WebContents* DevToolsWindow::OpenURLFromTab(
    WebContents* source,
    const content::OpenURLParams& params,
    base::OnceCallback<void(content::NavigationHandle&)>
        navigation_handle_callback) {}

WebContents* DevToolsWindow::OpenURLFromInspectedTab(
    const content::OpenURLParams& params) {}

void DevToolsWindow::ActivateContents(WebContents* contents) {}

WebContents* DevToolsWindow::AddNewContents(
    WebContents* source,
    std::unique_ptr<WebContents> new_contents,
    const GURL& target_url,
    WindowOpenDisposition disposition,
    const blink::mojom::WindowFeatures& window_features,
    bool user_gesture,
    bool* was_blocked) {}

void DevToolsWindow::WebContentsCreated(WebContents* source_contents,
                                        int opener_render_process_id,
                                        int opener_render_frame_id,
                                        const std::string& frame_name,
                                        const GURL& target_url,
                                        WebContents* new_contents) {}

void DevToolsWindow::CloseContents(WebContents* source) {}

void DevToolsWindow::ContentsZoomChange(bool zoom_in) {}

void DevToolsWindow::BeforeUnloadFired(WebContents* tab,
                                       bool proceed,
                                       bool* proceed_to_fire_unload) {}

content::KeyboardEventProcessingResult DevToolsWindow::PreHandleKeyboardEvent(
    WebContents* source,
    const input::NativeWebKeyboardEvent& event) {}

bool DevToolsWindow::HandleKeyboardEvent(
    WebContents* source,
    const input::NativeWebKeyboardEvent& event) {}

content::JavaScriptDialogManager* DevToolsWindow::GetJavaScriptDialogManager(
    WebContents* source) {}

std::unique_ptr<content::EyeDropper> DevToolsWindow::OpenEyeDropper(
    content::RenderFrameHost* render_frame_host,
    content::EyeDropperListener* listener) {}

void DevToolsWindow::RunFileChooser(
    content::RenderFrameHost* render_frame_host,
    scoped_refptr<content::FileSelectListener> listener,
    const blink::mojom::FileChooserParams& params) {}

bool DevToolsWindow::PreHandleGestureEvent(
    WebContents* source,
    const blink::WebGestureEvent& event) {}

void DevToolsWindow::ActivateWindow() {}

void DevToolsWindow::CloseWindow() {}

void DevToolsWindow::Close(DevToolsClosedByAction closed_by) {}

void DevToolsWindow::Inspect(scoped_refptr<content::DevToolsAgentHost> host) {}

void DevToolsWindow::SetInspectedPageBounds(const gfx::Rect& rect) {}

void DevToolsWindow::InspectElementCompleted() {}

void DevToolsWindow::SetIsDocked(bool dock_requested) {}

int DevToolsWindow::GetDockStateForLogging() {}

int DevToolsWindow::GetOpenedByForLogging() {}

int DevToolsWindow::GetClosedByForLogging() {}

void DevToolsWindow::OpenInNewTab(const GURL& url) {}

void DevToolsWindow::OpenInNewTab(const std::string& url) {}

void DevToolsWindow::OpenSearchResultsInNewTab(const std::string& query) {}

void DevToolsWindow::SetWhitelistedShortcuts(
    const std::string& message) {}

void DevToolsWindow::SetEyeDropperActive(bool active) {}

void DevToolsWindow::ColorPickedInEyeDropper(int r, int g, int b, int a) {}

void DevToolsWindow::InspectedContentsClosing() {}

infobars::ContentInfoBarManager* DevToolsWindow::GetInfoBarManager() {}

void DevToolsWindow::RenderProcessGone(bool crashed) {}

void DevToolsWindow::ShowCertificateViewer(const std::string& cert_chain) {}

void DevToolsWindow::OnLoadCompleted() {}

void DevToolsWindow::ReadyForTest() {}

void DevToolsWindow::ConnectionReady() {}

void DevToolsWindow::SetOpenNewWindowForPopups(bool value) {}

void DevToolsWindow::CreateDevToolsBrowser() {}

BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() {}

void DevToolsWindow::DoAction(const DevToolsToggleAction& action) {}

void DevToolsWindow::UpdateBrowserToolbar() {}

void DevToolsWindow::UpdateBrowserWindow() {}

WebContents* DevToolsWindow::GetInspectedWebContents() {}

void DevToolsWindow::LoadCompleted() {}

void DevToolsWindow::SetLoadCompletedCallback(base::OnceClosure closure) {}

bool DevToolsWindow::ForwardKeyboardEvent(
    const input::NativeWebKeyboardEvent& event) {}

bool DevToolsWindow::ReloadInspectedWebContents(bool bypass_cache) {}

void DevToolsWindow::RegisterModalDialogManager(Browser* browser) {}

void DevToolsWindow::OnLocaleChanged() {}

void DevToolsWindow::OverrideAndSyncDevToolsRendererPrefs() {}

void DevToolsWindow::MaybeShowSharedProcessInfobar() {}

void DevToolsWindow::OnInfoBarRemoved(infobars::InfoBar* infobar,
                                      bool animate) {}

void DevToolsWindow::PrimaryPageChanged(content::Page& page) {}