• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include "libcef/browser/devtools/devtools_manager.h"
6 
7 #include "libcef/browser/devtools/devtools_controller.h"
8 #include "libcef/browser/devtools/devtools_frontend.h"
9 #include "libcef/features/runtime.h"
10 
11 #include "content/public/browser/web_contents.h"
12 
13 namespace {
14 
15 // May be created on any thread but will be destroyed on the UI thread.
16 class CefDevToolsRegistrationImpl : public CefRegistration,
17                                     public CefDevToolsController::Observer {
18  public:
CefDevToolsRegistrationImpl(CefRefPtr<CefDevToolsMessageObserver> observer)19   explicit CefDevToolsRegistrationImpl(
20       CefRefPtr<CefDevToolsMessageObserver> observer)
21       : observer_(observer) {
22     DCHECK(observer_);
23   }
24 
~CefDevToolsRegistrationImpl()25   ~CefDevToolsRegistrationImpl() override {
26     CEF_REQUIRE_UIT();
27 
28     // May be null if OnDevToolsControllerDestroyed was called.
29     if (!controller_)
30       return;
31 
32     controller_->RemoveObserver(this);
33   }
34 
Initialize(CefBrowserHostBase * browser,base::WeakPtr<CefDevToolsController> controller)35   void Initialize(CefBrowserHostBase* browser,
36                   base::WeakPtr<CefDevToolsController> controller) {
37     CEF_REQUIRE_UIT();
38     DCHECK(browser && controller);
39     DCHECK(!browser_ && !controller_);
40     browser_ = browser;
41     controller_ = controller;
42 
43     controller_->AddObserver(this);
44   }
45 
46  private:
47   // CefDevToolsController::Observer methods:
OnDevToolsMessage(const base::StringPiece & message)48   bool OnDevToolsMessage(const base::StringPiece& message) override {
49     CEF_REQUIRE_UIT();
50     return observer_->OnDevToolsMessage(browser_, message.data(),
51                                         message.size());
52   }
53 
OnDevToolsMethodResult(int message_id,bool success,const base::StringPiece & result)54   void OnDevToolsMethodResult(int message_id,
55                               bool success,
56                               const base::StringPiece& result) override {
57     CEF_REQUIRE_UIT();
58     observer_->OnDevToolsMethodResult(browser_, message_id, success,
59                                       result.data(), result.size());
60   }
61 
OnDevToolsEvent(const base::StringPiece & method,const base::StringPiece & params)62   void OnDevToolsEvent(const base::StringPiece& method,
63                        const base::StringPiece& params) override {
64     CEF_REQUIRE_UIT();
65     observer_->OnDevToolsEvent(browser_, method.as_string(), params.data(),
66                                params.size());
67   }
68 
OnDevToolsAgentAttached()69   void OnDevToolsAgentAttached() override {
70     CEF_REQUIRE_UIT();
71     observer_->OnDevToolsAgentAttached(browser_);
72   }
73 
OnDevToolsAgentDetached()74   void OnDevToolsAgentDetached() override {
75     CEF_REQUIRE_UIT();
76     observer_->OnDevToolsAgentDetached(browser_);
77   }
78 
OnDevToolsControllerDestroyed()79   void OnDevToolsControllerDestroyed() override {
80     CEF_REQUIRE_UIT();
81     browser_ = nullptr;
82     controller_.reset();
83   }
84 
85   CefRefPtr<CefDevToolsMessageObserver> observer_;
86 
87   CefBrowserHostBase* browser_ = nullptr;
88   base::WeakPtr<CefDevToolsController> controller_;
89 
90   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDevToolsRegistrationImpl);
91   DISALLOW_COPY_AND_ASSIGN(CefDevToolsRegistrationImpl);
92 };
93 
94 }  // namespace
95 
CefDevToolsManager(CefBrowserHostBase * inspected_browser)96 CefDevToolsManager::CefDevToolsManager(CefBrowserHostBase* inspected_browser)
97     : inspected_browser_(inspected_browser), weak_ptr_factory_(this) {
98   CEF_REQUIRE_UIT();
99 }
100 
~CefDevToolsManager()101 CefDevToolsManager::~CefDevToolsManager() {
102   CEF_REQUIRE_UIT();
103 }
104 
ShowDevTools(const CefWindowInfo & windowInfo,CefRefPtr<CefClient> client,const CefBrowserSettings & settings,const CefPoint & inspect_element_at)105 void CefDevToolsManager::ShowDevTools(const CefWindowInfo& windowInfo,
106                                       CefRefPtr<CefClient> client,
107                                       const CefBrowserSettings& settings,
108                                       const CefPoint& inspect_element_at) {
109   CEF_REQUIRE_UIT();
110   if (devtools_frontend_) {
111     if (!inspect_element_at.IsEmpty()) {
112       devtools_frontend_->InspectElementAt(inspect_element_at.x,
113                                            inspect_element_at.y);
114     }
115     devtools_frontend_->Focus();
116     return;
117   }
118 
119   if (cef::IsChromeRuntimeEnabled()) {
120     NOTIMPLEMENTED();
121   } else {
122     auto alloy_browser = static_cast<AlloyBrowserHostImpl*>(inspected_browser_);
123     devtools_frontend_ = CefDevToolsFrontend::Show(
124         alloy_browser, windowInfo, client, settings, inspect_element_at,
125         base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed,
126                        weak_ptr_factory_.GetWeakPtr()));
127   }
128 }
129 
CloseDevTools()130 void CefDevToolsManager::CloseDevTools() {
131   CEF_REQUIRE_UIT();
132   if (!devtools_frontend_)
133     return;
134   devtools_frontend_->Close();
135 }
136 
HasDevTools()137 bool CefDevToolsManager::HasDevTools() {
138   CEF_REQUIRE_UIT();
139   return !!devtools_frontend_;
140 }
141 
SendDevToolsMessage(const void * message,size_t message_size)142 bool CefDevToolsManager::SendDevToolsMessage(const void* message,
143                                              size_t message_size) {
144   CEF_REQUIRE_UIT();
145   if (!message || message_size == 0)
146     return false;
147 
148   if (!EnsureController())
149     return false;
150 
151   return devtools_controller_->SendDevToolsMessage(
152       base::StringPiece(static_cast<const char*>(message), message_size));
153 }
154 
ExecuteDevToolsMethod(int message_id,const CefString & method,CefRefPtr<CefDictionaryValue> params)155 int CefDevToolsManager::ExecuteDevToolsMethod(
156     int message_id,
157     const CefString& method,
158     CefRefPtr<CefDictionaryValue> params) {
159   CEF_REQUIRE_UIT();
160   if (method.empty())
161     return 0;
162 
163   if (!EnsureController())
164     return 0;
165 
166   if (params && params->IsValid()) {
167     CefDictionaryValueImpl* impl =
168         static_cast<CefDictionaryValueImpl*>(params.get());
169     CefValueController::AutoLock lock_scope(impl->controller());
170     return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
171                                                        impl->GetValueUnsafe());
172   } else {
173     return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
174                                                        nullptr);
175   }
176 }
177 
178 // static
CreateRegistration(CefRefPtr<CefDevToolsMessageObserver> observer)179 CefRefPtr<CefRegistration> CefDevToolsManager::CreateRegistration(
180     CefRefPtr<CefDevToolsMessageObserver> observer) {
181   DCHECK(observer);
182   return new CefDevToolsRegistrationImpl(observer);
183 }
184 
InitializeRegistrationOnUIThread(CefRefPtr<CefRegistration> registration)185 void CefDevToolsManager::InitializeRegistrationOnUIThread(
186     CefRefPtr<CefRegistration> registration) {
187   CEF_REQUIRE_UIT();
188 
189   if (!EnsureController())
190     return;
191 
192   static_cast<CefDevToolsRegistrationImpl*>(registration.get())
193       ->Initialize(inspected_browser_, devtools_controller_->GetWeakPtr());
194 }
195 
OnFrontEndDestroyed()196 void CefDevToolsManager::OnFrontEndDestroyed() {
197   devtools_frontend_ = nullptr;
198 }
199 
EnsureController()200 bool CefDevToolsManager::EnsureController() {
201   if (!devtools_controller_) {
202     devtools_controller_.reset(new CefDevToolsController(
203         inspected_browser_->contents_delegate()->web_contents()));
204   }
205   return true;
206 }
207