From 9017c0e74ee94ed3738db9d98bb4b5d764675fa3 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 26 Apr 2012 22:20:18 +0000 Subject: [PATCH] - Update to Chromium revision 133962. - Mac: Fix path discovery for non-native frameworks (issue #576). - Avoid loading Chrome-specific pack files (issue #578). - Make DevTools remote debugging URLs harder to guess (issue #583) - Add CefBrowser::GetDevToolsURL() method (issue #583). - Add DevTools example to cefclient (must run with --remote-debugging-port=XXXX command-line flag) (issue #583). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@608 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- CHROMIUM_BUILD_COMPATIBILITY.txt | 2 +- cef.gyp | 4 +- include/capi/cef_browser_capi.h | 8 ++ include/cef_browser.h | 7 ++ libcef/browser/browser_host_impl.cc | 11 ++ libcef/browser/browser_host_impl.h | 2 + libcef/browser/browser_main.h | 1 + libcef/browser/context.cc | 5 + libcef/browser/context.h | 1 + libcef/browser/devtools_delegate.cc | 100 ++++++++++++++++++ libcef/browser/devtools_delegate.h | 8 +- .../url_request_context_getter_proxy.cc | 9 ++ libcef/common/main_delegate.cc | 76 ++++++------- libcef_dll/cpptoc/browser_host_cpptoc.cc | 16 +++ libcef_dll/ctocpp/browser_host_ctocpp.cc | 15 +++ libcef_dll/ctocpp/browser_host_ctocpp.h | 1 + patch/patch.cfg | 5 + patch/patches/resource_bundle.patch | 35 ++++++ tests/cefclient/client_handler.cpp | 19 ++-- tests/cefclient/client_handler.h | 3 +- tools/distrib/mac/README.txt | 2 +- 21 files changed, 275 insertions(+), 55 deletions(-) create mode 100644 patch/patches/resource_bundle.patch diff --git a/CHROMIUM_BUILD_COMPATIBILITY.txt b/CHROMIUM_BUILD_COMPATIBILITY.txt index 1b70b0d2a..adee1e7d2 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': '133430', + 'chromium_revision': '133962', } diff --git a/cef.gyp b/cef.gyp index 786249a71..75168b720 100644 --- a/cef.gyp +++ b/cef.gyp @@ -143,7 +143,7 @@ 'cp', '-f', '${BUILT_PRODUCTS_DIR}/cef.pak', - '${BUILT_PRODUCTS_DIR}/cefclient.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources/chrome.pak' + '${BUILT_PRODUCTS_DIR}/cefclient.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources/cef.pak' ], }, { @@ -316,7 +316,7 @@ 'cp', '-f', '${BUILT_PRODUCTS_DIR}/cef.pak', - '${BUILT_PRODUCTS_DIR}/cef_unittests.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources/chrome.pak' + '${BUILT_PRODUCTS_DIR}/cef_unittests.app/Contents/Frameworks/Chromium Embedded Framework.framework/Resources/cef.pak' ], }, { diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 4729ac0e7..bbab11cf7 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -222,6 +222,14 @@ typedef struct _cef_browser_host_t { /// struct _cef_client_t* (CEF_CALLBACK *get_client)( 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. + /// + // 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); } cef_browser_host_t; diff --git a/include/cef_browser.h b/include/cef_browser.h index 7790a38d3..10aac34bc 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -256,6 +256,13 @@ class CefBrowserHost : public virtual CefBase { /// /*--cef()--*/ 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. + /// + /*--cef()--*/ + virtual CefString GetDevToolsURL() =0; }; #endif // CEF_INCLUDE_CEF_BROWSER_H_ diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index fd4cfd880..8f6f5777b 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -289,6 +289,10 @@ CefRefPtr CefBrowserHostImpl::GetClient() { return client_; } +CefString CefBrowserHostImpl::GetDevToolsURL() { + return devtools_url_; +} + // CefBrowser methods. // ----------------------------------------------------------------------------- @@ -1099,6 +1103,13 @@ CefBrowserHostImpl::CefBrowserHostImpl(const CefWindowInfo& window_info, placeholder_frame_ = new CefFrameHostImpl(this, CefFrameHostImpl::kInvalidFrameId, true); + + // Retrieve the DevTools URL, if any. + CefDevToolsDelegate* devtools_delegate = _Context->devtools_delegate(); + if (devtools_delegate) { + devtools_url_ = devtools_delegate->GetDevToolsURL( + web_contents->GetRenderViewHost()); + } } CefRefPtr CefBrowserHostImpl::GetOrCreateFrame( diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index f1b3042f9..9571fed1d 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -100,6 +100,7 @@ class CefBrowserHostImpl : public CefBrowserHost, virtual CefWindowHandle GetWindowHandle() OVERRIDE; virtual CefWindowHandle GetOpenerWindowHandle() OVERRIDE; virtual CefRefPtr GetClient() OVERRIDE; + virtual CefString GetDevToolsURL() OVERRIDE; // CefBrowser methods. virtual CefRefPtr GetHost() OVERRIDE; @@ -305,6 +306,7 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr client_; scoped_ptr web_contents_; CefWindowHandle opener_; + CefString devtools_url_; // 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_main.h b/libcef/browser/browser_main.h index 554304b19..dad4d7d15 100644 --- a/libcef/browser/browser_main.h +++ b/libcef/browser/browser_main.h @@ -45,6 +45,7 @@ class CefBrowserMainParts : public content::BrowserMainParts { ui::Clipboard* GetClipboard(); CefBrowserContext* browser_context() const { return browser_context_.get(); } + CefDevToolsDelegate* devtools_delegate() const { return devtools_delegate_; } private: void PlatformInitialize(); diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 8483ef047..2a4f69b24 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -333,6 +333,11 @@ CefBrowserContext* CefContext::browser_context() const { browser_context(); } +CefDevToolsDelegate* CefContext::devtools_delegate() const { + return main_delegate_->browser_client()->browser_main_parts()-> + devtools_delegate(); +} + void CefContext::FinishShutdownOnUIThread( base::WaitableEvent* uithread_shutdown_event) { CEF_REQUIRE_UIT(); diff --git a/libcef/browser/context.h b/libcef/browser/context.h index 4dfe6b6ca..588c9827d 100644 --- a/libcef/browser/context.h +++ b/libcef/browser/context.h @@ -66,6 +66,7 @@ class CefContext : public CefBase { const CefSettings& settings() const { return settings_; } CefRefPtr application() const; CefBrowserContext* browser_context() const; + CefDevToolsDelegate* devtools_delegate() const; private: // Performs shutdown actions that need to occur on the UI thread before any diff --git a/libcef/browser/devtools_delegate.cc b/libcef/browser/devtools_delegate.cc index 0f5258ac1..8616f6b7f 100644 --- a/libcef/browser/devtools_delegate.cc +++ b/libcef/browser/devtools_delegate.cc @@ -5,13 +5,91 @@ #include "libcef/browser/devtools_delegate.h" #include +#include +#include "base/command_line.h" +#include "base/md5.h" +#include "base/rand_util.h" +#include "base/stringprintf.h" +#include "base/string_number_conversions.h" +#include "base/time.h" #include "content/public/browser/devtools_http_handler.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/render_view_host.h" #include "content/public/common/content_client.h" +#include "content/public/common/content_switches.h" #include "grit/cef_resources.h" #include "net/url_request/url_request_context_getter.h" #include "ui/base/resource/resource_bundle.h" +namespace { + +class CefDevToolsBindingHandler + : public content::DevToolsHttpHandler::RenderViewHostBinding { + public: + CefDevToolsBindingHandler() { + } + + virtual std::string GetIdentifier(content::RenderViewHost* rvh) OVERRIDE { + int process_id = rvh->GetProcess()->GetID(); + int routing_id = rvh->GetRoutingID(); + + if (random_seed_.empty()) { + // Generate a random seed that is used to make identifier guessing more + // difficult. + random_seed_ = base::StringPrintf("%lf|%llu", + base::Time::Now().ToDoubleT(), base::RandUint64()); + } + + // Create a key that combines RVH IDs and the random seed. + std::string key = base::StringPrintf("%d|%d|%s", + process_id, + routing_id, + random_seed_.c_str()); + + // Return an MD5 hash of the key. + return base::MD5String(key); + } + + virtual content::RenderViewHost* ForIdentifier( + const std::string& identifier) OVERRIDE { + // Iterate through the existing RVH instances to find a match. + for (content::RenderProcessHost::iterator it( + content::RenderProcessHost::AllHostsIterator()); + !it.IsAtEnd(); it.Advance()) { + content::RenderProcessHost* render_process_host = it.GetCurrentValue(); + DCHECK(render_process_host); + + // Ignore processes that don't have a connection, such as crashed + // contents. + if (!render_process_host->HasConnection()) + continue; + + content::RenderProcessHost::RenderWidgetHostsIterator rwit( + render_process_host->GetRenderWidgetHostsIterator()); + for (; !rwit.IsAtEnd(); rwit.Advance()) { + const content::RenderWidgetHost* widget = rwit.GetCurrentValue(); + DCHECK(widget); + if (!widget || !widget->IsRenderView()) + continue; + + content::RenderViewHost* host = + content::RenderViewHost::From( + const_cast(widget)); + if (GetIdentifier(host) == identifier) + return host; + } + } + + return NULL; + } + + private: + std::string random_seed_; +}; + +} // namespace + CefDevToolsDelegate::CefDevToolsDelegate( int port, net::URLRequestContextGetter* context_getter) { @@ -21,6 +99,9 @@ CefDevToolsDelegate::CefDevToolsDelegate( "", context_getter, this); + + binding_.reset(new CefDevToolsBindingHandler()); + devtools_http_handler_->SetRenderViewHostBinding(binding_.get()); } CefDevToolsDelegate::~CefDevToolsDelegate() { @@ -43,3 +124,22 @@ bool CefDevToolsDelegate::BundlesFrontendResources() { std::string CefDevToolsDelegate::GetFrontendResourcesBaseURL() { return ""; } + +std::string CefDevToolsDelegate::GetDevToolsURL(content::RenderViewHost* rvh) { + const CommandLine& command_line = *CommandLine::ForCurrentProcess(); + std::string port_str = + command_line.GetSwitchValueASCII(switches::kRemoteDebuggingPort); + DCHECK(!port_str.empty()); + int port; + if (!base::StringToInt(port_str, &port)) + return std::string(); + + std::string page_id = binding_->GetIdentifier(rvh); + + return base::StringPrintf( + "http://localhost:%d/devtools/devtools.html?" + "ws=localhost:%d/devtools/page/%s", + port, + port, + page_id.c_str()); +} diff --git a/libcef/browser/devtools_delegate.h b/libcef/browser/devtools_delegate.h index ca5d76f64..d47570f57 100644 --- a/libcef/browser/devtools_delegate.h +++ b/libcef/browser/devtools_delegate.h @@ -10,6 +10,8 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/devtools_http_handler.h" #include "content/public/browser/devtools_http_handler_delegate.h" namespace net { @@ -17,7 +19,7 @@ class URLRequestContextGetter; } namespace content { -class DevToolsHttpHandler; +class RenderViewHost; } class CefDevToolsDelegate : public content::DevToolsHttpHandlerDelegate { @@ -33,8 +35,12 @@ class CefDevToolsDelegate : public content::DevToolsHttpHandlerDelegate { virtual bool BundlesFrontendResources() OVERRIDE; virtual std::string GetFrontendResourcesBaseURL() OVERRIDE; + // Returns the DevTools URL for the specified RenderViewHost. + std::string GetDevToolsURL(content::RenderViewHost* rvh); + private: content::DevToolsHttpHandler* devtools_http_handler_; + scoped_ptr binding_; DISALLOW_COPY_AND_ASSIGN(CefDevToolsDelegate); }; diff --git a/libcef/browser/url_request_context_getter_proxy.cc b/libcef/browser/url_request_context_getter_proxy.cc index 9741552cc..8f7316446 100644 --- a/libcef/browser/url_request_context_getter_proxy.cc +++ b/libcef/browser/url_request_context_getter_proxy.cc @@ -3,6 +3,9 @@ // be found in the LICENSE file. #include "libcef/browser/url_request_context_getter_proxy.h" + +#include + #include "libcef/browser/browser_host_impl.h" #include "libcef/browser/cookie_manager_impl.h" #include "libcef/browser/thread_util.h" @@ -64,6 +67,12 @@ class CefCookieStoreProxy : public net::CookieStore { callback); } + virtual void DeleteSessionCookiesAsync(const DeleteCallback& callback) + OVERRIDE { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteSessionCookiesAsync(callback); + } + virtual net::CookieMonster* GetCookieMonster() OVERRIDE { scoped_refptr cookie_store = GetCookieStore(); return cookie_store->GetCookieMonster(); diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index 504fdb6c5..a9e06f82c 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -33,36 +33,37 @@ #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" #include "content/public/common/content_paths.h" +#endif namespace { +#if defined(OS_MACOSX) + FilePath GetFrameworksPath() { // Start out with the path to the running executable. - FilePath path; - PathService::Get(base::FILE_EXE, &path); + FilePath execPath; + PathService::Get(base::FILE_EXE, &execPath); - // Up to Contents. - if (base::mac::IsBackgroundOnlyProcess()) { - // The running executable is the helper. Go up five steps: - // Contents/Frameworks/Helper.app/Contents/MacOS/Helper - // ^ to here ^ from here - path = path.DirName().DirName().DirName().DirName().DirName(); - } else { - // One step up to MacOS, another to Contents. - path = path.DirName().DirName(); - } - DCHECK_EQ(path.BaseName().value(), "Contents"); + // Get the main bundle path. + FilePath bundlePath = base::mac::GetAppBundlePath(execPath); - // Go into the frameworks directory. - return path.Append("Frameworks"); + // Go into the Contents/Frameworks directory. + return bundlePath.Append(FILE_PATH_LITERAL("Contents")) + .Append(FILE_PATH_LITERAL("Frameworks")); } // The framework bundle path is used for loading resources, libraries, etc. -void OverrideFrameworkBundlePath() { - FilePath helper_path = - GetFrameworksPath().Append("Chromium Embedded Framework.framework"); +FilePath GetFrameworkBundlePath() { + return GetFrameworksPath().Append( + FILE_PATH_LITERAL("Chromium Embedded Framework.framework")); +} - base::mac::SetOverrideFrameworkBundlePath(helper_path); +FilePath GetDefaultPackPath() { + return GetFrameworkBundlePath().Append(FILE_PATH_LITERAL("Resources")); +} + +void OverrideFrameworkBundlePath() { + base::mac::SetOverrideFrameworkBundlePath(GetFrameworkBundlePath()); } void OverrideChildProcessPath() { @@ -72,19 +73,24 @@ void OverrideChildProcessPath() { std::string name = path.BaseName().value(); - FilePath helper_path = GetFrameworksPath().Append(name+" Helper.app") - .Append("Contents") - .Append("MacOS") - .Append(name+" Helper"); + FilePath helper_path = GetFrameworksPath() + .Append(FILE_PATH_LITERAL(name+" Helper.app")) + .Append(FILE_PATH_LITERAL("Contents")) + .Append(FILE_PATH_LITERAL("MacOS")) + .Append(FILE_PATH_LITERAL(name+" Helper")); PathService::Override(content::CHILD_PROCESS_EXE, helper_path); } -} // namespace +#else // !defined(OS_MACOSX) -#endif // OS_MACOSX +FilePath GetDefaultPackPath() { + FilePath pak_dir; + PathService::Get(base::DIR_MODULE, &pak_dir); + return pak_dir; +} -namespace { +#endif // !defined(OS_MACOSX) // Used to run the UI on a separate thread. class CefUIThread : public base::Thread { @@ -345,42 +351,30 @@ void CefMainDelegate::InitializeContentClient( void CefMainDelegate::InitializeResourceBundle() { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - // Mac OS-X does not support customization of the pack load paths. -#if !defined(OS_MACOSX) FilePath pak_file, locales_dir; if (command_line.HasSwitch(switches::kPackFilePath)) pak_file = command_line.GetSwitchValuePath(switches::kPackFilePath); - if (pak_file.empty()) { - FilePath pak_dir; - PathService::Get(base::DIR_MODULE, &pak_dir); - pak_file = pak_dir.Append(FILE_PATH_LITERAL("cef.pak")); - } - - if (!pak_file.empty()) - PathService::Override(ui::FILE_RESOURCES_PAK, pak_file); + if (pak_file.empty()) + pak_file = GetDefaultPackPath().Append(FILE_PATH_LITERAL("cef.pak")); if (command_line.HasSwitch(switches::kLocalesDirPath)) locales_dir = command_line.GetSwitchValuePath(switches::kLocalesDirPath); if (!locales_dir.empty()) PathService::Override(ui::DIR_LOCALES, locales_dir); -#endif // !defined(OS_MACOSX) std::string locale = command_line.GetSwitchValueASCII(switches::kLocale); if (locale.empty()) locale = "en-US"; const std::string loaded_locale = - ui::ResourceBundle::InitSharedInstanceWithLocale(locale); + ui::ResourceBundle::InitSharedInstanceWithLocaleCef(locale); CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale; -#if defined(OS_WIN) - // Explicitly load cef.pak on Windows. if (file_util::PathExists(pak_file)) ResourceBundle::GetSharedInstance().AddDataPack(pak_file); else NOTREACHED() << "Could not load cef.pak"; -#endif } diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index cc1c3a550..c59b58c3a 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -196,6 +196,21 @@ struct _cef_client_t* CEF_CALLBACK browser_host_get_client( return CefClientCToCpp::Unwrap(_retval); } +cef_string_userfree_t CEF_CALLBACK browser_host_get_dev_tools_url( + struct _cef_browser_host_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefBrowserHostCppToC::Get(self)->GetDevToolsURL(); + + // Return type: string + return _retval.DetachToUserFree(); +} + // CONSTRUCTOR - Do not edit by hand. @@ -210,6 +225,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls) struct_.struct_.get_opener_window_handle = browser_host_get_opener_window_handle; struct_.struct_.get_client = browser_host_get_client; + struct_.struct_.get_dev_tools_url = browser_host_get_dev_tools_url; } #ifndef NDEBUG diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 7f2202045..9882f80fd 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -147,6 +147,21 @@ CefRefPtr CefBrowserHostCToCpp::GetClient() { return CefClientCppToC::Unwrap(_retval); } +CefString CefBrowserHostCToCpp::GetDevToolsURL() { + 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_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + #ifndef NDEBUG template<> long CefCToCpp GetClient() OVERRIDE; + virtual CefString GetDevToolsURL() OVERRIDE; }; #endif // USING_CEF_SHARED diff --git a/patch/patch.cfg b/patch/patch.cfg index 526bb790c..ed349bc42 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -21,6 +21,11 @@ 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 new file mode 100644 index 000000000..644b985d6 --- /dev/null +++ b/patch/patches/resource_bundle.patch @@ -0,0 +1,35 @@ +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 2d428406e..15db6e56a 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -251,8 +251,11 @@ void ClientHandler::OnBeforeContextMenu( // Add a "Show DevTools" item to all context menus. model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools"); - // TODO(cef): Enable once ShowDevTools() is implemented. - model->SetEnabled(CLIENT_ID_SHOW_DEVTOOLS, false); + CefString devtools_url = browser->GetHost()->GetDevToolsURL(); + if (devtools_url.empty()) { + // Disable the menu option if DevTools aren't enabled. + model->SetEnabled(CLIENT_ID_SHOW_DEVTOOLS, false); + } // Test context menu features. BuildTestMenu(model); @@ -267,7 +270,7 @@ bool ClientHandler::OnContextMenuCommand( EventFlags event_flags) { switch (command_id) { case CLIENT_ID_SHOW_DEVTOOLS: - ShowDevTools(); + ShowDevTools(browser); return true; default: // Allow default handling, if any. return ExecuteTestMenu(command_id); @@ -310,10 +313,12 @@ std::string ClientHandler::GetLastDownloadFile() { return m_LastDownloadFile; } -void ClientHandler::ShowDevTools() { -} - -void ClientHandler::CloseDevTools() { +void ClientHandler::ShowDevTools(CefRefPtr browser) { + std::string devtools_url = browser->GetHost()->GetDevToolsURL(); + if (!devtools_url.empty()) { + browser->GetMainFrame()->ExecuteJavaScript( + "window.open('" + devtools_url + "');", "about:blank", 0); + } } // static diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index c73af3e84..9d1bb8b7b 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -178,8 +178,7 @@ class ClientHandler : public CefClient, void SendNotification(NotificationType type); void CloseMainWindow(); - void ShowDevTools(); - void CloseDevTools(); + void ShowDevTools(CefRefPtr browser); protected: void SetLoading(bool isLoading); diff --git a/tools/distrib/mac/README.txt b/tools/distrib/mac/README.txt index 214d2cbb8..b3da9a334 100644 --- a/tools/distrib/mac/README.txt +++ b/tools/distrib/mac/README.txt @@ -83,7 +83,7 @@ Optional components: CefSettings.pack_loading_disabled. * Other resources - Resources/chrome.pak + Resources/cef.pak Note: Contains WebKit image and inspector resources. Pack file loading can be disabled completely using CefSettings.pack_loading_disabled.