- 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
This commit is contained in:
Marshall Greenblatt 2012-04-11 18:00:55 +00:00
parent 1cd6e3b3e7
commit 9d200c109a
13 changed files with 132 additions and 84 deletions

View File

@ -37,17 +37,17 @@ CefBrowserMainParts::CefBrowserMainParts(
const content::MainFunctionParams& parameters) const content::MainFunctionParams& parameters)
: BrowserMainParts(), : BrowserMainParts(),
devtools_delegate_(NULL) { devtools_delegate_(NULL) {
CefContentBrowserClient* browser_client =
static_cast<CefContentBrowserClient*>(
content::GetContentClient()->browser());
browser_client->set_browser_main_parts(this);
} }
CefBrowserMainParts::~CefBrowserMainParts() { CefBrowserMainParts::~CefBrowserMainParts() {
} }
MessageLoop* CefBrowserMainParts::GetMainMessageLoop() { void CefBrowserMainParts::PreMainMessageLoopStart() {
return new CefBrowserMessageLoop(); if (!MessageLoop::current()) {
// Create the browser message loop.
message_loop_.reset(new CefBrowserMessageLoop());
message_loop_->set_thread_name("CrBrowserMain");
}
} }
int CefBrowserMainParts::PreCreateThreads() { int CefBrowserMainParts::PreCreateThreads() {

View File

@ -25,6 +25,7 @@ struct MainFunctionParams;
class CefBrowserContext; class CefBrowserContext;
class CefDevToolsDelegate; class CefDevToolsDelegate;
class MessageLoop;
class CefBrowserMainParts : public content::BrowserMainParts { class CefBrowserMainParts : public content::BrowserMainParts {
public: public:
@ -33,8 +34,7 @@ class CefBrowserMainParts : public content::BrowserMainParts {
virtual void PreEarlyInitialization() OVERRIDE {} virtual void PreEarlyInitialization() OVERRIDE {}
virtual void PostEarlyInitialization() OVERRIDE {} virtual void PostEarlyInitialization() OVERRIDE {}
virtual void PreMainMessageLoopStart() OVERRIDE {} virtual void PreMainMessageLoopStart() OVERRIDE;
virtual MessageLoop* GetMainMessageLoop() OVERRIDE;
virtual void PostMainMessageLoopStart() OVERRIDE {} virtual void PostMainMessageLoopStart() OVERRIDE {}
virtual void ToolkitInitialized() OVERRIDE {} virtual void ToolkitInitialized() OVERRIDE {}
virtual int PreCreateThreads() OVERRIDE; virtual int PreCreateThreads() OVERRIDE;
@ -52,6 +52,7 @@ class CefBrowserMainParts : public content::BrowserMainParts {
scoped_ptr<CefBrowserContext> browser_context_; scoped_ptr<CefBrowserContext> browser_context_;
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<ui::Clipboard> clipboard_; scoped_ptr<ui::Clipboard> clipboard_;
CefDevToolsDelegate* devtools_delegate_; CefDevToolsDelegate* devtools_delegate_;

View File

@ -9,7 +9,6 @@
#include "base/string_piece.h" #include "base/string_piece.h"
void CefBrowserMainParts::PlatformInitialize() { void CefBrowserMainParts::PlatformInitialize() {
gtk_init(NULL, NULL);
} }
void CefBrowserMainParts::PlatformCleanup() { void CefBrowserMainParts::PlatformCleanup() {

View File

@ -73,7 +73,8 @@ CefContentBrowserClient::~CefContentBrowserClient() {
content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts( content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
const content::MainFunctionParams& parameters) { const content::MainFunctionParams& parameters) {
return new CefBrowserMainParts(parameters); browser_main_parts_ = new CefBrowserMainParts(parameters);
return browser_main_parts_;
} }
content::WebContentsView* content::WebContentsView*

View File

@ -26,9 +26,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
CefContentBrowserClient(); CefContentBrowserClient();
virtual ~CefContentBrowserClient(); virtual ~CefContentBrowserClient();
void set_browser_main_parts(CefBrowserMainParts* parts) {
browser_main_parts_ = parts;
}
CefBrowserMainParts* browser_main_parts() const { CefBrowserMainParts* browser_main_parts() const {
return browser_main_parts_; return browser_main_parts_;
} }

View File

@ -14,7 +14,6 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/message_loop.h"
#include "base/synchronization/waitable_event.h" #include "base/synchronization/waitable_event.h"
#include "content/public/app/content_main.h" #include "content/public/app/content_main.h"
#include "content/public/app/content_main_runner.h" #include "content/public/app/content_main_runner.h"
@ -37,23 +36,6 @@ const int kNextBrowserIdReset = 1;
// Global CefContext pointer // Global CefContext pointer
CefRefPtr<CefContext> _Context; CefRefPtr<CefContext> _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, int CefExecuteProcess(const CefMainArgs& args,
CefRefPtr<CefApp> application) { CefRefPtr<CefApp> application) {
@ -200,11 +182,12 @@ bool CefContext::Initialize(const CefMainArgs& args,
cache_path_ = FilePath(CefString(&settings.cache_path)); cache_path_ = FilePath(CefString(&settings.cache_path));
#if !defined(OS_WIN)
if (settings.multi_threaded_message_loop) { if (settings.multi_threaded_message_loop) {
// TODO(cef): Figure out if we can support this. NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported.";
NOTIMPLEMENTED();
return false; return false;
} }
#endif
main_delegate_.reset(new CefMainDelegate(application)); main_delegate_.reset(new CefMainDelegate(application));
main_runner_.reset(content::ContentMainRunner::Create()); main_runner_.reset(content::ContentMainRunner::Create());
@ -246,24 +229,20 @@ void CefContext::Shutdown() {
if (settings_.multi_threaded_message_loop) { if (settings_.multi_threaded_message_loop) {
// Events that will be used to signal when shutdown is complete. Start in // Events that will be used to signal when shutdown is complete. Start in
// non-signaled mode so that the event will block. // non-signaled mode so that the event will block.
base::WaitableEvent browser_shutdown_event(false, false);
base::WaitableEvent uithread_shutdown_event(false, false); base::WaitableEvent uithread_shutdown_event(false, false);
// Finish shutdown on the UI thread. // Finish shutdown on the UI thread.
CEF_POST_TASK(CEF_UIT, CEF_POST_TASK(CEF_UIT,
base::Bind(&CefContext::FinishShutdownOnUIThread, this, base::Bind(&CefContext::FinishShutdownOnUIThread, this,
&browser_shutdown_event, &uithread_shutdown_event)); &uithread_shutdown_event));
// Block until browser shutdown is complete. /// Block until UI thread shutdown is complete.
browser_shutdown_event.Wait(); uithread_shutdown_event.Wait();
FinalizeShutdown(); FinalizeShutdown();
// Block until UI thread shutdown is complete.
uithread_shutdown_event.Wait();
} else { } else {
// Finish shutdown on the current thread, which should be the UI thread. // Finish shutdown on the current thread, which should be the UI thread.
FinishShutdownOnUIThread(NULL, NULL); FinishShutdownOnUIThread(NULL);
FinalizeShutdown(); FinalizeShutdown();
} }
@ -355,7 +334,6 @@ CefBrowserContext* CefContext::browser_context() const {
} }
void CefContext::FinishShutdownOnUIThread( void CefContext::FinishShutdownOnUIThread(
base::WaitableEvent* browser_shutdown_event,
base::WaitableEvent* uithread_shutdown_event) { base::WaitableEvent* uithread_shutdown_event) {
CEF_REQUIRE_UIT(); CEF_REQUIRE_UIT();
@ -376,19 +354,12 @@ void CefContext::FinishShutdownOnUIThread(
(*it)->DestroyBrowser(); (*it)->DestroyBrowser();
} }
if (uithread_shutdown_event) { if (uithread_shutdown_event)
// The destruction observer will signal the UI thread shutdown event when uithread_shutdown_event->Signal();
// the UI thread has been destroyed.
MessageLoop::current()->AddDestructionObserver(
new DestructionObserver(uithread_shutdown_event));
// Signal the browser shutdown event now.
browser_shutdown_event->Signal();
}
} }
void CefContext::FinalizeShutdown() { void CefContext::FinalizeShutdown() {
// Shut down the browser runner. // Shut down the browser runner or UI thread.
main_delegate_->ShutdownBrowser(); main_delegate_->ShutdownBrowser();
// Shut down the content runner. // Shut down the content runner.

View File

@ -70,8 +70,7 @@ class CefContext : public CefBase {
private: private:
// Performs shutdown actions that need to occur on the UI thread before any // Performs shutdown actions that need to occur on the UI thread before any
// threads are destroyed. // threads are destroyed.
void FinishShutdownOnUIThread(base::WaitableEvent* browser_shutdown_event, void FinishShutdownOnUIThread(base::WaitableEvent* uithread_shutdown_event);
base::WaitableEvent* uithread_shutdown_event);
// Destroys the main runner and related objects. // Destroys the main runner and related objects.
void FinalizeShutdown(); void FinalizeShutdown();

View File

@ -11,6 +11,7 @@
#include "libcef/common/request_impl.h" #include "libcef/common/request_impl.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
namespace { namespace {
@ -95,6 +96,8 @@ int CefNetworkDelegate::OnBeforeURLRequest(
if (handler.get()) { if (handler.get()) {
CefRefPtr<CefFrame> frame = browser->GetFrameForRequest(request); CefRefPtr<CefFrame> frame = browser->GetFrameForRequest(request);
GURL old_url = request->url();
// Populate the request data. // Populate the request data.
CefRefPtr<CefRequestImpl> requestPtr(new CefRequestImpl()); CefRefPtr<CefRequestImpl> requestPtr(new CefRequestImpl());
requestPtr->Set(request); requestPtr->Set(request);
@ -105,7 +108,10 @@ int CefNetworkDelegate::OnBeforeURLRequest(
return net::ERR_ABORTED; 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); requestPtr->Get(request);
} }
} }

View File

@ -51,27 +51,20 @@ bool CefContentClient::CanHandleWhileSwappedOut(const IPC::Message& msg) {
return false; return false;
} }
std::string CefContentClient::GetUserAgent(bool* overriding) const { std::string CefContentClient::GetUserAgent() const {
std::string product_version;
static CommandLine& command_line = *CommandLine::ForCurrentProcess(); static CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kUserAgent)) { if (command_line.HasSwitch(switches::kProductVersion)) {
*overriding = true; product_version =
return command_line.GetSwitchValueASCII(switches::kUserAgent); command_line.GetSwitchValueASCII(switches::kProductVersion);
} else { } else {
std::string product_version; product_version = base::StringPrintf("Chrome/%d.%d.%d.%d",
CHROME_VERSION_MAJOR, CHROME_VERSION_MINOR, CHROME_VERSION_BUILD,
if (command_line.HasSwitch(switches::kProductVersion)) { CHROME_VERSION_PATCH);
*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);
} }
return webkit_glue::BuildUserAgentFromProduct(product_version);
} }
string16 CefContentClient::GetLocalizedString(int message_id) const { string16 CefContentClient::GetLocalizedString(int message_id) const {

View File

@ -30,7 +30,7 @@ class CefContentClient : public content::ContentClient {
webkit::npapi::PluginList* plugin_list) OVERRIDE; webkit::npapi::PluginList* plugin_list) OVERRIDE;
virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE; virtual bool HasWebUIScheme(const GURL& url) const OVERRIDE;
virtual bool CanHandleWhileSwappedOut(const IPC::Message& msg) 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 string16 GetLocalizedString(int message_id) const OVERRIDE;
virtual base::StringPiece GetDataResource(int resource_id) const OVERRIDE; virtual base::StringPiece GetDataResource(int resource_id) const OVERRIDE;

View File

@ -15,19 +15,26 @@
#include "base/file_path.h" #include "base/file_path.h"
#include "base/file_util.h" #include "base/file_util.h"
#include "base/path_service.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/browser_main_runner.h"
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.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/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h" #include "ui/base/ui_base_paths.h"
#if defined(OS_WIN)
#include <Objbase.h> // NOLINT(build/include_order)
#endif
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
#include "base/mac/bundle_locations.h" #include "base/mac/bundle_locations.h"
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "content/public/common/content_paths.h" #include "content/public/common/content_paths.h"
namespace { namespace {
FilePath GetFrameworksPath() { FilePath GetFrameworksPath() {
// Start out with the path to the running executable. // Start out with the path to the running executable.
FilePath path; FilePath path;
@ -71,11 +78,53 @@ void OverrideChildProcessPath() {
PathService::Override(content::CHILD_PROCESS_EXE, helper_path); PathService::Override(content::CHILD_PROCESS_EXE, helper_path);
} }
} // namespace } // namespace
#endif // OS_MACOSX #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<content::BrowserMainRunner> browser_runner_;
};
} // namespace
CefMainDelegate::CefMainDelegate(CefRefPtr<CefApp> application) CefMainDelegate::CefMainDelegate(CefRefPtr<CefApp> application)
: content_client_(application) { : content_client_(application) {
@ -88,7 +137,7 @@ bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
OverrideFrameworkBundlePath(); OverrideFrameworkBundlePath();
#endif #endif
CommandLine* command_line = CommandLine::ForCurrentProcess(); CommandLine* command_line = CommandLine::ForCurrentProcess();
std::string process_type = std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType); command_line->GetSwitchValueASCII(switches::kProcessType);
@ -190,14 +239,28 @@ int CefMainDelegate::RunProcess(
const std::string& process_type, const std::string& process_type,
const content::MainFunctionParams& main_function_params) { const content::MainFunctionParams& main_function_params) {
if (process_type.empty()) { if (process_type.empty()) {
// Use our own browser process runner. const CefSettings& settings = _Context->settings();
browser_runner_.reset(content::BrowserMainRunner::Create()); 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 // Initialize browser process state. Results in a call to
// CefBrowserMain::GetMainMessageLoop(). // CefBrowserMain::GetMainMessageLoop().
int exit_code = browser_runner_->Initialize(main_function_params); int exit_code = browser_runner_->Initialize(main_function_params);
if (exit_code >= 0) if (exit_code >= 0)
return exit_code; return exit_code;
} else {
// Run the UI on a separate thread.
scoped_ptr<base::Thread> 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; return 0;
} }
@ -243,6 +306,11 @@ void CefMainDelegate::ShutdownBrowser() {
browser_runner_->Shutdown(); browser_runner_->Shutdown();
browser_runner_.reset(NULL); browser_runner_.reset(NULL);
} }
if (ui_thread_.get()) {
// Blocks until the thread has stopped.
ui_thread_->Stop();
ui_thread_.reset();
}
} }
void CefMainDelegate::InitializeContentClient( void CefMainDelegate::InitializeContentClient(

View File

@ -15,6 +15,10 @@
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "content/public/app/content_main_delegate.h" #include "content/public/app/content_main_delegate.h"
namespace base {
class Thread;
}
namespace content { namespace content {
class BrowserMainRunner; class BrowserMainRunner;
} }
@ -59,6 +63,8 @@ class CefMainDelegate : public content::ContentMainDelegate {
void InitializeResourceBundle(); void InitializeResourceBundle();
scoped_ptr<content::BrowserMainRunner> browser_runner_; scoped_ptr<content::BrowserMainRunner> browser_runner_;
scoped_ptr<base::Thread> ui_thread_;
scoped_ptr<CefContentBrowserClient> browser_client_; scoped_ptr<CefContentBrowserClient> browser_client_;
scoped_ptr<CefContentRendererClient> renderer_client_; scoped_ptr<CefContentRendererClient> renderer_client_;
scoped_ptr<CefContentPluginClient> plugin_client_; scoped_ptr<CefContentPluginClient> plugin_client_;

View File

@ -93,6 +93,13 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
const CefString& errorText, const CefString& errorText,
const CefString& failedUrl) { const CefString& failedUrl) {
REQUIRE_UI_THREAD(); REQUIRE_UI_THREAD();
// Display a load error message.
std::stringstream ss;
ss << "<html><body><h2>Failed to load URL " << std::string(failedUrl) <<
" with error " << std::string(errorText) << " (" << errorCode <<
").</h2></body></html>";
frame->LoadString(ss.str(), failedUrl);
} }
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser, void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,