| // Copyright (c) 2020 The Chromium Embedded Framework Authors. All rights |
| // reserved. Use of this source code is governed by a BSD-style license that |
| // can be found in the LICENSE file. |
| |
| #include "libcef/browser/devtools/devtools_manager.h" |
| |
| #include "libcef/browser/devtools/devtools_controller.h" |
| #include "libcef/browser/devtools/devtools_frontend.h" |
| |
| #include "content/public/browser/web_contents.h" |
| |
| namespace { |
| |
| // May be created on any thread but will be destroyed on the UI thread. |
| class CefDevToolsRegistrationImpl : public CefRegistration, |
| public CefDevToolsController::Observer { |
| public: |
| explicit CefDevToolsRegistrationImpl( |
| CefRefPtr<CefDevToolsMessageObserver> observer) |
| : observer_(observer) { |
| DCHECK(observer_); |
| } |
| |
| ~CefDevToolsRegistrationImpl() override { |
| CEF_REQUIRE_UIT(); |
| |
| // May be null if OnDevToolsControllerDestroyed was called. |
| if (!controller_) |
| return; |
| |
| controller_->RemoveObserver(this); |
| } |
| |
| void Initialize(CefBrowserHostImpl* browser, |
| base::WeakPtr<CefDevToolsController> controller) { |
| CEF_REQUIRE_UIT(); |
| DCHECK(browser && controller); |
| DCHECK(!browser_ && !controller_); |
| browser_ = browser; |
| controller_ = controller; |
| |
| controller_->AddObserver(this); |
| } |
| |
| private: |
| // CefDevToolsController::Observer methods: |
| bool OnDevToolsMessage(const base::StringPiece& message) override { |
| CEF_REQUIRE_UIT(); |
| return observer_->OnDevToolsMessage(browser_, message.data(), |
| message.size()); |
| } |
| |
| void OnDevToolsMethodResult(int message_id, |
| bool success, |
| const base::StringPiece& result) override { |
| CEF_REQUIRE_UIT(); |
| observer_->OnDevToolsMethodResult(browser_, message_id, success, |
| result.data(), result.size()); |
| } |
| |
| void OnDevToolsEvent(const base::StringPiece& method, |
| const base::StringPiece& params) override { |
| CEF_REQUIRE_UIT(); |
| observer_->OnDevToolsEvent(browser_, method.as_string(), params.data(), |
| params.size()); |
| } |
| |
| void OnDevToolsAgentAttached() override { |
| CEF_REQUIRE_UIT(); |
| observer_->OnDevToolsAgentAttached(browser_); |
| } |
| |
| void OnDevToolsAgentDetached() override { |
| CEF_REQUIRE_UIT(); |
| observer_->OnDevToolsAgentDetached(browser_); |
| } |
| |
| void OnDevToolsControllerDestroyed() override { |
| CEF_REQUIRE_UIT(); |
| browser_ = nullptr; |
| controller_.reset(); |
| } |
| |
| CefRefPtr<CefDevToolsMessageObserver> observer_; |
| |
| CefBrowserHostImpl* browser_ = nullptr; |
| base::WeakPtr<CefDevToolsController> controller_; |
| |
| IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefDevToolsRegistrationImpl); |
| DISALLOW_COPY_AND_ASSIGN(CefDevToolsRegistrationImpl); |
| }; |
| |
| } // namespace |
| |
| CefDevToolsManager::CefDevToolsManager(CefBrowserHostImpl* inspected_browser) |
| : inspected_browser_(inspected_browser), weak_ptr_factory_(this) { |
| CEF_REQUIRE_UIT(); |
| } |
| |
| CefDevToolsManager::~CefDevToolsManager() { |
| CEF_REQUIRE_UIT(); |
| } |
| |
| void CefDevToolsManager::ShowDevTools(const CefWindowInfo& windowInfo, |
| CefRefPtr<CefClient> client, |
| const CefBrowserSettings& settings, |
| const CefPoint& inspect_element_at) { |
| CEF_REQUIRE_UIT(); |
| if (devtools_frontend_) { |
| if (!inspect_element_at.IsEmpty()) { |
| devtools_frontend_->InspectElementAt(inspect_element_at.x, |
| inspect_element_at.y); |
| } |
| devtools_frontend_->Focus(); |
| return; |
| } |
| |
| devtools_frontend_ = CefDevToolsFrontend::Show( |
| inspected_browser_, windowInfo, client, settings, inspect_element_at, |
| base::BindOnce(&CefDevToolsManager::OnFrontEndDestroyed, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void CefDevToolsManager::CloseDevTools() { |
| CEF_REQUIRE_UIT(); |
| if (!devtools_frontend_) |
| return; |
| devtools_frontend_->Close(); |
| } |
| |
| bool CefDevToolsManager::HasDevTools() { |
| CEF_REQUIRE_UIT(); |
| return !!devtools_frontend_; |
| } |
| |
| bool CefDevToolsManager::SendDevToolsMessage(const void* message, |
| size_t message_size) { |
| CEF_REQUIRE_UIT(); |
| if (!message || message_size == 0) |
| return false; |
| |
| if (!EnsureController()) |
| return false; |
| |
| return devtools_controller_->SendDevToolsMessage( |
| base::StringPiece(static_cast<const char*>(message), message_size)); |
| } |
| |
| int CefDevToolsManager::ExecuteDevToolsMethod( |
| int message_id, |
| const CefString& method, |
| CefRefPtr<CefDictionaryValue> params) { |
| CEF_REQUIRE_UIT(); |
| if (method.empty()) |
| return 0; |
| |
| if (!EnsureController()) |
| return 0; |
| |
| if (params && params->IsValid()) { |
| CefDictionaryValueImpl* impl = |
| static_cast<CefDictionaryValueImpl*>(params.get()); |
| CefValueController::AutoLock lock_scope(impl->controller()); |
| return devtools_controller_->ExecuteDevToolsMethod(message_id, method, |
| impl->GetValueUnsafe()); |
| } else { |
| return devtools_controller_->ExecuteDevToolsMethod(message_id, method, |
| nullptr); |
| } |
| } |
| |
| // static |
| CefRefPtr<CefRegistration> CefDevToolsManager::CreateRegistration( |
| CefRefPtr<CefDevToolsMessageObserver> observer) { |
| DCHECK(observer); |
| return new CefDevToolsRegistrationImpl(observer); |
| } |
| |
| void CefDevToolsManager::InitializeRegistrationOnUIThread( |
| CefRefPtr<CefRegistration> registration) { |
| CEF_REQUIRE_UIT(); |
| |
| if (!EnsureController()) |
| return; |
| |
| static_cast<CefDevToolsRegistrationImpl*>(registration.get()) |
| ->Initialize(inspected_browser_, devtools_controller_->GetWeakPtr()); |
| } |
| |
| void CefDevToolsManager::OnFrontEndDestroyed() { |
| devtools_frontend_ = nullptr; |
| } |
| |
| bool CefDevToolsManager::EnsureController() { |
| if (!devtools_controller_) { |
| devtools_controller_.reset( |
| new CefDevToolsController(inspected_browser_->web_contents())); |
| } |
| return true; |
| } |