123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841 |
- // Copyright (c) 2012 The Chromium Authors. All rights reserved.
- // Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE-CHROMIUM file.
- #include <utility>
- #include "brightray/browser/inspectable_web_contents_impl.h"
- #include "base/guid.h"
- #include "base/json/json_reader.h"
- #include "base/json/json_writer.h"
- #include "base/metrics/histogram.h"
- #include "base/strings/pattern.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/values.h"
- #include "brightray/browser/browser_client.h"
- #include "brightray/browser/browser_context.h"
- #include "brightray/browser/browser_main_parts.h"
- #include "brightray/browser/inspectable_web_contents_delegate.h"
- #include "brightray/browser/inspectable_web_contents_view.h"
- #include "brightray/browser/inspectable_web_contents_view_delegate.h"
- #include "components/prefs/pref_registry_simple.h"
- #include "components/prefs/pref_service.h"
- #include "components/prefs/scoped_user_pref_update.h"
- #include "content/public/browser/browser_thread.h"
- #include "content/public/browser/host_zoom_map.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/common/user_agent.h"
- #include "ipc/ipc_channel.h"
- #include "net/http/http_response_headers.h"
- #include "net/url_request/url_fetcher.h"
- #include "net/url_request/url_fetcher_response_writer.h"
- #include "ui/display/display.h"
- #include "ui/display/screen.h"
- namespace brightray {
- namespace {
- const double kPresetZoomFactors[] = {0.25, 0.333, 0.5, 0.666, 0.75, 0.9,
- 1.0, 1.1, 1.25, 1.5, 1.75, 2.0,
- 2.5, 3.0, 4.0, 5.0};
- const char kChromeUIDevToolsURL[] =
- "chrome-devtools://devtools/bundled/inspector.html?"
- "remoteBase=%s&"
- "can_dock=%s&"
- "toolbarColor=rgba(223,223,223,1)&"
- "textColor=rgba(0,0,0,1)&"
- "experiments=true";
- const char kChromeUIDevToolsRemoteFrontendBase[] =
- "https://chrome-devtools-frontend.appspot.com/";
- const char kChromeUIDevToolsRemoteFrontendPath[] = "serve_file";
- const char kDevToolsBoundsPref[] = "brightray.devtools.bounds";
- const char kDevToolsZoomPref[] = "brightray.devtools.zoom";
- const char kDevToolsPreferences[] = "brightray.devtools.preferences";
- const char kFrontendHostId[] = "id";
- const char kFrontendHostMethod[] = "method";
- const char kFrontendHostParams[] = "params";
- const char kTitleFormat[] = "Developer Tools - %s";
- const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;
- void RectToDictionary(const gfx::Rect& bounds, base::DictionaryValue* dict) {
- dict->SetInteger("x", bounds.x());
- dict->SetInteger("y", bounds.y());
- dict->SetInteger("width", bounds.width());
- dict->SetInteger("height", bounds.height());
- }
- void DictionaryToRect(const base::DictionaryValue& dict, gfx::Rect* bounds) {
- int x = 0, y = 0, width = 800, height = 600;
- dict.GetInteger("x", &x);
- dict.GetInteger("y", &y);
- dict.GetInteger("width", &width);
- dict.GetInteger("height", &height);
- *bounds = gfx::Rect(x, y, width, height);
- }
- bool IsPointInRect(const gfx::Point& point, const gfx::Rect& rect) {
- return point.x() > rect.x() && point.x() < (rect.width() + rect.x()) &&
- point.y() > rect.y() && point.y() < (rect.height() + rect.y());
- }
- bool IsPointInScreen(const gfx::Point& point) {
- for (const auto& display : display::Screen::GetScreen()->GetAllDisplays()) {
- if (IsPointInRect(point, display.bounds()))
- return true;
- }
- return false;
- }
- void SetZoomLevelForWebContents(content::WebContents* web_contents,
- double level) {
- content::HostZoomMap::SetZoomLevel(web_contents, level);
- }
- double GetNextZoomLevel(double level, bool out) {
- double factor = content::ZoomLevelToZoomFactor(level);
- size_t size = arraysize(kPresetZoomFactors);
- for (size_t i = 0; i < size; ++i) {
- if (!content::ZoomValuesEqual(kPresetZoomFactors[i], factor))
- continue;
- if (out && i > 0)
- return content::ZoomFactorToZoomLevel(kPresetZoomFactors[i - 1]);
- if (!out && i != size - 1)
- return content::ZoomFactorToZoomLevel(kPresetZoomFactors[i + 1]);
- }
- return level;
- }
- GURL GetRemoteBaseURL() {
- return GURL(base::StringPrintf("%s%s/%s/",
- kChromeUIDevToolsRemoteFrontendBase,
- kChromeUIDevToolsRemoteFrontendPath,
- content::GetWebKitRevision().c_str()));
- }
- GURL GetDevToolsURL(bool can_dock) {
- auto url_string = base::StringPrintf(kChromeUIDevToolsURL,
- GetRemoteBaseURL().spec().c_str(),
- can_dock ? "true" : "");
- return GURL(url_string);
- }
- // ResponseWriter -------------------------------------------------------------
- class ResponseWriter : public net::URLFetcherResponseWriter {
- public:
- ResponseWriter(base::WeakPtr<InspectableWebContentsImpl> bindings,
- int stream_id);
- ~ResponseWriter() override;
- // URLFetcherResponseWriter overrides:
- int Initialize(const net::CompletionCallback& callback) override;
- int Write(net::IOBuffer* buffer,
- int num_bytes,
- const net::CompletionCallback& callback) override;
- int Finish(int net_error, const net::CompletionCallback& callback) override;
- private:
- base::WeakPtr<InspectableWebContentsImpl> bindings_;
- int stream_id_;
- DISALLOW_COPY_AND_ASSIGN(ResponseWriter);
- };
- ResponseWriter::ResponseWriter(
- base::WeakPtr<InspectableWebContentsImpl> bindings,
- int stream_id)
- : bindings_(bindings), stream_id_(stream_id) {}
- ResponseWriter::~ResponseWriter() {}
- int ResponseWriter::Initialize(const net::CompletionCallback& callback) {
- return net::OK;
- }
- int ResponseWriter::Write(net::IOBuffer* buffer,
- int num_bytes,
- const net::CompletionCallback& callback) {
- auto* id = new base::Value(stream_id_);
- base::Value* chunk = new base::Value(std::string(buffer->data(), num_bytes));
- content::BrowserThread::PostTask(
- content::BrowserThread::UI, FROM_HERE,
- base::BindOnce(&InspectableWebContentsImpl::CallClientFunction, bindings_,
- "DevToolsAPI.streamWrite", base::Owned(id),
- base::Owned(chunk), nullptr));
- return num_bytes;
- }
- int ResponseWriter::Finish(int net_error,
- const net::CompletionCallback& callback) {
- return net::OK;
- }
- } // namespace
- // Implemented separately on each platform.
- InspectableWebContentsView* CreateInspectableContentsView(
- InspectableWebContentsImpl* inspectable_web_contents_impl);
- void InspectableWebContentsImpl::RegisterPrefs(PrefRegistrySimple* registry) {
- std::unique_ptr<base::DictionaryValue> bounds_dict(new base::DictionaryValue);
- RectToDictionary(gfx::Rect(0, 0, 800, 600), bounds_dict.get());
- registry->RegisterDictionaryPref(kDevToolsBoundsPref, std::move(bounds_dict));
- registry->RegisterDoublePref(kDevToolsZoomPref, 0.);
- registry->RegisterDictionaryPref(kDevToolsPreferences);
- }
- InspectableWebContentsImpl::InspectableWebContentsImpl(
- content::WebContents* web_contents)
- : frontend_loaded_(false),
- can_dock_(true),
- delegate_(nullptr),
- web_contents_(web_contents),
- weak_factory_(this) {
- auto* context =
- static_cast<BrowserContext*>(web_contents_->GetBrowserContext());
- pref_service_ = context->prefs();
- auto* bounds_dict = pref_service_->GetDictionary(kDevToolsBoundsPref);
- if (bounds_dict) {
- DictionaryToRect(*bounds_dict, &devtools_bounds_);
- // Sometimes the devtools window is out of screen or has too small size.
- if (devtools_bounds_.height() < 100 || devtools_bounds_.width() < 100) {
- devtools_bounds_.set_height(600);
- devtools_bounds_.set_width(800);
- }
- if (!IsPointInScreen(devtools_bounds_.origin())) {
- gfx::Rect display;
- if (web_contents->GetNativeView()) {
- display = display::Screen::GetScreen()
- ->GetDisplayNearestView(web_contents->GetNativeView())
- .bounds();
- } else {
- display = display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
- }
- devtools_bounds_.set_x(display.x() +
- (display.width() - devtools_bounds_.width()) / 2);
- devtools_bounds_.set_y(
- display.y() + (display.height() - devtools_bounds_.height()) / 2);
- }
- }
- view_.reset(CreateInspectableContentsView(this));
- }
- InspectableWebContentsImpl::~InspectableWebContentsImpl() {
- // Unsubscribe from devtools and Clean up resources.
- if (GetDevToolsWebContents()) {
- if (managed_devtools_web_contents_)
- managed_devtools_web_contents_->SetDelegate(nullptr);
- // Calling this also unsubscribes the observer, so WebContentsDestroyed
- // won't be called again.
- WebContentsDestroyed();
- }
- // Let destructor destroy managed_devtools_web_contents_.
- }
- InspectableWebContentsView* InspectableWebContentsImpl::GetView() const {
- return view_.get();
- }
- content::WebContents* InspectableWebContentsImpl::GetWebContents() const {
- return web_contents_.get();
- }
- content::WebContents* InspectableWebContentsImpl::GetDevToolsWebContents()
- const {
- if (external_devtools_web_contents_)
- return external_devtools_web_contents_;
- else
- return managed_devtools_web_contents_.get();
- }
- void InspectableWebContentsImpl::InspectElement(int x, int y) {
- if (agent_host_.get())
- agent_host_->InspectElement(this, x, y);
- }
- void InspectableWebContentsImpl::SetDelegate(
- InspectableWebContentsDelegate* delegate) {
- delegate_ = delegate;
- }
- InspectableWebContentsDelegate* InspectableWebContentsImpl::GetDelegate()
- const {
- return delegate_;
- }
- void InspectableWebContentsImpl::SetDockState(const std::string& state) {
- if (state == "detach") {
- can_dock_ = false;
- } else {
- can_dock_ = true;
- dock_state_ = state;
- }
- }
- void InspectableWebContentsImpl::SetDevToolsWebContents(
- content::WebContents* devtools) {
- if (!managed_devtools_web_contents_)
- external_devtools_web_contents_ = devtools;
- }
- void InspectableWebContentsImpl::ShowDevTools() {
- if (embedder_message_dispatcher_) {
- if (managed_devtools_web_contents_)
- view_->ShowDevTools();
- return;
- }
- // Show devtools only after it has done loading, this is to make sure the
- // SetIsDocked is called *BEFORE* ShowDevTools.
- embedder_message_dispatcher_.reset(
- DevToolsEmbedderMessageDispatcher::CreateForDevToolsFrontend(this));
- if (!external_devtools_web_contents_) { // no external devtools
- managed_devtools_web_contents_.reset(
- content::WebContents::Create(content::WebContents::CreateParams(
- web_contents_->GetBrowserContext())));
- managed_devtools_web_contents_->SetDelegate(this);
- }
- Observe(GetDevToolsWebContents());
- AttachTo(content::DevToolsAgentHost::GetOrCreateFor(web_contents_.get()));
- GetDevToolsWebContents()->GetController().LoadURL(
- GetDevToolsURL(can_dock_), content::Referrer(),
- ui::PAGE_TRANSITION_AUTO_TOPLEVEL, std::string());
- }
- void InspectableWebContentsImpl::CloseDevTools() {
- if (GetDevToolsWebContents()) {
- frontend_loaded_ = false;
- if (managed_devtools_web_contents_) {
- view_->CloseDevTools();
- managed_devtools_web_contents_.reset();
- }
- embedder_message_dispatcher_.reset();
- web_contents_->Focus();
- }
- }
- bool InspectableWebContentsImpl::IsDevToolsViewShowing() {
- return managed_devtools_web_contents_ && view_->IsDevToolsViewShowing();
- }
- void InspectableWebContentsImpl::AttachTo(
- scoped_refptr<content::DevToolsAgentHost> host) {
- if (agent_host_.get())
- Detach();
- agent_host_ = std::move(host);
- // Terminate existing debugging connections and start debugging.
- agent_host_->ForceAttachClient(this);
- }
- void InspectableWebContentsImpl::Detach() {
- if (agent_host_.get())
- agent_host_->DetachClient(this);
- agent_host_ = nullptr;
- }
- void InspectableWebContentsImpl::CallClientFunction(
- const std::string& function_name,
- const base::Value* arg1,
- const base::Value* arg2,
- const base::Value* arg3) {
- if (!GetDevToolsWebContents())
- return;
- std::string javascript = function_name + "(";
- if (arg1) {
- std::string json;
- base::JSONWriter::Write(*arg1, &json);
- javascript.append(json);
- if (arg2) {
- base::JSONWriter::Write(*arg2, &json);
- javascript.append(", ").append(json);
- if (arg3) {
- base::JSONWriter::Write(*arg3, &json);
- javascript.append(", ").append(json);
- }
- }
- }
- javascript.append(");");
- GetDevToolsWebContents()->GetMainFrame()->ExecuteJavaScript(
- base::UTF8ToUTF16(javascript));
- }
- gfx::Rect InspectableWebContentsImpl::GetDevToolsBounds() const {
- return devtools_bounds_;
- }
- void InspectableWebContentsImpl::SaveDevToolsBounds(const gfx::Rect& bounds) {
- base::DictionaryValue bounds_dict;
- RectToDictionary(bounds, &bounds_dict);
- pref_service_->Set(kDevToolsBoundsPref, bounds_dict);
- devtools_bounds_ = bounds;
- }
- double InspectableWebContentsImpl::GetDevToolsZoomLevel() const {
- return pref_service_->GetDouble(kDevToolsZoomPref);
- }
- void InspectableWebContentsImpl::UpdateDevToolsZoomLevel(double level) {
- pref_service_->SetDouble(kDevToolsZoomPref, level);
- }
- void InspectableWebContentsImpl::ActivateWindow() {
- // Set the zoom level.
- SetZoomLevelForWebContents(GetDevToolsWebContents(), GetDevToolsZoomLevel());
- }
- void InspectableWebContentsImpl::CloseWindow() {
- GetDevToolsWebContents()->DispatchBeforeUnload();
- }
- void InspectableWebContentsImpl::LoadCompleted() {
- frontend_loaded_ = true;
- if (managed_devtools_web_contents_)
- view_->ShowDevTools();
- // If the devtools can dock, "SetIsDocked" will be called by devtools itself.
- if (!can_dock_) {
- SetIsDocked(DispatchCallback(), false);
- } else {
- if (dock_state_.empty()) {
- const base::DictionaryValue* prefs =
- pref_service_->GetDictionary(kDevToolsPreferences);
- std::string current_dock_state;
- prefs->GetString("currentDockState", ¤t_dock_state);
- base::RemoveChars(current_dock_state, "\"", &dock_state_);
- }
- base::string16 javascript = base::UTF8ToUTF16(
- "Components.dockController.setDockSide(\"" + dock_state_ + "\");");
- GetDevToolsWebContents()->GetMainFrame()->ExecuteJavaScript(javascript);
- }
- if (view_->GetDelegate())
- view_->GetDelegate()->DevToolsOpened();
- }
- void InspectableWebContentsImpl::SetInspectedPageBounds(const gfx::Rect& rect) {
- DevToolsContentsResizingStrategy strategy(rect);
- if (contents_resizing_strategy_.Equals(strategy))
- return;
- contents_resizing_strategy_.CopyFrom(strategy);
- if (managed_devtools_web_contents_)
- view_->SetContentsResizingStrategy(contents_resizing_strategy_);
- }
- void InspectableWebContentsImpl::InspectElementCompleted() {}
- void InspectableWebContentsImpl::InspectedURLChanged(const std::string& url) {
- if (managed_devtools_web_contents_)
- view_->SetTitle(
- base::UTF8ToUTF16(base::StringPrintf(kTitleFormat, url.c_str())));
- }
- void InspectableWebContentsImpl::LoadNetworkResource(
- const DispatchCallback& callback,
- const std::string& url,
- const std::string& headers,
- int stream_id) {
- GURL gurl(url);
- if (!gurl.is_valid()) {
- base::DictionaryValue response;
- response.SetInteger("statusCode", 404);
- callback.Run(&response);
- return;
- }
- auto* browser_context = static_cast<BrowserContext*>(
- GetDevToolsWebContents()->GetBrowserContext());
- net::URLFetcher* fetcher =
- (net::URLFetcher::Create(gurl, net::URLFetcher::GET, this)).release();
- pending_requests_[fetcher] = callback;
- fetcher->SetRequestContext(browser_context->url_request_context_getter());
- fetcher->SetExtraRequestHeaders(headers);
- fetcher->SaveResponseWithWriter(
- std::unique_ptr<net::URLFetcherResponseWriter>(
- new ResponseWriter(weak_factory_.GetWeakPtr(), stream_id)));
- fetcher->Start();
- }
- void InspectableWebContentsImpl::SetIsDocked(const DispatchCallback& callback,
- bool docked) {
- if (managed_devtools_web_contents_)
- view_->SetIsDocked(docked);
- if (!callback.is_null())
- callback.Run(nullptr);
- }
- void InspectableWebContentsImpl::OpenInNewTab(const std::string& url) {}
- void InspectableWebContentsImpl::SaveToFile(const std::string& url,
- const std::string& content,
- bool save_as) {
- if (delegate_)
- delegate_->DevToolsSaveToFile(url, content, save_as);
- }
- void InspectableWebContentsImpl::AppendToFile(const std::string& url,
- const std::string& content) {
- if (delegate_)
- delegate_->DevToolsAppendToFile(url, content);
- }
- void InspectableWebContentsImpl::RequestFileSystems() {
- if (delegate_)
- delegate_->DevToolsRequestFileSystems();
- }
- void InspectableWebContentsImpl::AddFileSystem(
- const std::string& file_system_path) {
- if (delegate_)
- delegate_->DevToolsAddFileSystem(
- base::FilePath::FromUTF8Unsafe(file_system_path));
- }
- void InspectableWebContentsImpl::RemoveFileSystem(
- const std::string& file_system_path) {
- if (delegate_)
- delegate_->DevToolsRemoveFileSystem(
- base::FilePath::FromUTF8Unsafe(file_system_path));
- }
- void InspectableWebContentsImpl::UpgradeDraggedFileSystemPermissions(
- const std::string& file_system_url) {}
- void InspectableWebContentsImpl::IndexPath(
- int request_id,
- const std::string& file_system_path) {
- if (delegate_)
- delegate_->DevToolsIndexPath(request_id, file_system_path);
- }
- void InspectableWebContentsImpl::StopIndexing(int request_id) {
- if (delegate_)
- delegate_->DevToolsStopIndexing(request_id);
- }
- void InspectableWebContentsImpl::SearchInPath(
- int request_id,
- const std::string& file_system_path,
- const std::string& query) {
- if (delegate_)
- delegate_->DevToolsSearchInPath(request_id, file_system_path, query);
- }
- void InspectableWebContentsImpl::SetWhitelistedShortcuts(
- const std::string& message) {}
- void InspectableWebContentsImpl::ZoomIn() {
- double new_level = GetNextZoomLevel(GetDevToolsZoomLevel(), false);
- SetZoomLevelForWebContents(GetDevToolsWebContents(), new_level);
- UpdateDevToolsZoomLevel(new_level);
- }
- void InspectableWebContentsImpl::ZoomOut() {
- double new_level = GetNextZoomLevel(GetDevToolsZoomLevel(), true);
- SetZoomLevelForWebContents(GetDevToolsWebContents(), new_level);
- UpdateDevToolsZoomLevel(new_level);
- }
- void InspectableWebContentsImpl::ResetZoom() {
- SetZoomLevelForWebContents(GetDevToolsWebContents(), 0.);
- UpdateDevToolsZoomLevel(0.);
- }
- void InspectableWebContentsImpl::SetDevicesUpdatesEnabled(bool enabled) {}
- void InspectableWebContentsImpl::DispatchProtocolMessageFromDevToolsFrontend(
- const std::string& message) {
- // If the devtools wants to reload the page, hijack the message and handle it
- // to the delegate.
- if (base::MatchPattern(message,
- "{\"id\":*,"
- "\"method\":\"Page.reload\","
- "\"params\":*}")) {
- if (delegate_)
- delegate_->DevToolsReloadPage();
- return;
- }
- if (agent_host_.get())
- agent_host_->DispatchProtocolMessage(this, message);
- }
- void InspectableWebContentsImpl::SendJsonRequest(
- const DispatchCallback& callback,
- const std::string& browser_id,
- const std::string& url) {
- callback.Run(nullptr);
- }
- void InspectableWebContentsImpl::GetPreferences(
- const DispatchCallback& callback) {
- const base::DictionaryValue* prefs =
- pref_service_->GetDictionary(kDevToolsPreferences);
- callback.Run(prefs);
- }
- void InspectableWebContentsImpl::SetPreference(const std::string& name,
- const std::string& value) {
- DictionaryPrefUpdate update(pref_service_, kDevToolsPreferences);
- update.Get()->SetKey(name, base::Value(value));
- }
- void InspectableWebContentsImpl::RemovePreference(const std::string& name) {
- DictionaryPrefUpdate update(pref_service_, kDevToolsPreferences);
- update.Get()->RemoveWithoutPathExpansion(name, nullptr);
- }
- void InspectableWebContentsImpl::ClearPreferences() {
- DictionaryPrefUpdate update(pref_service_, kDevToolsPreferences);
- update.Get()->Clear();
- }
- void InspectableWebContentsImpl::RegisterExtensionsAPI(
- const std::string& origin,
- const std::string& script) {
- extensions_api_[origin + "/"] = script;
- }
- void InspectableWebContentsImpl::HandleMessageFromDevToolsFrontend(
- const std::string& message) {
- std::string method;
- base::ListValue empty_params;
- base::ListValue* params = &empty_params;
- base::DictionaryValue* dict = nullptr;
- std::unique_ptr<base::Value> parsed_message(base::JSONReader::Read(message));
- if (!parsed_message || !parsed_message->GetAsDictionary(&dict) ||
- !dict->GetString(kFrontendHostMethod, &method) ||
- (dict->HasKey(kFrontendHostParams) &&
- !dict->GetList(kFrontendHostParams, ¶ms))) {
- LOG(ERROR) << "Invalid message was sent to embedder: " << message;
- return;
- }
- int id = 0;
- dict->GetInteger(kFrontendHostId, &id);
- embedder_message_dispatcher_->Dispatch(
- base::Bind(&InspectableWebContentsImpl::SendMessageAck,
- weak_factory_.GetWeakPtr(), id),
- method, params);
- }
- void InspectableWebContentsImpl::DispatchProtocolMessage(
- content::DevToolsAgentHost* agent_host,
- const std::string& message) {
- if (!frontend_loaded_)
- return;
- if (message.length() < kMaxMessageChunkSize) {
- base::string16 javascript =
- base::UTF8ToUTF16("DevToolsAPI.dispatchMessage(" + message + ");");
- GetDevToolsWebContents()->GetMainFrame()->ExecuteJavaScript(javascript);
- return;
- }
- base::Value total_size(static_cast<int>(message.length()));
- for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) {
- base::Value message_value(message.substr(pos, kMaxMessageChunkSize));
- CallClientFunction("DevToolsAPI.dispatchMessageChunk", &message_value,
- pos ? nullptr : &total_size, nullptr);
- }
- }
- void InspectableWebContentsImpl::AgentHostClosed(
- content::DevToolsAgentHost* agent_host,
- bool replaced) {}
- void InspectableWebContentsImpl::RenderFrameHostChanged(
- content::RenderFrameHost* old_host,
- content::RenderFrameHost* new_host) {
- if (new_host->GetParent())
- return;
- frontend_host_.reset(content::DevToolsFrontendHost::Create(
- new_host,
- base::Bind(&InspectableWebContentsImpl::HandleMessageFromDevToolsFrontend,
- weak_factory_.GetWeakPtr())));
- }
- void InspectableWebContentsImpl::WebContentsDestroyed() {
- frontend_loaded_ = false;
- external_devtools_web_contents_ = nullptr;
- Observe(nullptr);
- Detach();
- embedder_message_dispatcher_.reset();
- for (const auto& pair : pending_requests_)
- delete pair.first;
- if (view_ && view_->GetDelegate())
- view_->GetDelegate()->DevToolsClosed();
- }
- bool InspectableWebContentsImpl::DidAddMessageToConsole(
- content::WebContents* source,
- int32_t level,
- const base::string16& message,
- int32_t line_no,
- const base::string16& source_id) {
- logging::LogMessage("CONSOLE", line_no, level).stream()
- << "\"" << message << "\", source: " << source_id << " (" << line_no
- << ")";
- return true;
- }
- bool InspectableWebContentsImpl::ShouldCreateWebContents(
- content::WebContents* web_contents,
- content::RenderFrameHost* opener,
- content::SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
- content::mojom::WindowContainerType window_container_type,
- const GURL& opener_url,
- const std::string& frame_name,
- const GURL& target_url,
- const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) {
- return false;
- }
- void InspectableWebContentsImpl::HandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- auto* delegate = web_contents_->GetDelegate();
- if (delegate)
- delegate->HandleKeyboardEvent(source, event);
- }
- void InspectableWebContentsImpl::CloseContents(content::WebContents* source) {
- // This is where the devtools closes itself (by clicking the x button).
- CloseDevTools();
- }
- content::ColorChooser* InspectableWebContentsImpl::OpenColorChooser(
- content::WebContents* source,
- SkColor color,
- const std::vector<content::ColorSuggestion>& suggestions) {
- auto* delegate = web_contents_->GetDelegate();
- if (delegate)
- return delegate->OpenColorChooser(source, color, suggestions);
- return nullptr;
- }
- void InspectableWebContentsImpl::RunFileChooser(
- content::RenderFrameHost* render_frame_host,
- const content::FileChooserParams& params) {
- auto* delegate = web_contents_->GetDelegate();
- if (delegate)
- delegate->RunFileChooser(render_frame_host, params);
- }
- void InspectableWebContentsImpl::EnumerateDirectory(
- content::WebContents* source,
- int request_id,
- const base::FilePath& path) {
- auto* delegate = web_contents_->GetDelegate();
- if (delegate)
- delegate->EnumerateDirectory(source, request_id, path);
- }
- void InspectableWebContentsImpl::OnWebContentsFocused(
- content::RenderWidgetHost* render_widget_host) {
- #if defined(TOOLKIT_VIEWS)
- if (view_->GetDelegate())
- view_->GetDelegate()->DevToolsFocused();
- #endif
- }
- void InspectableWebContentsImpl::ReadyToCommitNavigation(
- content::NavigationHandle* navigation_handle) {
- if (navigation_handle->IsInMainFrame()) {
- if (navigation_handle->GetRenderFrameHost() ==
- GetDevToolsWebContents()->GetMainFrame() &&
- frontend_host_) {
- return;
- }
- frontend_host_.reset(content::DevToolsFrontendHost::Create(
- web_contents()->GetMainFrame(),
- base::Bind(
- &InspectableWebContentsImpl::HandleMessageFromDevToolsFrontend,
- base::Unretained(this))));
- return;
- }
- }
- void InspectableWebContentsImpl::DidFinishNavigation(
- content::NavigationHandle* navigation_handle) {
- if (navigation_handle->IsInMainFrame() ||
- !navigation_handle->GetURL().SchemeIs("chrome-extension") ||
- !navigation_handle->HasCommitted())
- return;
- content::RenderFrameHost* frame = navigation_handle->GetRenderFrameHost();
- auto origin = navigation_handle->GetURL().GetOrigin().spec();
- auto it = extensions_api_.find(origin);
- if (it == extensions_api_.end())
- return;
- // Injected Script from devtools frontend doesn't expose chrome,
- // most likely bug in chromium.
- base::ReplaceFirstSubstringAfterOffset(&it->second, 0, "var chrome",
- "var chrome = window.chrome ");
- auto script = base::StringPrintf("%s(\"%s\")", it->second.c_str(),
- base::GenerateGUID().c_str());
- // Invoking content::DevToolsFrontendHost::SetupExtensionsAPI(frame, script);
- // should be enough, but it seems to be a noop currently.
- frame->ExecuteJavaScriptForTests(base::UTF8ToUTF16(script));
- }
- void InspectableWebContentsImpl::OnURLFetchComplete(
- const net::URLFetcher* source) {
- DCHECK(source);
- auto it = pending_requests_.find(source);
- DCHECK(it != pending_requests_.end());
- base::DictionaryValue response;
- net::HttpResponseHeaders* rh = source->GetResponseHeaders();
- response.SetInteger("statusCode", rh ? rh->response_code() : 200);
- {
- auto headers = std::make_unique<base::DictionaryValue>();
- size_t iterator = 0;
- std::string name;
- std::string value;
- while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value))
- headers->SetString(name, value);
- response.Set("headers", std::move(headers));
- }
- it->second.Run(&response);
- pending_requests_.erase(it);
- delete source;
- }
- void InspectableWebContentsImpl::SendMessageAck(int request_id,
- const base::Value* arg) {
- base::Value id_value(request_id);
- CallClientFunction("DevToolsAPI.embedderMessageAck", &id_value, arg, nullptr);
- }
- } // namespace brightray
|