• 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 
25   CefDevToolsRegistrationImpl(const CefDevToolsRegistrationImpl&) = delete;
26   CefDevToolsRegistrationImpl& operator=(const CefDevToolsRegistrationImpl&) =
27       delete;
28 
~CefDevToolsRegistrationImpl()29   ~CefDevToolsRegistrationImpl() override {
30     CEF_REQUIRE_UIT();
31 
32     // May be null if OnDevToolsControllerDestroyed was called.
33     if (!controller_)
34       return;
35 
36     controller_->RemoveObserver(this);
37   }
38 
Initialize(CefBrowserHostBase * browser,base::WeakPtr<CefDevToolsController> controller)39   void Initialize(CefBrowserHostBase* browser,
40                   base::WeakPtr<CefDevToolsController> controller) {
41     CEF_REQUIRE_UIT();
42     DCHECK(browser && controller);
43     DCHECK(!browser_ && !controller_);
44     browser_ = browser;
45     controller_ = controller;
46 
47     controller_->AddObserver(this);
48   }
49 
50  private:
51   // CefDevToolsController::Observer methods:
OnDevToolsMessage(const base::StringPiece & message)52   bool OnDevToolsMessage(const base::StringPiece& message) override {
53     CEF_REQUIRE_UIT();
54     return observer_->OnDevToolsMessage(browser_, message.data(),
55                                         message.size());
56   }
57 
OnDevToolsMethodResult(int message_id,bool success,const base::StringPiece & result)58   void OnDevToolsMethodResult(int message_id,
59                               bool success,
60                               const base::StringPiece& result) override {
61     CEF_REQUIRE_UIT();
62     observer_->OnDevToolsMethodResult(browser_, message_id, success,
63                                       result.data(), result.size());
64   }
65 
OnDevToolsEvent(const base::StringPiece & method,const base::StringPiece & params)66   void OnDevToolsEvent(const base::StringPiece& method,
67                        const base::StringPiece& params) override {
68     CEF_REQUIRE_UIT();
69     observer_->OnDevToolsEvent(browser_, std::string(method), params.data(),
70                                params.size());
71   }
72 
OnDevToolsAgentAttached()73   void OnDevToolsAgentAttached() override {
74     CEF_REQUIRE_UIT();
75     observer_->OnDevToolsAgentAttached(browser_);
76   }
77 
OnDevToolsAgentDetached()78   void OnDevToolsAgentDetached() override {
79     CEF_REQUIRE_UIT();
80     observer_->OnDevToolsAgentDetached(browser_);
81   }
82 
OnDevToolsControllerDestroyed()83   void OnDevToolsControllerDestroyed() override {
84     CEF_REQUIRE_UIT();
85     browser_ = nullptr;
86     controller_.reset();
87   }
88 
89   CefRefPtr<CefDevToolsMessageObserver> observer_;
90 
91   CefBrowserHostBase* browser_ = nullptr;
92   base::WeakPtr<CefDevToolsController> controller_;
93 
94   IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDevToolsRegistrationImpl);
95 };
96 
97 }  // namespace
98 
CefDevToolsManager(CefBrowserHostBase * inspected_browser)99 CefDevToolsManager::CefDevToolsManager(CefBrowserHostBase* inspected_browser)
100     : inspected_browser_(inspected_browser), weak_ptr_factory_(this) {
101   CEF_REQUIRE_UIT();
102 }
103 
~CefDevToolsManager()104 CefDevToolsManager::~CefDevToolsManager() {
105   CEF_REQUIRE_UIT();
106 }
107 
ShowDevTools(const CefWindowInfo & windowInfo,CefRefPtr<CefClient> client,const CefBrowserSettings & settings,const CefPoint & inspect_element_at)108 void CefDevToolsManager::ShowDevTools(const CefWindowInfo& windowInfo,
109                                       CefRefPtr<CefClient> client,
110                                       const CefBrowserSettings& settings,
111                                       const CefPoint& inspect_element_at) {
112   CEF_REQUIRE_UIT();
113   if (devtools_frontend_) {
114     if (!inspect_element_at.IsEmpty()) {
115       devtools_frontend_->InspectElementAt(inspect_element_at.x,
116                                            inspect_element_at.y);
117     }
118     devtools_frontend_->Focus();
119     return;
120   }
121 
122   if (cef::IsChromeRuntimeEnabled()) {
123     NOTIMPLEMENTED();
124   } else {
125     auto alloy_browser = static_cast<AlloyBrowserHostImpl*>(inspected_browser_);
126     devtools_frontend_ = CefDevToolsFrontend::Show(
127         alloy_browser, windowInfo, client, settings, inspect_element_at,
128         base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed,
129                        weak_ptr_factory_.GetWeakPtr()));
130   }
131 }
132 
CloseDevTools()133 void CefDevToolsManager::CloseDevTools() {
134   CEF_REQUIRE_UIT();
135   if (!devtools_frontend_)
136     return;
137   devtools_frontend_->Close();
138 }
139 
HasDevTools()140 bool CefDevToolsManager::HasDevTools() {
141   CEF_REQUIRE_UIT();
142   return !!devtools_frontend_;
143 }
144 
SendDevToolsMessage(const void * message,size_t message_size)145 bool CefDevToolsManager::SendDevToolsMessage(const void* message,
146                                              size_t message_size) {
147   CEF_REQUIRE_UIT();
148   if (!message || message_size == 0)
149     return false;
150 
151   if (!EnsureController())
152     return false;
153 
154   return devtools_controller_->SendDevToolsMessage(
155       base::StringPiece(static_cast<const char*>(message), message_size));
156 }
157 
ExecuteDevToolsMethod(int message_id,const CefString & method,CefRefPtr<CefDictionaryValue> params)158 int CefDevToolsManager::ExecuteDevToolsMethod(
159     int message_id,
160     const CefString& method,
161     CefRefPtr<CefDictionaryValue> params) {
162   CEF_REQUIRE_UIT();
163   if (method.empty())
164     return 0;
165 
166   if (!EnsureController())
167     return 0;
168 
169   if (params && params->IsValid()) {
170     CefDictionaryValueImpl* impl =
171         static_cast<CefDictionaryValueImpl*>(params.get());
172     CefValueController::AutoLock lock_scope(impl->controller());
173     return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
174                                                        impl->GetValueUnsafe());
175   } else {
176     return devtools_controller_->ExecuteDevToolsMethod(message_id, method,
177                                                        nullptr);
178   }
179 }
180 
181 // static
CreateRegistration(CefRefPtr<CefDevToolsMessageObserver> observer)182 CefRefPtr<CefRegistration> CefDevToolsManager::CreateRegistration(
183     CefRefPtr<CefDevToolsMessageObserver> observer) {
184   DCHECK(observer);
185   return new CefDevToolsRegistrationImpl(observer);
186 }
187 
InitializeRegistrationOnUIThread(CefRefPtr<CefRegistration> registration)188 void CefDevToolsManager::InitializeRegistrationOnUIThread(
189     CefRefPtr<CefRegistration> registration) {
190   CEF_REQUIRE_UIT();
191 
192   if (!EnsureController())
193     return;
194 
195   static_cast<CefDevToolsRegistrationImpl*>(registration.get())
196       ->Initialize(inspected_browser_, devtools_controller_->GetWeakPtr());
197 }
198 
OnFrontEndDestroyed()199 void CefDevToolsManager::OnFrontEndDestroyed() {
200   devtools_frontend_ = nullptr;
201 }
202 
EnsureController()203 bool CefDevToolsManager::EnsureController() {
204   if (!devtools_controller_) {
205     devtools_controller_.reset(new CefDevToolsController(
206         inspected_browser_->contents_delegate()->web_contents()));
207   }
208   return true;
209 }
210