summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Negyokru <negyokru@inf.u-szeged.hu>2022-09-28 14:54:59 +0200
committerMichael BrĂ¼ning <michael.bruning@qt.io>2023-02-22 21:16:28 +0100
commit73acb3b3e8e74b087409f856746c3454c717dfa7 (patch)
treeb4a7770bfcebc6700e2c9430ee99bb21af27356b /src
parent442e347f592d389ff664f3b1cae466c3e2506d78 (diff)
downloadqtwebengine-73acb3b3e8e74b087409f856746c3454c717dfa7.tar.gz
Refactor devtools frontend
Use chrome's UIBindings and message dispatcher. Pick-to: 6.5 Change-Id: I580b551153de8a0d34b70199c17a50df67237e73 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/core/configure/BUILD.root.gn.in33
-rw-r--r--src/core/devtools_frontend_qt.cpp680
-rw-r--r--src/core/devtools_frontend_qt.h111
-rw-r--r--src/core/pref_service_adapter.cpp9
4 files changed, 130 insertions, 703 deletions
diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in
index 005bfa447..2c6b15d4c 100644
--- a/src/core/configure/BUILD.root.gn.in
+++ b/src/core/configure/BUILD.root.gn.in
@@ -216,6 +216,32 @@ source_set("qtwebengine_spellcheck_sources") {
}
}
+source_set("devtools_sources") {
+ configs += [ ":cpp17_config" ]
+ deps = [
+ "//components/zoom",
+ "//third_party/blink/public/mojom:mojom_platform",
+ ]
+ sources = [
+ "//chrome/browser/devtools/devtools_eye_dropper.cc",
+ "//chrome/browser/devtools/devtools_eye_dropper.h",
+ "//chrome/browser/devtools/devtools_file_helper.cc",
+ "//chrome/browser/devtools/devtools_file_helper.h",
+ "//chrome/browser/devtools/devtools_file_system_indexer.cc",
+ "//chrome/browser/devtools/devtools_file_system_indexer.h",
+ "//chrome/browser/devtools/devtools_file_watcher.cc",
+ "//chrome/browser/devtools/devtools_file_watcher.h",
+ "//chrome/browser/devtools/url_constants.cc",
+ "//chrome/browser/devtools/url_constants.h",
+ "//chrome/browser/devtools/devtools_ui_bindings.cc",
+ "//chrome/browser/devtools/devtools_ui_bindings.h",
+ "//chrome/browser/devtools/devtools_settings.cc",
+ "//chrome/browser/devtools/devtools_settings.h",
+ "//chrome/browser/devtools/devtools_embedder_message_dispatcher.cc",
+ "//chrome/browser/devtools/devtools_embedder_message_dispatcher.h",
+ ]
+}
+
source_set("qtwebengine_sources") {
configs += [
":cpp17_config",
@@ -223,6 +249,7 @@ source_set("qtwebengine_sources") {
"//third_party/boringssl:external_config",
]
deps = [
+ ":devtools_sources",
"//build:branding_buildflags",
"//build/config/chromebox_for_meetings:buildflags",
"//chrome/browser:dev_ui_browser_resources_grit",
@@ -246,12 +273,6 @@ source_set("qtwebengine_sources") {
sources = [
"//chrome/browser/accessibility/accessibility_ui.cc",
"//chrome/browser/accessibility/accessibility_ui.h",
- "//chrome/browser/devtools/devtools_eye_dropper.cc",
- "//chrome/browser/devtools/devtools_eye_dropper.h",
- "//chrome/browser/devtools/devtools_file_helper.cc",
- "//chrome/browser/devtools/devtools_file_helper.h",
- "//chrome/browser/devtools/devtools_file_watcher.cc",
- "//chrome/browser/devtools/devtools_file_watcher.h",
"//chrome/browser/gcm/gcm_product_util.cc",
"//chrome/browser/gcm/gcm_product_util.h",
"//chrome/browser/gcm/gcm_profile_service_factory.cc",
diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp
index 73698e263..8ac834c9d 100644
--- a/src/core/devtools_frontend_qt.cpp
+++ b/src/core/devtools_frontend_qt.cpp
@@ -8,171 +8,42 @@
#include "devtools_frontend_qt.h"
-#include "profile_adapter.h"
#include "profile_qt.h"
+#include "profile_adapter.h"
#include "web_contents_adapter.h"
+#include "web_contents_delegate_qt.h"
-#include "base/base64.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/json/string_escape.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
#include "chrome/browser/devtools/devtools_eye_dropper.h"
-#include "chrome/browser/devtools/devtools_file_helper.h"
-#include "chrome/common/url_constants.h"
-#include "components/prefs/in_memory_pref_store.h"
-#include "components/prefs/json_pref_store.h"
+#include "chrome/browser/devtools/devtools_ui_bindings.h"
#include "content/public/browser/browser_context.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/devtools_frontend_host.h"
-#include "content/public/browser/file_url_loader.h"
+#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/shared_cors_origin_access_list.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/common/url_utils.h"
-#include "ipc/ipc_channel.h"
-#include "net/http/http_response_headers.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "services/network/public/cpp/simple_url_loader.h"
-#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/site_instance.h"
+#include "url/gurl.h"
using namespace QtWebEngineCore;
namespace {
-constexpr char kScreencastEnabled[] = "screencastEnabled";
-
-base::DictionaryValue CreateFileSystemValue(DevToolsFileHelper::FileSystem fileSystem)
-{
- base::DictionaryValue fileSystemValue;
- fileSystemValue.SetStringKey("type", fileSystem.type);
- fileSystemValue.SetStringKey("fileSystemName", fileSystem.file_system_name);
- fileSystemValue.SetStringKey("rootURL", fileSystem.root_url);
- fileSystemValue.SetStringKey("fileSystemPath", fileSystem.file_system_path);
- return fileSystemValue;
-}
-
-base::DictionaryValue BuildObjectForResponse(const net::HttpResponseHeaders *rh, bool success,
- int netError)
-{
- base::DictionaryValue response;
- int responseCode = 200;
- if (rh) {
- responseCode = rh->response_code();
- } else if (!success) {
- // In case of no headers, assume file:// URL and failed to load
- responseCode = 404;
- }
- response.SetInteger("statusCode", responseCode);
- response.SetInteger("netError", netError);
- response.SetString("netErrorName", net::ErrorToString(netError));
-
- auto headers = std::make_unique<base::DictionaryValue>();
- size_t iterator = 0;
- std::string name;
- std::string value;
- // TODO(caseq): this probably needs to handle duplicate header names
- // correctly by folding them.
- while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value))
- headers->SetString(name, value);
-
- response.Set("headers", std::move(headers));
- return response;
-}
-
static std::string GetFrontendURL()
{
return "devtools://devtools/bundled/inspector.html";
}
-
-} // namespace
+} // namespace
namespace QtWebEngineCore {
-class DevToolsFrontendQt::NetworkResourceLoader
- : public network::SimpleURLLoaderStreamConsumer {
-public:
- NetworkResourceLoader(int stream_id,
- int request_id,
- DevToolsFrontendQt *bindings,
- std::unique_ptr<network::SimpleURLLoader> loader,
- network::mojom::URLLoaderFactory *url_loader_factory)
- : stream_id_(stream_id),
- request_id_(request_id),
- bindings_(bindings),
- loader_(std::move(loader))
- {
- loader_->SetOnResponseStartedCallback(base::BindOnce(
- &NetworkResourceLoader::OnResponseStarted, base::Unretained(this)));
- loader_->DownloadAsStream(url_loader_factory, this);
- }
-
-private:
- void OnResponseStarted(const GURL &final_url,
- const network::mojom::URLResponseHead &response_head)
- {
- response_headers_ = response_head.headers;
- }
-
- void OnDataReceived(base::StringPiece chunk, base::OnceClosure resume) override
- {
- base::Value chunkValue;
-
- bool encoded = !base::IsStringUTF8(chunk);
- if (encoded) {
- std::string encoded_string;
- base::Base64Encode(chunk, &encoded_string);
- chunkValue = base::Value(std::move(encoded_string));
- } else {
- chunkValue = base::Value(chunk);
- }
- base::Value id(stream_id_);
- base::Value encodedValue(encoded);
-
- bindings_->CallClientFunction("DevToolsAPI", "streamWrite", std::move(id), std::move(chunkValue), std::move(encodedValue));
- std::move(resume).Run();
- }
-
- void OnComplete(bool success) override
- {
- auto response = BuildObjectForResponse(response_headers_.get(), success, loader_->NetError());
- bindings_->SendMessageAck(request_id_, std::move(response));
- bindings_->m_loaders.erase(bindings_->m_loaders.find(this));
- }
-
- void OnRetry(base::OnceClosure start_retry) override { NOTREACHED(); }
-
- const int stream_id_;
- const int request_id_;
- DevToolsFrontendQt *const bindings_;
- std::unique_ptr<network::SimpleURLLoader> loader_;
- scoped_refptr<net::HttpResponseHeaders> response_headers_;
-};
-
-// This constant should be in sync with
-// the constant at devtools_ui_bindings.cc.
-const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
-
// static
-DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> frontendAdapter, content::WebContents *inspectedContents)
+DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> frontendAdapter,
+ content::WebContents *inspectedContents)
{
DCHECK(frontendAdapter);
DCHECK(inspectedContents);
if (!frontendAdapter->isInitialized()) {
- scoped_refptr<content::SiteInstance> site =
- content::SiteInstance::CreateForURL(frontendAdapter->profile(), GURL(GetFrontendURL()));
+ scoped_refptr<content::SiteInstance> site = content::SiteInstance::CreateForURL(
+ frontendAdapter->profile(), GURL(GetFrontendURL()));
frontendAdapter->initialize(site.get());
}
@@ -184,13 +55,15 @@ DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter>
return nullptr;
}
- DevToolsFrontendQt *devtoolsFrontend = new DevToolsFrontendQt(frontendAdapter, inspectedContents);
+ DevToolsFrontendQt *devtoolsFrontend =
+ new DevToolsFrontendQt(frontendAdapter, inspectedContents);
if (contents->GetURL() == GURL(GetFrontendURL())) {
contents->GetController().Reload(content::ReloadType::ORIGINAL_REQUEST_URL, false);
- } else {
+ } else {
content::NavigationController::LoadURLParams loadParams((GURL(GetFrontendURL())));
- loadParams.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FROM_API);
+ loadParams.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_TOPLEVEL
+ | ui::PAGE_TRANSITION_FROM_API);
contents->GetController().LoadURLWithParams(loadParams);
}
@@ -201,25 +74,12 @@ DevToolsFrontendQt::DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webCon
content::WebContents *inspectedContents)
: content::WebContentsObserver(webContentsAdapter->webContents())
, m_frontendAdapter(webContentsAdapter)
- , m_inspectedAdapter(static_cast<WebContentsDelegateQt *>(inspectedContents->GetDelegate())
- ->webContentsAdapter())
, m_inspectedContents(inspectedContents)
- , m_inspect_element_at_x(-1)
- , m_inspect_element_at_y(-1)
- , m_prefStore(nullptr)
- , m_weakFactory(this)
+ , m_bindings(new DevToolsUIBindings(webContentsAdapter->webContents()))
{
- // We use a separate prefstore than one in ProfileQt, because that one is in-memory only, and this
- // needs to be stored or it will show introduction text on every load.
- if (webContentsAdapter->profileAdapter()->isOffTheRecord())
- m_prefStore = scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore());
- else
- CreateJsonPreferences(false);
-
- m_frontendDelegate = static_cast<WebContentsDelegateQt *>(webContentsAdapter->webContents()->GetDelegate());
- m_fileHelper = std::make_unique<DevToolsFileHelper>(
- webContentsAdapter->webContents(),
- static_cast<Profile *>(webContentsAdapter->webContents()->GetBrowserContext()), this);
+ // bindings take ownership over devtools
+ m_bindings->SetDelegate(this);
+ m_bindings->AttachTo(content::DevToolsAgentHost::GetOrCreateFor(m_inspectedContents));
}
DevToolsFrontendQt::~DevToolsFrontendQt()
@@ -230,7 +90,7 @@ DevToolsFrontendQt::~DevToolsFrontendQt()
void DevToolsFrontendQt::Activate()
{
- m_frontendDelegate->ActivateContents(web_contents());
+ web_contents()->GetDelegate()->ActivateContents(web_contents());
}
void DevToolsFrontendQt::Focus()
@@ -240,12 +100,11 @@ void DevToolsFrontendQt::Focus()
void DevToolsFrontendQt::InspectElementAt(int x, int y)
{
- if (m_agentHost)
- m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), x, y);
- else {
- m_inspect_element_at_x = x;
- m_inspect_element_at_y = y;
- }
+ if (!m_inspectedContents)
+ return;
+ scoped_refptr<content::DevToolsAgentHost> agent(
+ content::DevToolsAgentHost::GetOrCreateFor(m_inspectedContents));
+ agent->InspectElement(m_inspectedContents->GetFocusedFrame(), x, y);
}
void DevToolsFrontendQt::Close()
@@ -256,314 +115,54 @@ void DevToolsFrontendQt::Close()
void DevToolsFrontendQt::DisconnectFromTarget()
{
- if (!m_agentHost)
- return;
- m_agentHost->DetachClient(this);
- m_agentHost = nullptr;
+ m_bindings->Detach();
}
-void DevToolsFrontendQt::ReadyToCommitNavigation(content::NavigationHandle *navigationHandle)
+WebContentsDelegateQt *DevToolsFrontendQt::frontendDelegate() const
{
- // ShellDevToolsFrontend does this in RenderViewCreated,
- // but that doesn't work for us for some reason.
- content::RenderFrameHost *frame = navigationHandle->GetRenderFrameHost();
- if (navigationHandle->IsInMainFrame()) {
- // If the frontend for some reason goes to some place other than devtools, stop the bindings
- if (navigationHandle->GetURL() != GetFrontendURL())
- m_frontendHost.reset(nullptr);
- else if (!m_frontendHost)
- m_frontendHost = content::DevToolsFrontendHost::Create(
- frame,
- base::BindRepeating(&DevToolsFrontendQt::HandleMessageFromDevToolsFrontend,
- base::Unretained(this)));
- }
+ return static_cast<WebContentsDelegateQt *>(web_contents()->GetDelegate());
}
-void DevToolsFrontendQt::DocumentOnLoadCompletedInPrimaryMainFrame()
+void DevToolsFrontendQt::ColorPickedInEyeDropper(int r, int g, int b, int a)
{
- if (!m_inspectedContents)
- return;
- // Don't call AttachClient multiple times for the same DevToolsAgentHost.
- // Otherwise it will call AgentHostClosed which closes the DevTools window.
- // This may happen in cases where the DevTools content fails to load.
- scoped_refptr<content::DevToolsAgentHost> agent_host =
- content::DevToolsAgentHost::GetOrCreateFor(m_inspectedContents);
- if (agent_host != m_agentHost) {
- if (m_agentHost)
- m_agentHost->DetachClient(this);
- m_agentHost = agent_host;
- m_agentHost->AttachClient(this);
- if (m_inspect_element_at_x != -1) {
- m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), m_inspect_element_at_x, m_inspect_element_at_y);
- m_inspect_element_at_x = -1;
- m_inspect_element_at_y = -1;
- }
- }
+ base::DictionaryValue color;
+ color.SetInteger("r", r);
+ color.SetInteger("g", g);
+ color.SetInteger("b", b);
+ color.SetInteger("a", a);
+ m_bindings->CallClientMethod("DevToolsAPI", "eyeDropperPickedColor", std::move(color));
}
+// content::WebContentsObserver implementation
void DevToolsFrontendQt::WebContentsDestroyed()
{
- if (m_inspectedAdapter)
- m_inspectedAdapter->devToolsFrontendDestroyed(this);
-
- if (m_agentHost) {
- m_agentHost->DetachClient(this);
- m_agentHost = nullptr;
- }
- delete this;
-}
-
-void DevToolsFrontendQt::SetPreference(const std::string &name, const std::string &value)
-{
- DCHECK(m_prefStore);
- m_prefStore->SetValue(name, base::Value(value), 0);
-}
+ WebContentsAdapter *inspectedAdapter =
+ static_cast<WebContentsDelegateQt *>(m_inspectedContents->GetDelegate())
+ ->webContentsAdapter();
+ if (inspectedAdapter)
+ inspectedAdapter->devToolsFrontendDestroyed(this);
-void DevToolsFrontendQt::RemovePreference(const std::string &name)
-{
- DCHECK(m_prefStore);
- m_prefStore->RemoveValue(name, 0);
+ delete m_bindings; // it will call ~DevToolsFrontendQt()
}
-void DevToolsFrontendQt::ClearPreferences()
+// DevToolsUIBindings::Delegate implementation
+void DevToolsFrontendQt::ActivateWindow()
{
- ProfileQt *profile = static_cast<ProfileQt *>(web_contents()->GetBrowserContext());
- if (profile->IsOffTheRecord() || profile->profileAdapter()->storageName().isEmpty())
- m_prefStore = scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore());
- else
- CreateJsonPreferences(true);
+ web_contents()->Focus();
}
-void DevToolsFrontendQt::CreateJsonPreferences(bool clear)
+void DevToolsFrontendQt::InspectElementCompleted()
{
- content::BrowserContext *browserContext = web_contents()->GetBrowserContext();
- DCHECK(!browserContext->IsOffTheRecord());
- JsonPrefStore *jsonPrefStore = new JsonPrefStore(
- browserContext->GetPath().Append(FILE_PATH_LITERAL("devtoolsprefs.json")));
- // We effectively clear the preferences by not calling ReadPrefs
- base::ScopedAllowBlockingForTesting allowBlocking;
- if (!clear)
- jsonPrefStore->ReadPrefs();
-
- m_prefStore = scoped_refptr<PersistentPrefStore>(jsonPrefStore);
+ m_bindings->CallClientMethod("DevToolsAPI", "setUseSoftMenu", base::Value(true));
}
-void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(base::Value::Dict message)
+void DevToolsFrontendQt::OpenInNewTab(const std::string &url)
{
- const base::Value *method_ptr = nullptr;
- base::Value *params_value = nullptr;
- method_ptr = message.Find("method");
- params_value = message.Find("params");
- if (!method_ptr || !method_ptr->is_string() || (params_value && !params_value->is_list())) {
- LOG(ERROR) << "Invalid message was sent to embedder: " << message;
- return;
- }
- base::Value empty_params(base::Value::Type::LIST);
- if (!params_value)
- params_value = &empty_params;
-
- int request_id = message.Find("id")->GetIfInt().value_or(0);
- const std::string &method = *method_ptr->GetIfString();
- base::Value::List *paramsPtr;
- if (params_value)
- paramsPtr = params_value->GetIfList();
- base::Value::List &params = *paramsPtr;
-
- if (method == "dispatchProtocolMessage" && params.size() == 1) {
- const std::string *protocol_message = params[0].GetIfString();
- if (!protocol_message)
- return;
- if (m_agentHost)
- m_agentHost->DispatchProtocolMessage(this, base::as_bytes(base::make_span(*protocol_message)));
- } else if (method == "loadCompleted") {
- web_contents()->GetPrimaryMainFrame()->ExecuteJavaScript(u"DevToolsAPI.setUseSoftMenu(true);",
- base::NullCallback());
- } else if (method == "loadNetworkResource" && params.size() == 3) {
- // TODO(pfeldman): handle some of the embedder messages in content.
- const std::string *url = params[0].GetIfString();
- const std::string *headers = params[1].GetIfString();
- absl::optional<int> stream_id = params[2].GetIfInt();
- if (!url || !headers || !stream_id.has_value()) {
- return;
- }
-
- GURL gurl(*url);
- if (!gurl.is_valid()) {
- base::DictionaryValue response;
- response.SetInteger("statusCode", 404);
- response.SetBoolean("urlValid", false);
- SendMessageAck(request_id, std::move(response));
- return;
- }
-
- net::NetworkTrafficAnnotationTag traffic_annotation =
- net::DefineNetworkTrafficAnnotation(
- "devtools_handle_front_end_messages", R"(
- semantics {
- sender: "Developer Tools"
- description:
- "When user opens Developer Tools, the browser may fetch "
- "additional resources from the network to enrich the debugging "
- "experience (e.g. source map resources)."
- trigger: "User opens Developer Tools to debug a web page."
- data: "Any resources requested by Developer Tools."
- destination: OTHER
- }
- policy {
- cookies_allowed: YES
- cookies_store: "user"
- setting:
- "It's not possible to disable this feature from settings."
- chrome_policy {
- DeveloperToolsAvailability {
- policy_options {mode: MANDATORY}
- DeveloperToolsAvailability: 2
- }
- }
- })");
- auto resource_request = std::make_unique<network::ResourceRequest>();
- resource_request->url = gurl;
- // TODO(caseq): this preserves behavior of URLFetcher-based implementation.
- // We really need to pass proper first party origin from the front-end.
- resource_request->site_for_cookies = net::SiteForCookies::FromUrl(gurl);
- resource_request->headers.AddHeadersFromString(*headers);
-
- mojo::Remote<network::mojom::URLLoaderFactory> file_url_loader_factory;
- scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory;
- network::mojom::URLLoaderFactory *url_loader_factory;
- if (gurl.SchemeIsFile()) {
- file_url_loader_factory.Bind(content::CreateFileURLLoaderFactory(base::FilePath(), nullptr));
- url_loader_factory = file_url_loader_factory.get();
- } else if (content::HasWebUIScheme(gurl)) {
- base::DictionaryValue response;
- response.SetInteger("statusCode", 403);
- SendMessageAck(request_id, std::move(response));
- return;
- } else {
- auto *partition = web_contents()->GetBrowserContext()->GetStoragePartitionForUrl(gurl);
- network_url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
- url_loader_factory = network_url_loader_factory.get();
- }
- auto simple_url_loader = network::SimpleURLLoader::Create(
- std::move(resource_request), traffic_annotation);
- auto resource_loader = std::make_unique<NetworkResourceLoader>(
- *stream_id, request_id, this, std::move(simple_url_loader),
- url_loader_factory);
- m_loaders.insert(std::move(resource_loader));
- return;
- } else if (method == "getPreferences") {
- // Screencast is enabled by default if it's not present in the preference store.
- if (!m_prefStore->GetValue(kScreencastEnabled, NULL))
- SetPreference(kScreencastEnabled, "false");
-
- m_preferences = std::move(m_prefStore->GetValues());
- SendMessageAck(request_id, base::Value(m_preferences.Clone()));
- return;
- } else if (method == "setPreference" && params.size() >= 2) {
- const std::string *name = params[0].GetIfString();
- const std::string *value = params[1].GetIfString();
- if (!name || !value)
- return;
- SetPreference(*name, *value);
- } else if (method == "removePreference" && params.size() >= 1) {
- const std::string *name = params[0].GetIfString();
- if (!name)
- return;
- RemovePreference(*name);
- } else if (method == "clearPreferences") {
- ClearPreferences();
- } else if (method == "requestFileSystems") {
- base::ListValue fileSystemsValue;
- for (auto const &fileSystem : m_fileHelper->GetFileSystems())
- fileSystemsValue.Append(CreateFileSystemValue(fileSystem));
- CallClientFunction("DevToolsAPI", "fileSystemsLoaded", std::move(fileSystemsValue));
- } else if (method == "reattach") {
- if (!m_agentHost)
- return;
- m_agentHost->DetachClient(this);
- m_agentHost->AttachClient(this);
- } else if (method == "inspectedURLChanged" && params.size() >= 1) {
- const std::string *url = params[0].GetIfString();
- if (!url)
- return;
- const std::string kHttpPrefix = "http://";
- const std::string kHttpsPrefix = "https://";
- const std::string simplified_url =
- base::StartsWith(*url, kHttpsPrefix, base::CompareCase::SENSITIVE)
- ? url->substr(kHttpsPrefix.length())
- : base::StartsWith(*url, kHttpPrefix, base::CompareCase::SENSITIVE)
- ? url->substr(kHttpPrefix.length())
- : *url;
- // DevTools UI is not localized.
- web_contents()->UpdateTitleForEntry(web_contents()->GetController().GetActiveEntry(),
- base::UTF8ToUTF16(
- base::StringPrintf("DevTools - %s", simplified_url.c_str())));
- } else if (method == "openInNewTab" && params.size() >= 1) {
- const std::string *urlString = params[0].GetIfString();
- if (!urlString)
- return;
- GURL url(*urlString);
- if (!url.is_valid())
- return;
- content::OpenURLParams openParams(GURL(url),
- content::Referrer(),
- WindowOpenDisposition::NEW_FOREGROUND_TAB,
- ui::PAGE_TRANSITION_LINK,
- false);
- // OpenURL will (via WebContentsDelegateQt::OpenURLFromTab) call
- // application code, which may decide to close this devtools view (see
- // quicknanobrowser for example).
- //
- // Chromium always calls SendMessageAck through a callback bound to a
- // WeakPtr, we do the same here, except without the callback.
- base::WeakPtr<DevToolsFrontendQt> weakThis = m_weakFactory.GetWeakPtr();
- web_contents()->OpenURL(openParams);
- if (!weakThis)
- return;
- } else if (method == "bringToFront") {
- Activate();
- } else if (method == "closeWindow") {
- web_contents()->Close();
- } else if (method == "setEyeDropperActive" && params.size() == 1) {
- absl::optional<bool> active = params[0].GetIfBool();
- if (!active)
- return;
- SetEyeDropperActive(*active);
- } else if (method == "save" && params.size() == 3) {
- const std::string *url = params[0].GetIfString();
- const std::string *content = params[1].GetIfString();
- absl::optional<bool> saveAs = params[2].GetIfBool();
- if (!url || !content || !saveAs)
- return;
- SaveToFile(*url, *content, *saveAs);
- } else if (method == "append" && params.size() == 2) {
- const std::string *url = params[0].GetIfString();
- const std::string *content = params[1].GetIfString();
- if (!url || !content)
- return;
- AppendToFile(*url, *content);
- } else if (method == "addFileSystem" && params.size() == 1) {
- const std::string *type = params[0].GetIfString();
- if (!type)
- return;
- AddFileSystem(*type);
- } else if (method == "removeFileSystem" && params.size() == 1) {
- const std::string *fileSystemPath = params[0].GetIfString();
- if (!fileSystemPath)
- return;
- RemoveFileSystem(*fileSystemPath);
- } else if (method == "upgradeDraggedFileSystemPermissions" && params.size() == 1) {
- const std::string *fileSystemUrl = params[0].GetIfString();
- if (!fileSystemUrl)
- return;
- UpgradeDraggedFileSystemPermissions(*fileSystemUrl);
- } else {
- VLOG(1) << "Unimplemented devtools method: " << message;
- return;
- }
+ content::OpenURLParams params(GURL(url), content::Referrer(),
+ WindowOpenDisposition::NEW_FOREGROUND_TAB,
+ ui::PAGE_TRANSITION_LINK, false);
- if (request_id)
- SendMessageAck(request_id, base::Value());
+ m_inspectedContents->OpenURL(params);
}
void DevToolsFrontendQt::SetEyeDropperActive(bool active)
@@ -572,67 +171,14 @@ void DevToolsFrontendQt::SetEyeDropperActive(bool active)
return;
if (active) {
m_eyeDropper.reset(new DevToolsEyeDropper(
- m_inspectedContents,
- base::BindRepeating(&DevToolsFrontendQt::ColorPickedInEyeDropper,
- base::Unretained(this))));
+ m_inspectedContents,
+ base::BindRepeating(&DevToolsFrontendQt::ColorPickedInEyeDropper,
+ base::Unretained(this))));
} else {
m_eyeDropper.reset();
}
}
-void DevToolsFrontendQt::ColorPickedInEyeDropper(int r, int g, int b, int a)
-{
- base::DictionaryValue color;
- color.SetInteger("r", r);
- color.SetInteger("g", g);
- color.SetInteger("b", b);
- color.SetInteger("a", a);
- CallClientFunction("DevToolsAPI", "eyeDropperPickedColor", std::move(color));
-}
-
-void DevToolsFrontendQt::DispatchProtocolMessage(content::DevToolsAgentHost *agentHost, base::span<const uint8_t> message)
-{
- Q_UNUSED(agentHost);
- base::StringPiece str_message(reinterpret_cast<const char*>(message.data()), message.size());
-
- if (str_message.length() < kMaxMessageChunkSize) {
- CallClientFunction("DevToolsAPI", "dispatchMessage",
- base::Value(std::string(str_message)));
- } else {
- size_t total_size = str_message.length();
- for (size_t pos = 0; pos < str_message.length(); pos += kMaxMessageChunkSize) {
- base::StringPiece str_message_chunk = str_message.substr(pos, kMaxMessageChunkSize);
-
- CallClientFunction("DevToolsAPI", "dispatchMessageChunk",
- base::Value(std::string(str_message_chunk)),
- base::Value(base::NumberToString(pos ? 0 : total_size)));
- }
- }
-}
-
-void DevToolsFrontendQt::CallClientFunction(const std::string &object_name,
- const std::string &method_name,
- base::Value arg1, base::Value arg2, base::Value arg3,
- base::OnceCallback<void(base::Value)> cb)
-
-{
- base::Value::List arguments;
- if (!arg1.is_none()) {
- arguments.Append(std::move(arg1));
- if (!arg2.is_none()) {
- arguments.Append(std::move(arg2));
- if (!arg3.is_none()) {
- arguments.Append(std::move(arg3));
- }
- }
- }
- web_contents()->GetPrimaryMainFrame()->ExecuteJavaScriptMethod(base::ASCIIToUTF16(object_name),
- base::ASCIIToUTF16(method_name),
- std::move(arguments),
- std::move(cb));
-
-}
-
// static
bool DevToolsFrontendQt::IsValidFrontendURL(const GURL &url)
{
@@ -642,117 +188,9 @@ bool DevToolsFrontendQt::IsValidFrontendURL(const GURL &url)
return url.spec() == GetFrontendURL();
}
-void DevToolsFrontendQt::SendMessageAck(int request_id, base::Value arg)
-{
- base::Value id_value(request_id);
- CallClientFunction("DevToolsAPI", "embedderMessageAck", std::move(id_value), std::move(arg));
-}
-
-void DevToolsFrontendQt::AgentHostClosed(content::DevToolsAgentHost *agentHost)
-{
- DCHECK(agentHost == m_agentHost.get());
- m_agentHost = nullptr;
- m_inspectedContents = nullptr;
- m_inspectedAdapter = nullptr;
- Close();
-}
-
-void DevToolsFrontendQt::SaveToFile(const std::string &url, const std::string &content, bool saveAs)
-{
- m_fileHelper->Save(
- url, content, saveAs,
- base::BindOnce(&DevToolsFrontendQt::FileSavedAs, m_weakFactory.GetWeakPtr(), url),
- base::BindOnce(&DevToolsFrontendQt::CanceledFileSaveAs, m_weakFactory.GetWeakPtr(),
- url));
-}
-
-void DevToolsFrontendQt::FileSavedAs(const std::string &url, const std::string &fileSystemPath)
-{
- CallClientFunction("DevToolsAPI", "savedURL", base::Value(url), base::Value(fileSystemPath));
-}
-
-void DevToolsFrontendQt::CanceledFileSaveAs(const std::string &url)
-{
- CallClientFunction("DevToolsAPI", "canceledSaveURL", base::Value(url));
-}
-
-void DevToolsFrontendQt::AppendToFile(const std::string &url, const std::string &content)
-{
- m_fileHelper->Append(
- url, content,
- base::BindOnce(&DevToolsFrontendQt::AppendedTo, m_weakFactory.GetWeakPtr(), url));
-}
-
-void DevToolsFrontendQt::AppendedTo(const std::string &url)
-{
- CallClientFunction("DevToolsAPI", "appendedToURL", base::Value(url));
-}
-
-void DevToolsFrontendQt::AddFileSystem(const std::string &type)
-{
- CHECK(IsValidFrontendURL(web_contents()->GetLastCommittedURL()) && m_frontendHost);
- m_fileHelper->AddFileSystem(type, base::NullCallback());
-}
-
-void DevToolsFrontendQt::UpgradeDraggedFileSystemPermissions(const std::string &fileSystemUrl)
-{
- CHECK(IsValidFrontendURL(web_contents()->GetLastCommittedURL()) && m_frontendHost);
- m_fileHelper->UpgradeDraggedFileSystemPermissions(fileSystemUrl, base::NullCallback());
-}
-
-void DevToolsFrontendQt::RemoveFileSystem(const std::string &fileSystemPath)
-{
- CHECK(IsValidFrontendURL(web_contents()->GetLastCommittedURL()) && m_frontendHost);
- m_fileHelper->RemoveFileSystem(fileSystemPath);
-}
-
-// DevToolsFileHelper::Delegate implementation
-// based on chrome/browser/devtools/devtools_ui_bindings.cc
-void DevToolsFrontendQt::FileSystemAdded(const std::string &error,
- const DevToolsFileHelper::FileSystem *file_system)
-{
- if (file_system) {
- CallClientFunction("DevToolsAPI", "fileSystemAdded", base::Value(error),
- CreateFileSystemValue(*file_system));
- } else {
- CallClientFunction("DevToolsAPI", "fileSystemAdded", base::Value(error));
- }
-}
-
-void DevToolsFrontendQt::FileSystemRemoved(const std::string &file_system_path)
+void DevToolsFrontendQt::InspectedContentsClosing()
{
- CallClientFunction("DevToolsAPI", "fileSystemRemoved", base::Value(file_system_path));
-}
-
-void DevToolsFrontendQt::FilePathsChanged(const std::vector<std::string> &changed_paths,
- const std::vector<std::string> &added_paths,
- const std::vector<std::string> &removed_paths)
-{
- const int kMaxPathsPerMessage = 1000;
- size_t changed_index = 0;
- size_t added_index = 0;
- size_t removed_index = 0;
- // Dispatch limited amount of file paths in a time to avoid
- // IPC max message size limit. See https://crbug.com/797817.
- while (changed_index < changed_paths.size() || added_index < added_paths.size()
- || removed_index < removed_paths.size()) {
- int budget = kMaxPathsPerMessage;
- base::ListValue changed, added, removed;
- while (budget > 0 && changed_index < changed_paths.size()) {
- changed.Append(changed_paths[changed_index++]);
- --budget;
- }
- while (budget > 0 && added_index < added_paths.size()) {
- added.Append(added_paths[added_index++]);
- --budget;
- }
- while (budget > 0 && removed_index < removed_paths.size()) {
- removed.Append(removed_paths[removed_index++]);
- --budget;
- }
- CallClientFunction("DevToolsAPI", "fileSystemFilesChangedAddedRemoved", std::move(changed),
- std::move(added), std::move(removed));
- }
+ web_contents()->ClosePage();
}
} // namespace QtWebEngineCore
diff --git a/src/core/devtools_frontend_qt.h b/src/core/devtools_frontend_qt.h
index 5c1237bbc..3b722c9ad 100644
--- a/src/core/devtools_frontend_qt.h
+++ b/src/core/devtools_frontend_qt.h
@@ -11,31 +11,24 @@
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/weak_ptr.h"
-#include "chrome/browser/devtools/devtools_file_helper.h"
-#include "content/public/browser/devtools_agent_host.h"
+#include "chrome/browser/devtools/devtools_ui_bindings.h"
#include "content/public/browser/web_contents_observer.h"
-namespace base {
-class Value;
-}
+class DevToolsEyeDropper;
namespace content {
-class DevToolsFrontendHost;
-class NavigationHandle;
+class DevToolsAgentHost;
class WebContents;
-} // namespace content
-
-class DevToolsEyeDropper;
-class PersistentPrefStore;
+} // namespace content
namespace QtWebEngineCore {
+class WebContentsAdapter;
-class DevToolsFrontendQt : public content::WebContentsObserver,
- public content::DevToolsAgentHostClient,
- public DevToolsFileHelper::Delegate
+class DevToolsFrontendQt : public DevToolsUIBindings::Delegate, public content::WebContentsObserver
{
public:
- static DevToolsFrontendQt *Show(QSharedPointer<WebContentsAdapter> frontendAdapter, content::WebContents *inspectedContents);
+ static DevToolsFrontendQt *Show(QSharedPointer<WebContentsAdapter> frontendAdapter,
+ content::WebContents *inspectedContents);
void Activate();
void Focus();
@@ -44,82 +37,48 @@ public:
void DisconnectFromTarget();
- void CallClientFunction(const std::string &object_name,
- const std::string &method_name,
- base::Value arg1 = {},
- base::Value arg2 = {},
- base::Value arg3 = {},
- base::OnceCallback<void(base::Value)> cb = base::NullCallback());
-
- WebContentsDelegateQt *frontendDelegate() const
- {
- return m_frontendDelegate;
- }
+ WebContentsDelegateQt *frontendDelegate() const;
static bool IsValidFrontendURL(const GURL &url);
protected:
- DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webContentsAdapter, content::WebContents *inspectedContents);
+ DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webContentsAdapter,
+ content::WebContents *inspectedContents);
~DevToolsFrontendQt() override;
- // content::DevToolsAgentHostClient implementation.
- void AgentHostClosed(content::DevToolsAgentHost* agent_host) override;
- void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host, base::span<const uint8_t> message) override;
-
- void SetPreferences(const std::string& json);
- void HandleMessageFromDevToolsFrontend(base::Value::Dict message);
-
private:
- // WebContentsObserver overrides
- void ReadyToCommitNavigation(content::NavigationHandle* navigation_handle) override;
- void DocumentOnLoadCompletedInPrimaryMainFrame() override;
- void WebContentsDestroyed() override;
-
- // DevToolsFileHelper::Delegate overrides.
- void FileSystemAdded(const std::string &error,
- const DevToolsFileHelper::FileSystem *file_system) override;
- void FileSystemRemoved(const std::string &file_system_path) override;
- void FilePathsChanged(const std::vector<std::string> &changed_paths,
- const std::vector<std::string> &added_paths,
- const std::vector<std::string> &removed_paths) override;
-
- void SendMessageAck(int request_id, base::Value arg1);
- void SetPreference(const std::string &name, const std::string &value);
- void RemovePreference(const std::string &name);
- void ClearPreferences();
- void CreateJsonPreferences(bool clear);
- void SetEyeDropperActive(bool active);
void ColorPickedInEyeDropper(int r, int g, int b, int a);
- void SaveToFile(const std::string &url, const std::string &content, bool saveAs);
- void FileSavedAs(const std::string &url, const std::string &fileSystemPath);
- void CanceledFileSaveAs(const std::string &url);
- void AppendToFile(const std::string &url, const std::string &content);
- void AppendedTo(const std::string &url);
- void AddFileSystem(const std::string &type);
- void UpgradeDraggedFileSystemPermissions(const std::string &fileSystem);
- void RemoveFileSystem(const std::string &fileSystemPath);
+ // content::WebContentsObserver overrides
+ void WebContentsDestroyed() override;
+
+ // DevToolsUIBindings::Delegate overrides
+ void ActivateWindow() override;
+ void InspectElementCompleted() override;
+ void SetEyeDropperActive(bool active) override;
+ void OpenInNewTab(const std::string &url) override;
+ void InspectedContentsClosing() override;
+
+ void CloseWindow() override{};
+ void Inspect(scoped_refptr<content::DevToolsAgentHost>) override{};
+ void SetInspectedPageBounds(const gfx::Rect &) override{};
+ void SetIsDocked(bool) override{};
+ void SetWhitelistedShortcuts(const std::string &) override{};
+ void OpenNodeFrontend() override{};
+ void OnLoadCompleted() override{};
+ void ReadyForTest() override{};
+ void ConnectionReady() override{};
+ void SetOpenNewWindowForPopups(bool) override{};
+ void RenderProcessGone(bool) override{};
+ void ShowCertificateViewer(const std::string &) override{};
// We shouldn't be keeping it alive
QWeakPointer<WebContentsAdapter> m_frontendAdapter;
- WebContentsAdapter *m_inspectedAdapter;
- WebContentsDelegateQt *m_frontendDelegate;
content::WebContents *m_inspectedContents;
- scoped_refptr<content::DevToolsAgentHost> m_agentHost;
- int m_inspect_element_at_x;
- int m_inspect_element_at_y;
- std::unique_ptr<content::DevToolsFrontendHost> m_frontendHost;
std::unique_ptr<DevToolsEyeDropper> m_eyeDropper;
- std::unique_ptr<DevToolsFileHelper> m_fileHelper;
-
- class NetworkResourceLoader;
- std::set<std::unique_ptr<NetworkResourceLoader>, base::UniquePtrComparator> m_loaders;
-
- base::Value::Dict m_preferences;
- scoped_refptr<PersistentPrefStore> m_prefStore;
- base::WeakPtrFactory<DevToolsFrontendQt> m_weakFactory;
+ DevToolsUIBindings *m_bindings;
};
} // namespace QtWebEngineCore
-#endif // DEVTOOLS_FRONTEND_QT_H
+#endif // DEVTOOLS_FRONTEND_QT_H
diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp
index 34251880e..b6cfc2714 100644
--- a/src/core/pref_service_adapter.cpp
+++ b/src/core/pref_service_adapter.cpp
@@ -26,6 +26,9 @@
#include "extensions/buildflags/buildflags.h"
#include "content/public/browser/browser_context.h"
+#include "components/pref_registry/pref_registry_syncable.h"
+#include "chrome/browser/devtools/devtools_settings.h"
+
#if QT_CONFIG(webengine_spellchecker)
#include "chrome/browser/spellchecker/spellcheck_service.h"
#include "components/spellcheck/browser/pref_names.h"
@@ -126,6 +129,12 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter)
// devtools
registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths);
registry->RegisterDictionaryPref(prefs::kDevToolsEditedFiles);
+ registry->RegisterDictionaryPref(prefs::kDevToolsPreferences);
+ registry->RegisterBooleanPref(prefs::kDevToolsSyncPreferences, false);
+ // even if kDevToolsSyncPreferences is disabled, the js frontend tries to access
+ // these two. E.g.: 'clearPreferences', that is overridden by devtools_compatibility.js
+ registry->RegisterDictionaryPref(prefs::kDevToolsSyncedPreferencesSyncDisabled);
+ registry->RegisterDictionaryPref(prefs::kDevToolsSyncedPreferencesSyncEnabled);
registry->RegisterStringPref(prefs::kGoogleServicesSigninScopedDeviceId, std::string());
registry->RegisterStringPref(prefs::kGaiaCookieLastListAccountsData, std::string());