From 9d200c109ab19a09b863227c01c338db6b392daa Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Wed, 11 Apr 2012 18:00:55 +0000 Subject: [PATCH] - Update to Chromium revision 131752. - Add support for multi_threaded_message_loop run mode on Windows (issue #522). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@586 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- libcef/browser/browser_main.cc | 12 ++-- libcef/browser/browser_main.h | 5 +- libcef/browser/browser_main_gtk.cc | 1 - libcef/browser/content_browser_client.cc | 3 +- libcef/browser/content_browser_client.h | 3 - libcef/browser/context.cc | 49 +++---------- libcef/browser/context.h | 3 +- libcef/browser/url_network_delegate.cc | 8 ++- libcef/common/content_client.cc | 29 +++----- libcef/common/content_client.h | 2 +- libcef/common/main_delegate.cc | 88 +++++++++++++++++++++--- libcef/common/main_delegate.h | 6 ++ tests/cefclient/client_handler.cpp | 7 ++ 13 files changed, 132 insertions(+), 84 deletions(-) diff --git a/libcef/browser/browser_main.cc b/libcef/browser/browser_main.cc index e84256e18..01d7115b6 100644 --- a/libcef/browser/browser_main.cc +++ b/libcef/browser/browser_main.cc @@ -37,17 +37,17 @@ CefBrowserMainParts::CefBrowserMainParts( const content::MainFunctionParams& parameters) : BrowserMainParts(), devtools_delegate_(NULL) { - CefContentBrowserClient* browser_client = - static_cast( - content::GetContentClient()->browser()); - browser_client->set_browser_main_parts(this); } CefBrowserMainParts::~CefBrowserMainParts() { } -MessageLoop* CefBrowserMainParts::GetMainMessageLoop() { - return new CefBrowserMessageLoop(); +void CefBrowserMainParts::PreMainMessageLoopStart() { + if (!MessageLoop::current()) { + // Create the browser message loop. + message_loop_.reset(new CefBrowserMessageLoop()); + message_loop_->set_thread_name("CrBrowserMain"); + } } int CefBrowserMainParts::PreCreateThreads() { diff --git a/libcef/browser/browser_main.h b/libcef/browser/browser_main.h index 941b0be88..554304b19 100644 --- a/libcef/browser/browser_main.h +++ b/libcef/browser/browser_main.h @@ -25,6 +25,7 @@ struct MainFunctionParams; class CefBrowserContext; class CefDevToolsDelegate; +class MessageLoop; class CefBrowserMainParts : public content::BrowserMainParts { public: @@ -33,8 +34,7 @@ class CefBrowserMainParts : public content::BrowserMainParts { virtual void PreEarlyInitialization() OVERRIDE {} virtual void PostEarlyInitialization() OVERRIDE {} - virtual void PreMainMessageLoopStart() OVERRIDE {} - virtual MessageLoop* GetMainMessageLoop() OVERRIDE; + virtual void PreMainMessageLoopStart() OVERRIDE; virtual void PostMainMessageLoopStart() OVERRIDE {} virtual void ToolkitInitialized() OVERRIDE {} virtual int PreCreateThreads() OVERRIDE; @@ -52,6 +52,7 @@ class CefBrowserMainParts : public content::BrowserMainParts { scoped_ptr browser_context_; + scoped_ptr message_loop_; scoped_ptr clipboard_; CefDevToolsDelegate* devtools_delegate_; diff --git a/libcef/browser/browser_main_gtk.cc b/libcef/browser/browser_main_gtk.cc index e6beaf524..0f547f331 100644 --- a/libcef/browser/browser_main_gtk.cc +++ b/libcef/browser/browser_main_gtk.cc @@ -9,7 +9,6 @@ #include "base/string_piece.h" void CefBrowserMainParts::PlatformInitialize() { - gtk_init(NULL, NULL); } void CefBrowserMainParts::PlatformCleanup() { diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index cbf02528a..511590678 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -73,7 +73,8 @@ CefContentBrowserClient::~CefContentBrowserClient() { content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts( const content::MainFunctionParams& parameters) { - return new CefBrowserMainParts(parameters); + browser_main_parts_ = new CefBrowserMainParts(parameters); + return browser_main_parts_; } content::WebContentsView* diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index 26c0bb3cc..12fb3e433 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -26,9 +26,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient { CefContentBrowserClient(); virtual ~CefContentBrowserClient(); - void set_browser_main_parts(CefBrowserMainParts* parts) { - browser_main_parts_ = parts; - } CefBrowserMainParts* browser_main_parts() const { return browser_main_parts_; } diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 38fcbfb4f..8483ef047 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -14,7 +14,6 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/file_util.h" -#include "base/message_loop.h" #include "base/synchronization/waitable_event.h" #include "content/public/app/content_main.h" #include "content/public/app/content_main_runner.h" @@ -37,23 +36,6 @@ const int kNextBrowserIdReset = 1; // Global CefContext pointer CefRefPtr _Context; -namespace { - -// Used in multi-threaded message loop mode to observe shutdown of the UI -// thread. -class DestructionObserver : public MessageLoop::DestructionObserver { - public: - explicit DestructionObserver(base::WaitableEvent *event) : event_(event) {} - virtual void WillDestroyCurrentMessageLoop() { - MessageLoop::current()->RemoveDestructionObserver(this); - event_->Signal(); - delete this; - } - private: - base::WaitableEvent *event_; -}; - -} // namespace int CefExecuteProcess(const CefMainArgs& args, CefRefPtr application) { @@ -200,11 +182,12 @@ bool CefContext::Initialize(const CefMainArgs& args, cache_path_ = FilePath(CefString(&settings.cache_path)); +#if !defined(OS_WIN) if (settings.multi_threaded_message_loop) { - // TODO(cef): Figure out if we can support this. - NOTIMPLEMENTED(); + NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported."; return false; } +#endif main_delegate_.reset(new CefMainDelegate(application)); main_runner_.reset(content::ContentMainRunner::Create()); @@ -246,24 +229,20 @@ void CefContext::Shutdown() { if (settings_.multi_threaded_message_loop) { // Events that will be used to signal when shutdown is complete. Start in // non-signaled mode so that the event will block. - base::WaitableEvent browser_shutdown_event(false, false); base::WaitableEvent uithread_shutdown_event(false, false); // Finish shutdown on the UI thread. CEF_POST_TASK(CEF_UIT, base::Bind(&CefContext::FinishShutdownOnUIThread, this, - &browser_shutdown_event, &uithread_shutdown_event)); + &uithread_shutdown_event)); - // Block until browser shutdown is complete. - browser_shutdown_event.Wait(); + /// Block until UI thread shutdown is complete. + uithread_shutdown_event.Wait(); FinalizeShutdown(); - - // Block until UI thread shutdown is complete. - uithread_shutdown_event.Wait(); } else { // Finish shutdown on the current thread, which should be the UI thread. - FinishShutdownOnUIThread(NULL, NULL); + FinishShutdownOnUIThread(NULL); FinalizeShutdown(); } @@ -355,7 +334,6 @@ CefBrowserContext* CefContext::browser_context() const { } void CefContext::FinishShutdownOnUIThread( - base::WaitableEvent* browser_shutdown_event, base::WaitableEvent* uithread_shutdown_event) { CEF_REQUIRE_UIT(); @@ -376,19 +354,12 @@ void CefContext::FinishShutdownOnUIThread( (*it)->DestroyBrowser(); } - if (uithread_shutdown_event) { - // The destruction observer will signal the UI thread shutdown event when - // the UI thread has been destroyed. - MessageLoop::current()->AddDestructionObserver( - new DestructionObserver(uithread_shutdown_event)); - - // Signal the browser shutdown event now. - browser_shutdown_event->Signal(); - } + if (uithread_shutdown_event) + uithread_shutdown_event->Signal(); } void CefContext::FinalizeShutdown() { - // Shut down the browser runner. + // Shut down the browser runner or UI thread. main_delegate_->ShutdownBrowser(); // Shut down the content runner. diff --git a/libcef/browser/context.h b/libcef/browser/context.h index ab243144d..4dfe6b6ca 100644 --- a/libcef/browser/context.h +++ b/libcef/browser/context.h @@ -70,8 +70,7 @@ class CefContext : public CefBase { private: // Performs shutdown actions that need to occur on the UI thread before any // threads are destroyed. - void FinishShutdownOnUIThread(base::WaitableEvent* browser_shutdown_event, - base::WaitableEvent* uithread_shutdown_event); + void FinishShutdownOnUIThread(base::WaitableEvent* uithread_shutdown_event); // Destroys the main runner and related objects. void FinalizeShutdown(); diff --git a/libcef/browser/url_network_delegate.cc b/libcef/browser/url_network_delegate.cc index 238a9640f..51a629860 100644 --- a/libcef/browser/url_network_delegate.cc +++ b/libcef/browser/url_network_delegate.cc @@ -11,6 +11,7 @@ #include "libcef/common/request_impl.h" #include "net/base/net_errors.h" +#include "net/url_request/url_request.h" namespace { @@ -95,6 +96,8 @@ int CefNetworkDelegate::OnBeforeURLRequest( if (handler.get()) { CefRefPtr frame = browser->GetFrameForRequest(request); + GURL old_url = request->url(); + // Populate the request data. CefRefPtr requestPtr(new CefRequestImpl()); requestPtr->Set(request); @@ -105,7 +108,10 @@ int CefNetworkDelegate::OnBeforeURLRequest( return net::ERR_ABORTED; } - *new_url = GURL(std::string(requestPtr->GetURL())); + GURL url = GURL(std::string(requestPtr->GetURL())); + if (old_url != url) + new_url ->Swap(&url); + requestPtr->Get(request); } } diff --git a/libcef/common/content_client.cc b/libcef/common/content_client.cc index f7b23135f..7bbe01c5d 100644 --- a/libcef/common/content_client.cc +++ b/libcef/common/content_client.cc @@ -51,27 +51,20 @@ bool CefContentClient::CanHandleWhileSwappedOut(const IPC::Message& msg) { return false; } -std::string CefContentClient::GetUserAgent(bool* overriding) const { +std::string CefContentClient::GetUserAgent() const { + std::string product_version; + static CommandLine& command_line = *CommandLine::ForCurrentProcess(); - if (command_line.HasSwitch(switches::kUserAgent)) { - *overriding = true; - return command_line.GetSwitchValueASCII(switches::kUserAgent); + if (command_line.HasSwitch(switches::kProductVersion)) { + product_version = + command_line.GetSwitchValueASCII(switches::kProductVersion); } else { - std::string product_version; - - if (command_line.HasSwitch(switches::kProductVersion)) { - *overriding = true; - product_version = - command_line.GetSwitchValueASCII(switches::kProductVersion); - } else { - *overriding = false; - product_version = base::StringPrintf("Chrome/%d.%d.%d.%d", - CHROME_VERSION_MAJOR, CHROME_VERSION_MINOR, CHROME_VERSION_BUILD, - CHROME_VERSION_PATCH); - } - - return webkit_glue::BuildUserAgentFromProduct(product_version); + product_version = base::StringPrintf("Chrome/%d.%d.%d.%d", + CHROME_VERSION_MAJOR, CHROME_VERSION_MINOR, CHROME_VERSION_BUILD, + CHROME_VERSION_PATCH); } + + return webkit_glue::BuildUserAgentFromProduct(product_version); } string16 CefContentClient::GetLocalizedString(int message_id) const { diff --git a/libcef/common/content_client.h b/libcef/common/content_client.h index 908826dcb..adca0c2cb 100644 --- a/libcef/common/content_client.h +++ b/libcef/common/content_client.h @@ -30,7 +30,7 @@ class CefContentClient : public content::ContentClient { webkit::npapi::PluginList* plugin_list) OVERRIDE; virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) OVERRIDE; - virtual std::string GetUserAgent(bool* overriding) const OVERRIDE; + virtual std::string GetUserAgent() const OVERRIDE; virtual string16 GetLocalizedString(int message_id) const OVERRIDE; virtual base::StringPiece GetDataResource(int resource_id) const OVERRIDE; diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index 94991c91d..185fcf7c9 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -15,19 +15,26 @@ #include "base/file_path.h" #include "base/file_util.h" #include "base/path_service.h" +#include "base/synchronization/waitable_event.h" +#include "base/threading/thread.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/content_switches.h" +#include "content/public/common/main_function_params.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" +#if defined(OS_WIN) +#include // NOLINT(build/include_order) +#endif + #if defined(OS_MACOSX) #include "base/mac/bundle_locations.h" #include "base/mac/foundation_util.h" #include "content/public/common/content_paths.h" namespace { - + FilePath GetFrameworksPath() { // Start out with the path to the running executable. FilePath path; @@ -71,11 +78,53 @@ void OverrideChildProcessPath() { PathService::Override(content::CHILD_PROCESS_EXE, helper_path); } - + } // namespace #endif // OS_MACOSX +namespace { + +// Used to run the UI on a separate thread. +class CefUIThread : public base::Thread { + public: + explicit CefUIThread(const content::MainFunctionParams& main_function_params) + : base::Thread("CefUIThread"), + main_function_params_(main_function_params) { + } + + virtual void Init() OVERRIDE { +#if defined(OS_WIN) + // Initializes the COM library on the current thread. + CoInitialize(NULL); +#endif + + // Use our own browser process runner. + browser_runner_.reset(content::BrowserMainRunner::Create()); + + // Initialize browser process state. Results in a call to + // CefBrowserMain::GetMainMessageLoop(). + int exit_code = browser_runner_->Initialize(main_function_params_); + CHECK_EQ(exit_code, -1); + } + + virtual void CleanUp() OVERRIDE { + browser_runner_->Shutdown(); + browser_runner_.reset(NULL); + +#if defined(OS_WIN) + // Closes the COM library on the current thread. CoInitialize must + // be balanced by a corresponding call to CoUninitialize. + CoUninitialize(); +#endif + } + + protected: + content::MainFunctionParams main_function_params_; + scoped_ptr browser_runner_; +}; + +} // namespace CefMainDelegate::CefMainDelegate(CefRefPtr application) : content_client_(application) { @@ -88,7 +137,7 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) { #if defined(OS_MACOSX) OverrideFrameworkBundlePath(); #endif - + CommandLine* command_line = CommandLine::ForCurrentProcess(); std::string process_type = command_line->GetSwitchValueASCII(switches::kProcessType); @@ -190,14 +239,28 @@ int CefMainDelegate::RunProcess( const std::string& process_type, const content::MainFunctionParams& main_function_params) { if (process_type.empty()) { - // Use our own browser process runner. - browser_runner_.reset(content::BrowserMainRunner::Create()); + const CefSettings& settings = _Context->settings(); + if (!settings.multi_threaded_message_loop) { + // Use our own browser process runner. + browser_runner_.reset(content::BrowserMainRunner::Create()); - // Initialize browser process state. Results in a call to - // CefBrowserMain::GetMainMessageLoop(). - int exit_code = browser_runner_->Initialize(main_function_params); - if (exit_code >= 0) - return exit_code; + // Initialize browser process state. Results in a call to + // CefBrowserMain::GetMainMessageLoop(). + int exit_code = browser_runner_->Initialize(main_function_params); + if (exit_code >= 0) + return exit_code; + } else { + // Run the UI on a separate thread. + scoped_ptr thread; + thread.reset(new CefUIThread(main_function_params)); + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_UI; + if (!thread->StartWithOptions(options)) { + NOTREACHED() << "failed to start UI thread"; + return 1; + } + ui_thread_.swap(thread); + } return 0; } @@ -243,6 +306,11 @@ void CefMainDelegate::ShutdownBrowser() { browser_runner_->Shutdown(); browser_runner_.reset(NULL); } + if (ui_thread_.get()) { + // Blocks until the thread has stopped. + ui_thread_->Stop(); + ui_thread_.reset(); + } } void CefMainDelegate::InitializeContentClient( diff --git a/libcef/common/main_delegate.h b/libcef/common/main_delegate.h index d28835c86..bf381817b 100644 --- a/libcef/common/main_delegate.h +++ b/libcef/common/main_delegate.h @@ -15,6 +15,10 @@ #include "base/memory/scoped_ptr.h" #include "content/public/app/content_main_delegate.h" +namespace base { +class Thread; +} + namespace content { class BrowserMainRunner; } @@ -59,6 +63,8 @@ class CefMainDelegate : public content::ContentMainDelegate { void InitializeResourceBundle(); scoped_ptr browser_runner_; + scoped_ptr ui_thread_; + scoped_ptr browser_client_; scoped_ptr renderer_client_; scoped_ptr plugin_client_; diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 64deecebd..33bd82962 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -93,6 +93,13 @@ void ClientHandler::OnLoadError(CefRefPtr browser, const CefString& errorText, const CefString& failedUrl) { REQUIRE_UI_THREAD(); + + // Display a load error message. + std::stringstream ss; + ss << "

Failed to load URL " << std::string(failedUrl) << + " with error " << std::string(errorText) << " (" << errorCode << + ").

"; + frame->LoadString(ss.str(), failedUrl); } void ClientHandler::OnLoadingStateChange(CefRefPtr browser,