diff --git a/CHROMIUM_BUILD_COMPATIBILITY.txt b/CHROMIUM_BUILD_COMPATIBILITY.txt index d31d9b812..6c9465e77 100644 --- a/CHROMIUM_BUILD_COMPATIBILITY.txt +++ b/CHROMIUM_BUILD_COMPATIBILITY.txt @@ -17,5 +17,5 @@ { 'chromium_url': 'http://src.chromium.org/svn/trunk/src', - 'chromium_revision': '134688', + 'chromium_revision': '136953', } diff --git a/cef.gyp b/cef.gyp index 5d6c4c8ab..ed4a636d8 100644 --- a/cef.gyp +++ b/cef.gyp @@ -783,6 +783,8 @@ 'libcef/browser/cookie_manager_impl.h', 'libcef/browser/devtools_delegate.cc', 'libcef/browser/devtools_delegate.h', + 'libcef/browser/devtools_scheme_handler.cc', + 'libcef/browser/devtools_scheme_handler.h', 'libcef/browser/download_manager_delegate.cc', 'libcef/browser/download_manager_delegate.h', 'libcef/browser/frame_host_impl.cc', diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index bbab11cf7..971a394c5 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -224,12 +224,14 @@ typedef struct _cef_browser_host_t { struct _cef_browser_host_t* self); /// - // Returns the remote debugging DevTools URL for this browser. If remote - // debugging is disabled this function will return an NULL string. + // Returns the DevTools URL for this browser. If |http_scheme| is true (1) the + // returned URL will use the http scheme instead of the chrome-devtools + // scheme. If remote debugging is disabled this function will return an NULL + // string. /// // The resulting string must be freed by calling cef_string_userfree_free(). cef_string_userfree_t (CEF_CALLBACK *get_dev_tools_url)( - struct _cef_browser_host_t* self); + struct _cef_browser_host_t* self, int http_scheme); } cef_browser_host_t; diff --git a/include/cef_browser.h b/include/cef_browser.h index 10aac34bc..9c4a41e69 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -258,11 +258,13 @@ class CefBrowserHost : public virtual CefBase { virtual CefRefPtr GetClient() =0; /// - // Returns the remote debugging DevTools URL for this browser. If remote - // debugging is disabled this method will return an empty string. + // Returns the DevTools URL for this browser. If |http_scheme| is true the + // returned URL will use the http scheme instead of the chrome-devtools + // scheme. If remote debugging is disabled this method will return an empty + // string. /// /*--cef()--*/ - virtual CefString GetDevToolsURL() =0; + virtual CefString GetDevToolsURL(bool http_scheme) =0; }; #endif // CEF_INCLUDE_CEF_BROWSER_H_ diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 8f6f5777b..6261f64c6 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -289,8 +289,8 @@ CefRefPtr CefBrowserHostImpl::GetClient() { return client_; } -CefString CefBrowserHostImpl::GetDevToolsURL() { - return devtools_url_; +CefString CefBrowserHostImpl::GetDevToolsURL(bool http_scheme) { + return (http_scheme ? devtools_url_http_ : devtools_url_chrome_); } @@ -1107,8 +1107,10 @@ CefBrowserHostImpl::CefBrowserHostImpl(const CefWindowInfo& window_info, // Retrieve the DevTools URL, if any. CefDevToolsDelegate* devtools_delegate = _Context->devtools_delegate(); if (devtools_delegate) { - devtools_url_ = devtools_delegate->GetDevToolsURL( - web_contents->GetRenderViewHost()); + devtools_url_http_ = devtools_delegate->GetDevToolsURL( + web_contents->GetRenderViewHost(), true); + devtools_url_chrome_ = devtools_delegate->GetDevToolsURL( + web_contents->GetRenderViewHost(), false); } } diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 9571fed1d..bb75673b4 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -100,7 +100,7 @@ class CefBrowserHostImpl : public CefBrowserHost, virtual CefWindowHandle GetWindowHandle() OVERRIDE; virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; virtual CefRefPtr GetClient() OVERRIDE; - virtual CefString GetDevToolsURL() OVERRIDE; + virtual CefString GetDevToolsURL(bool http_scheme) OVERRIDE; // CefBrowser methods. virtual CefRefPtr GetHost() OVERRIDE; @@ -306,7 +306,8 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr client_; scoped_ptr web_contents_; CefWindowHandle opener_; - CefString devtools_url_; + CefString devtools_url_http_; + CefString devtools_url_chrome_; // Unique ids used for routing communication to/from the renderer. We keep a // copy of them as member variables so that we can locate matching browsers in diff --git a/libcef/browser/browser_settings.cc b/libcef/browser/browser_settings.cc index 90ffaebc9..a1dcc743b 100644 --- a/libcef/browser/browser_settings.cc +++ b/libcef/browser/browser_settings.cc @@ -14,7 +14,8 @@ #include "content/public/browser/gpu_data_manager.h" #include "webkit/glue/webpreferences.h" -void BrowserToWebSettings(const CefBrowserSettings& cef, WebPreferences& web) { +void BrowserToWebSettings(const CefBrowserSettings& cef, + webkit_glue::WebPreferences& web) { if (cef.standard_font_family.length > 0) web.standard_font_family = CefString(&cef.standard_font_family); else diff --git a/libcef/browser/browser_settings.h b/libcef/browser/browser_settings.h index 187f39b2e..8e182259e 100644 --- a/libcef/browser/browser_settings.h +++ b/libcef/browser/browser_settings.h @@ -7,8 +7,12 @@ #pragma once #include "include/internal/cef_types_wrappers.h" -struct WebPreferences; -void BrowserToWebSettings(const CefBrowserSettings& cef, WebPreferences& web); +namespace webkit_glue { +struct WebPreferences; +} + +void BrowserToWebSettings(const CefBrowserSettings& cef, + webkit_glue::WebPreferences& web); #endif // CEF_LIBCEF_BROWSER_BROWSER_SETTINGS_H_ diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index 511590678..872a1a417 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -61,6 +61,14 @@ class CefMediaObserver : public content::MediaObserver { double volume) OVERRIDE {} virtual void OnMediaEvent(int render_process_id, const media::MediaLogEvent& event) OVERRIDE {} + virtual void OnCaptureDevicesOpened( + int render_process_id, + int render_view_id, + const content::MediaStreamDevices& devices) OVERRIDE {} + virtual void OnCaptureDevicesClosed( + int render_process_id, + int render_view_id, + const content::MediaStreamDevices& devices) OVERRIDE {} }; @@ -381,8 +389,9 @@ bool CefContentBrowserClient::IsFastShutdownPossible() { void CefContentBrowserClient::OverrideWebkitPrefs( content::RenderViewHost* rvh, const GURL& url, - WebPreferences* prefs) { - CefRefPtr browser = CefBrowserHostImpl::GetBrowserForHost(rvh); + webkit_glue::WebPreferences* prefs) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForHost(rvh); DCHECK(browser.get()); // Populate WebPreferences based on CefBrowserSettings. diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index 12fb3e433..2ff3330dc 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -166,7 +166,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient { virtual bool IsFastShutdownPossible() OVERRIDE; virtual void OverrideWebkitPrefs(content::RenderViewHost* rvh, const GURL& url, - WebPreferences* prefs) OVERRIDE; + webkit_glue::WebPreferences* prefs) OVERRIDE; virtual void UpdateInspectorSetting(content::RenderViewHost* rvh, const std::string& key, const std::string& value) OVERRIDE; diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 2a4f69b24..f4759bb59 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -8,6 +8,7 @@ #include "libcef/browser/browser_main.h" #include "libcef/browser/browser_message_loop.h" #include "libcef/browser/content_browser_client.h" +#include "libcef/browser/devtools_scheme_handler.h" #include "libcef/browser/thread_util.h" #include "libcef/common/main_delegate.h" @@ -181,6 +182,10 @@ bool CefContext::Initialize(const CefMainArgs& args, settings_ = settings; cache_path_ = FilePath(CefString(&settings.cache_path)); + if (!cache_path_.empty() && !file_util::CreateDirectory(cache_path_)) { + NOTREACHED() << "The cache_path directory could not be created"; + cache_path_ = FilePath(); + } #if !defined(OS_WIN) if (settings.multi_threaded_message_loop) { @@ -217,6 +222,9 @@ bool CefContext::Initialize(const CefMainArgs& args, initialized_ = true; + // Perform DevTools scheme registration when CEF initialization is complete. + CEF_POST_TASK(CEF_UIT, base::Bind(&RegisterDevToolsSchemeHandler)); + return true; } diff --git a/libcef/browser/cookie_manager_impl.cc b/libcef/browser/cookie_manager_impl.cc index e11af0dc6..acd488272 100644 --- a/libcef/browser/cookie_manager_impl.cc +++ b/libcef/browser/cookie_manager_impl.cc @@ -15,6 +15,7 @@ #include "base/bind.h" #include "base/file_util.h" #include "base/logging.h" +#include "base/threading/thread_restrictions.h" #include "chrome/browser/net/sqlite_persistent_cookie_store.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_context.h" @@ -227,6 +228,9 @@ bool CefCookieManagerImpl::SetStoragePath(const CefString& path) { scoped_refptr persistent_store; if (!new_path.empty()) { + // TODO(cef): Move directory creation to the blocking pool instead of + // allowing file IO on this thread. + base::ThreadRestrictions::SetIOAllowed(true); if (file_util::CreateDirectory(new_path)) { const FilePath& cookie_path = new_path.AppendASCII("Cookies"); persistent_store = new SQLitePersistentCookieStore(cookie_path, false); @@ -234,6 +238,7 @@ bool CefCookieManagerImpl::SetStoragePath(const CefString& path) { NOTREACHED() << "The cookie storage directory could not be created"; storage_path_.clear(); } + base::ThreadRestrictions::SetIOAllowed(false); } // Set the new cookie store that will be used for all new requests. The old diff --git a/libcef/browser/devtools_delegate.cc b/libcef/browser/devtools_delegate.cc index 0a577572d..92373af54 100644 --- a/libcef/browser/devtools_delegate.cc +++ b/libcef/browser/devtools_delegate.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "libcef/browser/devtools_delegate.h" +#include "libcef/browser/devtools_scheme_handler.h" #include #include @@ -118,14 +119,15 @@ std::string CefDevToolsDelegate::GetDiscoveryPageHTML() { } bool CefDevToolsDelegate::BundlesFrontendResources() { - return true; + return false; } std::string CefDevToolsDelegate::GetFrontendResourcesBaseURL() { - return ""; + return kChromeDevToolsURL; } -std::string CefDevToolsDelegate::GetDevToolsURL(content::RenderViewHost* rvh) { +std::string CefDevToolsDelegate::GetDevToolsURL(content::RenderViewHost* rvh, + bool http_scheme) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); std::string port_str = command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort); @@ -135,11 +137,13 @@ std::string CefDevToolsDelegate::GetDevToolsURL(content::RenderViewHost* rvh) { return std::string(); std::string page_id = binding_->GetIdentifier(rvh); + std::string host = http_scheme ? + base::StringPrintf("http://localhost:%d/devtools/", port) : + kChromeDevToolsURL; return base::StringPrintf( - "http://localhost:%d/devtools/devtools.html?" - "ws=localhost:%d/devtools/page/%s", - port, + "%sdevtools.html?ws=localhost:%d/devtools/page/%s", + host.c_str(), port, page_id.c_str()); } diff --git a/libcef/browser/devtools_delegate.h b/libcef/browser/devtools_delegate.h index d47570f57..f51f46d09 100644 --- a/libcef/browser/devtools_delegate.h +++ b/libcef/browser/devtools_delegate.h @@ -36,7 +36,7 @@ class CefDevToolsDelegate : public content::DevToolsHttpHandlerDelegate { virtual std::string GetFrontendResourcesBaseURL() OVERRIDE; // Returns the DevTools URL for the specified RenderViewHost. - std::string GetDevToolsURL(content::RenderViewHost* rvh); + std::string GetDevToolsURL(content::RenderViewHost* rvh, bool http_scheme); private: content::DevToolsHttpHandler* devtools_http_handler_; diff --git a/libcef/browser/devtools_scheme_handler.cc b/libcef/browser/devtools_scheme_handler.cc new file mode 100644 index 000000000..ec6d25e3b --- /dev/null +++ b/libcef/browser/devtools_scheme_handler.cc @@ -0,0 +1,145 @@ +// Copyright (c) 2012 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2012 The Chromium 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_scheme_handler.h" + +#include + +#include "include/cef_browser.h" +#include "include/cef_request.h" +#include "include/cef_resource_handler.h" +#include "include/cef_response.h" +#include "include/cef_scheme.h" +#include "include/cef_stream.h" +#include "include/cef_url.h" + +#include "base/file_util.h" +#include "base/string_util.h" +#include "content/public/common/content_client.h" +#include "grit/devtools_resources_map.h" +#include "ui/base/resource/resource_bundle.h" + +const char kChromeDevToolsScheme[] = "chrome-devtools"; +const char kChromeDevToolsHost[] = "devtools"; +const char kChromeDevToolsURL[] = "chrome-devtools://devtools/"; + +namespace { + +static std::string PathWithoutParams(const std::string& path) { + size_t query_position = path.find("?"); + if (query_position != std::string::npos) + return path.substr(0, query_position); + return path; +} + +static std::string GetMimeType(const std::string& filename) { + if (EndsWith(filename, ".html", false)) { + return "text/html"; + } else if (EndsWith(filename, ".css", false)) { + return "text/css"; + } else if (EndsWith(filename, ".js", false)) { + return "application/javascript"; + } else if (EndsWith(filename, ".png", false)) { + return "image/png"; + } else if (EndsWith(filename, ".gif", false)) { + return "image/gif"; + } + NOTREACHED(); + return "text/plain"; +} + +class DevToolsSchemeHandler : public CefResourceHandler { + public: + DevToolsSchemeHandler(const std::string& path, + CefRefPtr reader, + int size) + : path_(path), reader_(reader), size_(size) { + } + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) + OVERRIDE { + callback->Continue(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = size_; + + response->SetMimeType(GetMimeType(path_)); + response->SetStatus(200); + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) + OVERRIDE { + bytes_read = reader_->Read(data_out, 1, bytes_to_read); + return (bytes_read > 0); + } + + virtual void Cancel() OVERRIDE { + } + + private: + std::string path_; + CefRefPtr reader_; + int size_; + + IMPLEMENT_REFCOUNTING(DevToolSSchemeHandler); +}; + +class DevToolsSchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + DevToolsSchemeHandlerFactory() {} + + virtual CefRefPtr Create( + CefRefPtr browser, + CefRefPtr frame, + const CefString& scheme_name, + CefRefPtr request) OVERRIDE { + std::string url = PathWithoutParams(request->GetURL()); + const char* path = &url.c_str()[strlen(kChromeDevToolsURL)]; + + int size = -1; + CefRefPtr reader = GetStreamReader(path, size); + if (!reader.get()) + return NULL; + + return new DevToolsSchemeHandler(path, reader, size); + } + + CefRefPtr GetStreamReader(const char* path, int& size) { + // Create a stream for the grit resource. + for (size_t i = 0; i < kDevtoolsResourcesSize; ++i) { + if (base::strcasecmp(kDevtoolsResources[i].name, path) == 0) { + base::StringPiece piece = + content::GetContentClient()->GetDataResource( + kDevtoolsResources[i].value); + if (!piece.empty()) { + size = piece.size(); + return CefStreamReader::CreateForData(const_cast(piece.data()), + size); + } + } + } + + NOTREACHED() << "Missing DevTools resource: " << path; + return NULL; + } + + IMPLEMENT_REFCOUNTING(DevToolSSchemeHandlerFactory); +}; + +} // namespace + +// Register the DevTools scheme handler. +void RegisterDevToolsSchemeHandler() { + CefRegisterSchemeHandlerFactory(kChromeDevToolsScheme, kChromeDevToolsHost, + new DevToolsSchemeHandlerFactory()); +} diff --git a/libcef/browser/devtools_scheme_handler.h b/libcef/browser/devtools_scheme_handler.h new file mode 100644 index 000000000..f36608586 --- /dev/null +++ b/libcef/browser/devtools_scheme_handler.h @@ -0,0 +1,16 @@ +// Copyright (c) 2012 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. + +#ifndef CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ +#define CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ +#pragma once + +extern const char kChromeDevToolsScheme[]; +extern const char kChromeDevToolsHost[]; +extern const char kChromeDevToolsURL[]; + +// Register the DevTools scheme handler. +void RegisterDevToolsSchemeHandler(); + +#endif // CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ diff --git a/libcef/browser/scheme_impl.cc b/libcef/browser/scheme_impl.cc index 692e9619b..eb959c8bb 100644 --- a/libcef/browser/scheme_impl.cc +++ b/libcef/browser/scheme_impl.cc @@ -10,6 +10,7 @@ #include "libcef/browser/browser_context.h" #include "libcef/browser/browser_host_impl.h" #include "libcef/browser/context.h" +#include "libcef/browser/devtools_scheme_handler.h" #include "libcef/browser/resource_request_job.h" #include "libcef/browser/thread_util.h" #include "libcef/browser/url_request_context_getter.h" @@ -44,6 +45,10 @@ using net::URLRequestStatus; namespace { +bool IsInternalScheme(const std::string& scheme) { + return (scheme == kChromeDevToolsScheme); +} + bool IsStandardScheme(const std::string& scheme) { url_parse::Component scheme_comp(0, scheme.length()); return url_util::IsStandard(scheme.c_str(), scheme_comp); @@ -226,12 +231,14 @@ class CefUrlRequestManager { if (factory) { CefRefPtr browser = CefBrowserHostImpl::GetBrowserForRequest(request); - if (browser.get()) { + if (browser.get() || IsInternalScheme(request->url().scheme())) { // Populate the request data. CefRefPtr requestPtr(new CefRequestImpl()); requestPtr->Set(request); - CefRefPtr frame = browser->GetFrameForRequest(request); + CefRefPtr frame; + if (browser.get()) + frame = browser->GetFrameForRequest(request); // Call the handler factory to create the handler for the request. CefRefPtr handler = @@ -303,6 +310,9 @@ bool CefClearSchemeHandlerFactories() { if (CEF_CURRENTLY_ON(CEF_IOT)) { CefUrlRequestManager::GetInstance()->ClearFactories(); + + // Re-register the DevTools scheme handler. + RegisterDevToolsSchemeHandler(); } else { CEF_POST_TASK(CEF_IOT, base::Bind(base::IgnoreResult(&CefClearSchemeHandlerFactories))); diff --git a/libcef/browser/url_network_delegate.cc b/libcef/browser/url_network_delegate.cc index 094ccbdb2..c2c0887ba 100644 --- a/libcef/browser/url_network_delegate.cc +++ b/libcef/browser/url_network_delegate.cc @@ -196,13 +196,18 @@ net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired( return AUTH_REQUIRED_RESPONSE_NO_ACTION; } -bool CefNetworkDelegate::CanGetCookies(const net::URLRequest* request, - const net::CookieList& cookie_list) { +bool CefNetworkDelegate::OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) { return true; } -bool CefNetworkDelegate::CanSetCookie(const net::URLRequest* request, - const std::string& cookie_line, - net::CookieOptions* options) { +bool CefNetworkDelegate::OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) { + return true; +} + +bool CefNetworkDelegate::OnCanAccessFile(const net::URLRequest& request, + const FilePath& path) const { return true; } diff --git a/libcef/browser/url_network_delegate.h b/libcef/browser/url_network_delegate.h index 6578297ce..0c86e0092 100644 --- a/libcef/browser/url_network_delegate.h +++ b/libcef/browser/url_network_delegate.h @@ -45,11 +45,13 @@ class CefNetworkDelegate : public net::NetworkDelegate { const net::AuthChallengeInfo& auth_info, const AuthCallback& callback, net::AuthCredentials* credentials) OVERRIDE; - virtual bool CanGetCookies(const net::URLRequest* request, - const net::CookieList& cookie_list) OVERRIDE; - virtual bool CanSetCookie(const net::URLRequest* request, - const std::string& cookie_line, - net::CookieOptions* options) OVERRIDE; + virtual bool OnCanGetCookies(const net::URLRequest& request, + const net::CookieList& cookie_list) OVERRIDE; + virtual bool OnCanSetCookie(const net::URLRequest& request, + const std::string& cookie_line, + net::CookieOptions* options) OVERRIDE; + virtual bool OnCanAccessFile(const net::URLRequest& request, + const FilePath& path) const OVERRIDE; DISALLOW_COPY_AND_ASSIGN(CefNetworkDelegate); }; diff --git a/libcef/browser/url_request_context_getter.cc b/libcef/browser/url_request_context_getter.cc index 637d0882a..8b53f3523 100644 --- a/libcef/browser/url_request_context_getter.cc +++ b/libcef/browser/url_request_context_getter.cc @@ -18,6 +18,8 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/string_split.h" +#include "base/threading/thread_restrictions.h" +#include "base/threading/worker_pool.h" #include "chrome/browser/net/sqlite_persistent_cookie_store.h" #include "content/public/browser/browser_thread.h" #include "net/base/cert_verifier.h" @@ -140,26 +142,20 @@ CefURLRequestContextGetter::~CefURLRequestContextGetter() { net::URLRequestContext* CefURLRequestContextGetter::GetURLRequestContext() { CEF_REQUIRE_IOT(); - if (!url_request_context_) { - // Create the |cache_path| directory if necessary. - bool cache_path_valid = false; + if (!url_request_context_.get()) { const FilePath& cache_path = _Context->cache_path(); - if (!cache_path.empty()) { - if (file_util::CreateDirectory(cache_path)) - cache_path_valid = true; - else - NOTREACHED() << "The cache_path directory could not be created"; - } - url_request_context_ = new net::URLRequestContext(); - storage_.reset(new net::URLRequestContextStorage(url_request_context_)); + url_request_context_.reset(new net::URLRequestContext()); + storage_.reset( + new net::URLRequestContextStorage(url_request_context_.get())); SetCookieStoragePath(cache_path); storage_->set_network_delegate(new CefNetworkDelegate); storage_->set_server_bound_cert_service(new net::ServerBoundCertService( - new net::DefaultServerBoundCertStore(NULL))); + new net::DefaultServerBoundCertStore(NULL), + base::WorkerPool::GetTaskRunner(true))); url_request_context_->set_accept_language("en-us,en"); url_request_context_->set_accept_charset("iso-8859-1,*,utf-8"); @@ -247,7 +243,7 @@ net::URLRequestContext* CefURLRequestContextGetter::GetURLRequestContext() { net::HttpCache::DefaultBackend* main_backend = new net::HttpCache::DefaultBackend( - cache_path_valid ? net::DISK_CACHE : net::MEMORY_CACHE, + cache_path.empty() ? net::MEMORY_CACHE : net::DISK_CACHE, cache_path, 0, BrowserThread::GetMessageLoopProxyForThread( @@ -277,7 +273,7 @@ net::URLRequestContext* CefURLRequestContextGetter::GetURLRequestContext() { request_interceptor_.reset(new CefRequestInterceptor); } - return url_request_context_; + return url_request_context_.get(); } scoped_refptr @@ -301,12 +297,16 @@ void CefURLRequestContextGetter::SetCookieStoragePath(const FilePath& path) { scoped_refptr persistent_store; if (!path.empty()) { + // TODO(cef): Move directory creation to the blocking pool instead of + // allowing file IO on this thread. + base::ThreadRestrictions::SetIOAllowed(true); if (file_util::CreateDirectory(path)) { const FilePath& cookie_path = path.AppendASCII("Cookies"); persistent_store = new SQLitePersistentCookieStore(cookie_path, false); } else { NOTREACHED() << "The cookie storage directory could not be created"; } + base::ThreadRestrictions::SetIOAllowed(false); } // Set the new cookie store that will be used for all new requests. The old diff --git a/libcef/browser/url_request_context_getter.h b/libcef/browser/url_request_context_getter.h index bcfec7c4a..cce2f453c 100644 --- a/libcef/browser/url_request_context_getter.h +++ b/libcef/browser/url_request_context_getter.h @@ -48,11 +48,10 @@ class CefURLRequestContextGetter : public net::URLRequestContextGetter { MessageLoop* file_loop_; scoped_ptr proxy_config_service_; - - scoped_refptr url_request_context_; - scoped_ptr url_security_manager_; - scoped_ptr storage_; scoped_ptr request_interceptor_; + scoped_ptr storage_; + scoped_ptr url_request_context_; + scoped_ptr url_security_manager_; FilePath cookie_store_path_; diff --git a/libcef/browser/url_request_context_getter_proxy.cc b/libcef/browser/url_request_context_getter_proxy.cc index 8f7316446..02cab8a68 100644 --- a/libcef/browser/url_request_context_getter_proxy.cc +++ b/libcef/browser/url_request_context_getter_proxy.cc @@ -120,39 +120,41 @@ class CefCookieStoreProxy : public net::CookieStore { class CefRequestContextProxy : public net::URLRequestContext { public: CefRequestContextProxy(CefBrowserHostImpl* browser, - net::URLRequestContext* parent) + net::URLRequestContextGetter* parent) : parent_(parent) { + net::URLRequestContext* context = parent->GetURLRequestContext(); + // Cookie store that proxies to the browser implementation. - cookie_store_proxy_ = new CefCookieStoreProxy(browser, parent_); + cookie_store_proxy_ = new CefCookieStoreProxy(browser, context); set_cookie_store(cookie_store_proxy_); // All other values refer to the parent request context. - set_net_log(parent_->net_log()); - set_host_resolver(parent_->host_resolver()); - set_cert_verifier(parent_->cert_verifier()); - set_server_bound_cert_service(parent_->server_bound_cert_service()); + set_net_log(context->net_log()); + set_host_resolver(context->host_resolver()); + set_cert_verifier(context->cert_verifier()); + set_server_bound_cert_service(context->server_bound_cert_service()); set_fraudulent_certificate_reporter( - parent_->fraudulent_certificate_reporter()); - set_proxy_service(parent_->proxy_service()); - set_ssl_config_service(parent_->ssl_config_service()); - set_http_auth_handler_factory(parent_->http_auth_handler_factory()); - set_http_transaction_factory(parent_->http_transaction_factory()); - set_ftp_transaction_factory(parent_->ftp_transaction_factory()); - set_network_delegate(parent_->network_delegate()); - set_http_server_properties(parent_->http_server_properties()); - set_transport_security_state(parent_->transport_security_state()); - set_accept_charset(parent_->accept_charset()); - set_accept_language(parent_->accept_language()); - set_referrer_charset(parent_->referrer_charset()); - set_job_factory(parent_->job_factory()); + context->fraudulent_certificate_reporter()); + set_proxy_service(context->proxy_service()); + set_ssl_config_service(context->ssl_config_service()); + set_http_auth_handler_factory(context->http_auth_handler_factory()); + set_http_transaction_factory(context->http_transaction_factory()); + set_ftp_transaction_factory(context->ftp_transaction_factory()); + set_network_delegate(context->network_delegate()); + set_http_server_properties(context->http_server_properties()); + set_transport_security_state(context->transport_security_state()); + set_accept_charset(context->accept_charset()); + set_accept_language(context->accept_language()); + set_referrer_charset(context->referrer_charset()); + set_job_factory(context->job_factory()); } virtual const std::string& GetUserAgent(const GURL& url) const OVERRIDE { - return parent_->GetUserAgent(url); + return parent_->GetURLRequestContext()->GetUserAgent(url); } private: - scoped_refptr parent_; + net::URLRequestContextGetter* parent_; scoped_refptr cookie_store_proxy_; DISALLOW_COPY_AND_ASSIGN(CefRequestContextProxy); @@ -173,11 +175,11 @@ CefURLRequestContextGetterProxy::CefURLRequestContextGetterProxy( net::URLRequestContext* CefURLRequestContextGetterProxy::GetURLRequestContext() { CEF_REQUIRE_IOT(); - if (!context_proxy_) { - context_proxy_ = - new CefRequestContextProxy(browser_, parent_->GetURLRequestContext()); + if (!context_proxy_.get()) { + context_proxy_.reset( + new CefRequestContextProxy(browser_, parent_)); } - return context_proxy_; + return context_proxy_.get(); } scoped_refptr diff --git a/libcef/browser/url_request_context_getter_proxy.h b/libcef/browser/url_request_context_getter_proxy.h index a9c22d99c..11d86b0b4 100644 --- a/libcef/browser/url_request_context_getter_proxy.h +++ b/libcef/browser/url_request_context_getter_proxy.h @@ -6,6 +6,7 @@ #define CEF_LIBCEF_BROWSER_URL_REQUEST_CONTEXT_GETTER_PROXY_H_ #pragma once +#include "base/memory/scoped_ptr.h" #include "net/url_request/url_request_context_getter.h" class CefBrowserHostImpl; @@ -23,7 +24,7 @@ class CefURLRequestContextGetterProxy : public net::URLRequestContextGetter { private: CefBrowserHostImpl* browser_; scoped_refptr parent_; - scoped_refptr context_proxy_; + scoped_ptr context_proxy_; DISALLOW_COPY_AND_ASSIGN(CefURLRequestContextGetterProxy); }; diff --git a/libcef/common/content_client.cc b/libcef/common/content_client.cc index f154f5326..5b528e984 100644 --- a/libcef/common/content_client.cc +++ b/libcef/common/content_client.cc @@ -5,8 +5,10 @@ #include "libcef/common/content_client.h" #include "include/cef_stream.h" #include "include/cef_version.h" +#include "libcef/browser/devtools_scheme_handler.h" #include "libcef/common/cef_switches.h" #include "libcef/common/scheme_registrar_impl.h" +#include "libcef/renderer/content_renderer_client.h" #include "base/command_line.h" #include "base/logging.h" @@ -18,7 +20,8 @@ CefContentClient::CefContentClient(CefRefPtr application) : application_(application), - pack_loading_disabled_(false) { + pack_loading_disabled_(false), + allow_pack_file_load_(false) { } CefContentClient::~CefContentClient() { @@ -56,6 +59,13 @@ void CefContentClient::AddAdditionalSchemes( schemeRegistrar->Detach(); DCHECK(schemeRegistrar->VerifyRefCount()); } + + standard_schemes->push_back(kChromeDevToolsScheme); + if (CefContentRendererClient::Get()) { + // Register the DevTools scheme with WebKit. + CefContentRendererClient::Get()->AddCustomScheme(kChromeDevToolsScheme, + true, false); + } } bool CefContentClient::HasWebUIScheme(const GURL& url) const { @@ -84,21 +94,8 @@ std::string CefContentClient::GetUserAgent() const { } string16 CefContentClient::GetLocalizedString(int message_id) const { - string16 value; - - if (application_.get()) { - CefRefPtr handler = - application_->GetResourceBundleHandler(); - if (handler.get()) { - CefString cef_str; - if (handler->GetLocalizedString(message_id, cef_str)) - value = cef_str; - } - } - - if (value.empty() && !pack_loading_disabled_) - value = ResourceBundle::GetSharedInstance().GetLocalizedString(message_id); - + string16 value = + ResourceBundle::GetSharedInstance().GetLocalizedString(message_id); if (value.empty()) LOG(ERROR) << "No localized string available for id " << message_id; @@ -106,28 +103,19 @@ string16 CefContentClient::GetLocalizedString(int message_id) const { } base::StringPiece CefContentClient::GetDataResource(int resource_id) const { - base::StringPiece value; - - if (application_.get()) { - CefRefPtr handler = - application_->GetResourceBundleHandler(); - if (handler.get()) { - void* data = NULL; - size_t data_size = 0; - if (handler->GetDataResource(resource_id, data, data_size)) - value = base::StringPiece(static_cast(data), data_size); - } - } - - if (value.empty() && !pack_loading_disabled_) - value = ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id); - + base::StringPiece value = + ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id); if (value.empty()) LOG(ERROR) << "No data resource available for id " << resource_id; return value; } +base::StringPiece CefContentClient::GetImageResource(int resource_id, + float scale_factor) const { + return GetDataResource(resource_id); +} + #if defined(OS_WIN) bool CefContentClient::SandboxPlugin(CommandLine* command_line, sandbox::TargetPolicy* policy) { @@ -142,3 +130,68 @@ bool CefContentClient::GetSandboxProfileForSandboxType( return false; } #endif + +FilePath CefContentClient::GetPathForResourcePack(const FilePath& pack_path, + float scale_factor) { + // Only allow the cef pack file to load. + if (!pack_loading_disabled_ && allow_pack_file_load_) + return pack_path; + return FilePath(); +} + +FilePath CefContentClient::GetPathForLocalePack(const FilePath& pack_path, + const std::string& locale) { + if (!pack_loading_disabled_) + return pack_path; + return FilePath(); +} + +gfx::Image CefContentClient::GetImageNamed(int resource_id) { + return gfx::Image(); +} + +gfx::Image CefContentClient::GetNativeImageNamed( + int resource_id, + ui::ResourceBundle::ImageRTL rtl) { + return gfx::Image(); +} + +base::RefCountedStaticMemory* CefContentClient::LoadDataResourceBytes( + int resource_id) { + return NULL; +} + +bool CefContentClient::GetRawDataResource(int resource_id, + base::StringPiece* value) { + if (application_.get()) { + CefRefPtr handler = + application_->GetResourceBundleHandler(); + if (handler.get()) { + void* data = NULL; + size_t data_size = 0; + if (handler->GetDataResource(resource_id, data, data_size)) + *value = base::StringPiece(static_cast(data), data_size); + } + } + + return (pack_loading_disabled_ || !value->empty()); +} + +bool CefContentClient::GetLocalizedString(int message_id, string16* value) { + if (application_.get()) { + CefRefPtr handler = + application_->GetResourceBundleHandler(); + if (handler.get()) { + CefString cef_str; + if (handler->GetLocalizedString(message_id, cef_str)) + *value = cef_str; + } + } + + return (pack_loading_disabled_ || !value->empty()); +} + +scoped_ptr CefContentClient::GetFont( + ui::ResourceBundle::FontStyle style) { + return scoped_ptr(); +} diff --git a/libcef/common/content_client.h b/libcef/common/content_client.h index 888c3435b..2dbc90895 100644 --- a/libcef/common/content_client.h +++ b/libcef/common/content_client.h @@ -13,8 +13,10 @@ #include "base/compiler_specific.h" #include "content/public/common/content_client.h" +#include "ui/base/resource/resource_bundle.h" -class CefContentClient : public content::ContentClient { +class CefContentClient : public content::ContentClient, + public ui::ResourceBundle::Delegate { public: explicit CefContentClient(CefRefPtr application); virtual ~CefContentClient(); @@ -22,6 +24,7 @@ class CefContentClient : public content::ContentClient { // Returns the singleton CefContentClient instance. static CefContentClient* Get(); + // content::ContentClient methods. virtual void SetActiveURL(const GURL& url) OVERRIDE; virtual void SetGpuInfo(const content::GPUInfo& gpu_info) OVERRIDE; virtual void AddPepperPlugins( @@ -36,6 +39,8 @@ class CefContentClient : public content::ContentClient { virtual std::string GetUserAgent() const OVERRIDE; virtual string16 GetLocalizedString(int message_id) const OVERRIDE; virtual base::StringPiece GetDataResource(int resource_id) const OVERRIDE; + virtual base::StringPiece GetImageResource(int resource_id, + float scale_factor) const OVERRIDE; #if defined(OS_WIN) virtual bool SandboxPlugin(CommandLine* command_line, @@ -52,10 +57,29 @@ class CefContentClient : public content::ContentClient { void set_pack_loading_disabled(bool val) { pack_loading_disabled_ = val; } bool pack_loading_disabled() const { return pack_loading_disabled_; } + void set_allow_pack_file_load(bool val) { allow_pack_file_load_ = val; } private: + // ui::ResourceBundle::Delegate methods. + virtual FilePath GetPathForResourcePack(const FilePath& pack_path, + float scale_factor) OVERRIDE; + virtual FilePath GetPathForLocalePack(const FilePath& pack_path, + const std::string& locale) OVERRIDE; + virtual gfx::Image GetImageNamed(int resource_id) OVERRIDE; + virtual gfx::Image GetNativeImageNamed( + int resource_id, + ui::ResourceBundle::ImageRTL rtl) OVERRIDE; + virtual base::RefCountedStaticMemory* LoadDataResourceBytes( + int resource_id) OVERRIDE; + virtual bool GetRawDataResource(int resource_id, + base::StringPiece* value) OVERRIDE; + virtual bool GetLocalizedString(int message_id, string16* value) OVERRIDE; + virtual scoped_ptr GetFont( + ui::ResourceBundle::FontStyle style) OVERRIDE; + CefRefPtr application_; bool pack_loading_disabled_; + bool allow_pack_file_load_; }; #endif // CEF_LIBCEF_COMMON_CONTENT_CLIENT_H_ diff --git a/libcef/common/request_impl.cc b/libcef/common/request_impl.cc index d02fb6d97..890f3d055 100644 --- a/libcef/common/request_impl.cc +++ b/libcef/common/request_impl.cc @@ -163,6 +163,9 @@ void CefRequestImpl::Get(net::URLRequest* request) { // static void CefRequestImpl::GetHeaderMap(const net::HttpRequestHeaders& headers, HeaderMap& map) { + if (headers.IsEmpty()) + return; + net::HttpRequestHeaders::Iterator it(headers); do { map.insert(std::make_pair(it.name(), it.value())); diff --git a/libcef/renderer/content_renderer_client.cc b/libcef/renderer/content_renderer_client.cc index cca59d488..6baacec8a 100644 --- a/libcef/renderer/content_renderer_client.cc +++ b/libcef/renderer/content_renderer_client.cc @@ -149,6 +149,12 @@ bool CefContentRendererClient::OverrideCreatePlugin( return false; } +WebKit::WebPlugin* CefContentRendererClient::CreatePluginReplacement( + content::RenderView* render_view, + const FilePath& plugin_path) { + return NULL; +} + bool CefContentRendererClient::HasErrorPage(int http_status_code, std::string* error_domain) { return false; diff --git a/libcef/renderer/content_renderer_client.h b/libcef/renderer/content_renderer_client.h index 3d18eb91d..294450bcc 100644 --- a/libcef/renderer/content_renderer_client.h +++ b/libcef/renderer/content_renderer_client.h @@ -60,6 +60,9 @@ class CefContentRendererClient : public content::ContentRendererClient { WebKit::WebFrame* frame, const WebKit::WebPluginParams& params, WebKit::WebPlugin** plugin) OVERRIDE; + virtual WebKit::WebPlugin* CreatePluginReplacement( + content::RenderView* render_view, + const FilePath& plugin_path) OVERRIDE; virtual bool HasErrorPage(int http_status_code, std::string* error_domain) OVERRIDE; virtual void GetNavigationErrorStrings( diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index c59b58c3a..6f3d58db3 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -197,7 +197,7 @@ struct _cef_client_t* CEF_CALLBACK browser_host_get_client( } cef_string_userfree_t CEF_CALLBACK browser_host_get_dev_tools_url( - struct _cef_browser_host_t* self) { + struct _cef_browser_host_t* self, int http_scheme) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); @@ -205,7 +205,8 @@ cef_string_userfree_t CEF_CALLBACK browser_host_get_dev_tools_url( return NULL; // Execute - CefString _retval = CefBrowserHostCppToC::Get(self)->GetDevToolsURL(); + CefString _retval = CefBrowserHostCppToC::Get(self)->GetDevToolsURL( + http_scheme?true:false); // Return type: string return _retval.DetachToUserFree(); diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 9882f80fd..04e57c86b 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -147,14 +147,15 @@ CefRefPtr CefBrowserHostCToCpp::GetClient() { return CefClientCppToC::Unwrap(_retval); } -CefString CefBrowserHostCToCpp::GetDevToolsURL() { +CefString CefBrowserHostCToCpp::GetDevToolsURL(bool http_scheme) { if (CEF_MEMBER_MISSING(struct_, get_dev_tools_url)) return CefString(); // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // Execute - cef_string_userfree_t _retval = struct_->get_dev_tools_url(struct_); + cef_string_userfree_t _retval = struct_->get_dev_tools_url(struct_, + http_scheme); // Return type: string CefString _retvalStr; diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.h b/libcef_dll/ctocpp/browser_host_ctocpp.h index 420ea86aa..e4f9da06e 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.h +++ b/libcef_dll/ctocpp/browser_host_ctocpp.h @@ -43,7 +43,7 @@ class CefBrowserHostCToCpp virtual CefWindowHandle GetWindowHandle() OVERRIDE; virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; virtual CefRefPtr GetClient() OVERRIDE; - virtual CefString GetDevToolsURL() OVERRIDE; + virtual CefString GetDevToolsURL(bool http_scheme) OVERRIDE; }; #endif // USING_CEF_SHARED diff --git a/patch/patch.cfg b/patch/patch.cfg index ed349bc42..526bb790c 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -21,11 +21,6 @@ patches = [ 'name': 'tools_gyp', 'path': '../tools/gyp/', }, - { - # http://code.google.com/p/chromiumembedded/issues/detail?id=578 - 'name': 'resource_bundle', - 'path': '../ui/base/resource/', - }, { # http://code.google.com/p/chromiumembedded/issues/detail?id=364 'name': 'spi_webcore_364', diff --git a/patch/patches/resource_bundle.patch b/patch/patches/resource_bundle.patch deleted file mode 100644 index 644b985d6..000000000 --- a/patch/patches/resource_bundle.patch +++ /dev/null @@ -1,35 +0,0 @@ -Index: resource_bundle.cc -=================================================================== ---- resource_bundle.cc (revision 133962) -+++ resource_bundle.cc (working copy) -@@ -47,6 +47,15 @@ - ResourceBundle* ResourceBundle::g_shared_instance_ = NULL; - - // static -+std::string ResourceBundle::InitSharedInstanceWithLocaleCef( -+ const std::string& pref_locale) { -+ DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; -+ g_shared_instance_ = new ResourceBundle(); -+ -+ return g_shared_instance_->LoadLocaleResources(pref_locale); -+} -+ -+// static - std::string ResourceBundle::InitSharedInstanceWithLocale( - const std::string& pref_locale) { - DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice"; -Index: resource_bundle.h -=================================================================== ---- resource_bundle.h (revision 133962) -+++ resource_bundle.h (working copy) -@@ -63,6 +63,10 @@ - RTL_DISABLED, - }; - -+ // Initialize the ResourceBundle without loading any Chrome pack files. -+ static std::string InitSharedInstanceWithLocaleCef( -+ const std::string& pref_locale); -+ - // Initialize the ResourceBundle for this process. Returns the language - // selected. - // NOTE: Mac ignores this and always loads up resources for the language diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 98eca89bd..bf9cf17d1 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -94,6 +94,12 @@ void ClientHandler::OnBeforeClose(CefRefPtr browser) { if (m_BrowserId == browser->GetIdentifier()) { // Free the browser pointer so that the browser can be destroyed m_Browser = NULL; + } else if (browser->IsPopup()) { + // Remove the record for DevTools popup windows. + std::set::iterator it = + m_OpenDevToolsURLs.find(browser->GetMainFrame()->GetURL()); + if (it != m_OpenDevToolsURLs.end()) + m_OpenDevToolsURLs.erase(it); } } @@ -262,9 +268,11 @@ void ClientHandler::OnBeforeContextMenu( // Add a "Show DevTools" item to all context menus. model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools"); - CefString devtools_url = browser->GetHost()->GetDevToolsURL(); - if (devtools_url.empty()) { - // Disable the menu option if DevTools aren't enabled. + CefString devtools_url = browser->GetHost()->GetDevToolsURL(true); + if (devtools_url.empty() || + m_OpenDevToolsURLs.find(devtools_url) != m_OpenDevToolsURLs.end()) { + // Disable the menu option if DevTools isn't enabled or if a window is + // already open for the current URL. model->SetEnabled(CLIENT_ID_SHOW_DEVTOOLS, false); } @@ -325,8 +333,10 @@ std::string ClientHandler::GetLastDownloadFile() { } void ClientHandler::ShowDevTools(CefRefPtr browser) { - std::string devtools_url = browser->GetHost()->GetDevToolsURL(); - if (!devtools_url.empty()) { + std::string devtools_url = browser->GetHost()->GetDevToolsURL(true); + if (!devtools_url.empty() && + m_OpenDevToolsURLs.find(devtools_url) == m_OpenDevToolsURLs.end()) { + m_OpenDevToolsURLs.insert(devtools_url); browser->GetMainFrame()->ExecuteJavaScript( "window.open('" + devtools_url + "');", "about:blank", 0); } diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index 9d1bb8b7b..ac5846488 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -231,6 +231,8 @@ class ClientHandler : public CefClient, ProcessMessageDelegateSet process_message_delegates_; RequestDelegateSet request_delegates_; + std::set m_OpenDevToolsURLs; + // Include the default reference counting implementation. IMPLEMENT_REFCOUNTING(ClientHandler); // Include the default locking implementation.