- 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)
: BrowserMainParts(),
devtools_delegate_(NULL) {
CefContentBrowserClient* browser_client =
static_cast<CefContentBrowserClient*>(
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() {

View File

@ -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<CefBrowserContext> browser_context_;
scoped_ptr<MessageLoop> message_loop_;
scoped_ptr<ui::Clipboard> clipboard_;
CefDevToolsDelegate* devtools_delegate_;

View File

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

View File

@ -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*

View File

@ -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_;
}

View File

@ -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<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,
CefRefPtr<CefApp> 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.

View File

@ -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();

View File

@ -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<CefFrame> frame = browser->GetFrameForRequest(request);
GURL old_url = request->url();
// Populate the request data.
CefRefPtr<CefRequestImpl> 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);
}
}

View File

@ -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 {

View File

@ -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;

View File

@ -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 <Objbase.h> // 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<content::BrowserMainRunner> browser_runner_;
};
} // namespace
CefMainDelegate::CefMainDelegate(CefRefPtr<CefApp> 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<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;
}
@ -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(

View File

@ -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<content::BrowserMainRunner> browser_runner_;
scoped_ptr<base::Thread> ui_thread_;
scoped_ptr<CefContentBrowserClient> browser_client_;
scoped_ptr<CefContentRendererClient> renderer_client_;
scoped_ptr<CefContentPluginClient> plugin_client_;

View File

@ -93,6 +93,13 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
const CefString& errorText,
const CefString& failedUrl) {
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,