mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Compare commits
25 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
7f37a0a130 | ||
|
cd24143111 | ||
|
ead5caf25a | ||
|
c6dbc58c5f | ||
|
00188c7052 | ||
|
b472a8d9ea | ||
|
847fd4fd63 | ||
|
0a87d5f25f | ||
|
13f506f92a | ||
|
4c165056e1 | ||
|
461fa1fe83 | ||
|
bf8b64d70e | ||
|
004ef913a2 | ||
|
9df58650e1 | ||
|
a4f7e361be | ||
|
52427ce97f | ||
|
01f9a30b1d | ||
|
fd089efa24 | ||
|
3f956461bb | ||
|
4f87de9f52 | ||
|
532ce6b99c | ||
|
633c181700 | ||
|
7ed3a545e9 | ||
|
17f0192053 | ||
|
f7ae4ed0da |
2
BUILD.gn
2
BUILD.gn
@@ -403,6 +403,8 @@ static_library("libcef_static") {
|
||||
"libcef/browser/net/chrome_scheme_handler.h",
|
||||
"libcef/browser/net/cookie_store_proxy.cc",
|
||||
"libcef/browser/net/cookie_store_proxy.h",
|
||||
"libcef/browser/net/cookie_store_source.cc",
|
||||
"libcef/browser/net/cookie_store_source.h",
|
||||
"libcef/browser/net/crlset_file_util_impl.cc",
|
||||
"libcef/browser/net/devtools_scheme_handler.cc",
|
||||
"libcef/browser/net/devtools_scheme_handler.h",
|
||||
|
@@ -7,5 +7,5 @@
|
||||
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
|
||||
|
||||
{
|
||||
'chromium_checkout': 'refs/tags/69.0.3497.0',
|
||||
'chromium_checkout': 'refs/tags/69.0.3497.100',
|
||||
}
|
||||
|
@@ -368,6 +368,8 @@
|
||||
'tests/cefclient/browser/dialog_handler_gtk.cc',
|
||||
'tests/cefclient/browser/dialog_handler_gtk.h',
|
||||
'tests/cefclient/browser/main_context_impl_posix.cc',
|
||||
'tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc',
|
||||
'tests/cefclient/browser/main_message_loop_multithreaded_gtk.h',
|
||||
'tests/cefclient/browser/print_handler_gtk.cc',
|
||||
'tests/cefclient/browser/print_handler_gtk.h',
|
||||
'tests/cefclient/browser/resource_util_linux.cc',
|
||||
@@ -377,6 +379,8 @@
|
||||
'tests/cefclient/browser/root_window_views.h',
|
||||
'tests/cefclient/browser/temp_window_x11.cc',
|
||||
'tests/cefclient/browser/temp_window_x11.h',
|
||||
'tests/cefclient/browser/util_gtk.cc',
|
||||
'tests/cefclient/browser/util_gtk.h',
|
||||
'tests/cefclient/browser/views_menu_bar.cc',
|
||||
'tests/cefclient/browser/views_menu_bar.h',
|
||||
'tests/cefclient/browser/views_style.cc',
|
||||
|
@@ -346,6 +346,7 @@ if(OS_WINDOWS)
|
||||
1912 # VS2017 version 15.5
|
||||
1913 # VS2017 version 15.6
|
||||
1914 # VS2017 version 15.7
|
||||
1915 # VS2017 version 15.8
|
||||
)
|
||||
list(FIND supported_msvc_versions ${MSVC_VERSION} _index)
|
||||
if (${_index} EQUAL -1)
|
||||
|
@@ -51,6 +51,7 @@
|
||||
#include "include/base/cef_atomic_ref_count.h"
|
||||
#include "include/base/cef_build.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
namespace base {
|
||||
|
||||
|
@@ -181,7 +181,7 @@ typedef struct _cef_settings_t {
|
||||
// Set to true (1) to have the browser process message loop run in a separate
|
||||
// thread. If false (0) than the CefDoMessageLoopWork() function must be
|
||||
// called from your application message loop. This option is only supported on
|
||||
// Windows.
|
||||
// Windows and Linux.
|
||||
///
|
||||
int multi_threaded_message_loop;
|
||||
|
||||
|
@@ -10,7 +10,6 @@
|
||||
|
||||
#include "libcef/browser/browser_context_impl.h"
|
||||
#include "libcef/browser/browser_context_keyed_service_factories.h"
|
||||
#include "libcef/browser/browser_message_loop.h"
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/devtools_manager_delegate.h"
|
||||
@@ -34,6 +33,7 @@
|
||||
#include "extensions/common/constants.h"
|
||||
#include "net/base/net_module.h"
|
||||
#include "services/service_manager/embedder/result_codes.h"
|
||||
#include "ui/base/material_design/material_design_controller.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
|
||||
#if defined(USE_AURA)
|
||||
@@ -107,11 +107,6 @@ void CefBrowserMainParts::ToolkitInitialized() {
|
||||
}
|
||||
|
||||
void CefBrowserMainParts::PreMainMessageLoopStart() {
|
||||
if (!base::MessageLoop::current()) {
|
||||
// Create the browser message loop.
|
||||
message_loop_.reset(new CefBrowserMessageLoop());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
|
||||
chrome_extra_parts_[i]->PreMainMessageLoopStart();
|
||||
}
|
||||
@@ -156,6 +151,8 @@ void CefBrowserMainParts::PreMainMessageLoopRun() {
|
||||
display::Screen::SetScreenInstance(views::CreateDesktopScreen());
|
||||
#endif
|
||||
|
||||
ui::MaterialDesignController::Initialize();
|
||||
|
||||
// CEF's profile is a BrowserContext.
|
||||
PreProfileInit();
|
||||
|
||||
|
@@ -16,11 +16,6 @@
|
||||
#include "content/public/browser/browser_main_parts.h"
|
||||
#include "net/url_request/url_request_context_getter.h"
|
||||
|
||||
namespace base {
|
||||
class MessageLoop;
|
||||
class Thread;
|
||||
} // namespace base
|
||||
|
||||
namespace content {
|
||||
struct MainFunctionParams;
|
||||
}
|
||||
@@ -89,7 +84,6 @@ class CefBrowserMainParts : public content::BrowserMainParts {
|
||||
|
||||
CefRefPtr<CefRequestContextImpl> global_request_context_;
|
||||
CefDevToolsDelegate* devtools_delegate_; // Deletes itself.
|
||||
std::unique_ptr<base::MessageLoop> message_loop_;
|
||||
|
||||
std::unique_ptr<extensions::ExtensionsClient> extensions_client_;
|
||||
std::unique_ptr<extensions::ExtensionsBrowserClient>
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "services/service_manager/embedder/main.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
@@ -343,7 +344,7 @@ bool CefContext::Initialize(const CefMainArgs& args,
|
||||
init_thread_id_ = base::PlatformThread::CurrentId();
|
||||
settings_ = settings;
|
||||
|
||||
#if !defined(OS_WIN)
|
||||
#if !(defined(OS_WIN) || defined(OS_LINUX))
|
||||
if (settings.multi_threaded_message_loop) {
|
||||
NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported.";
|
||||
return false;
|
||||
@@ -526,6 +527,8 @@ void CefContext::FinishShutdownOnUIThread(
|
||||
|
||||
static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Shutdown();
|
||||
|
||||
ui::ResourceBundle::GetSharedInstance().CleanupOnUIThread();
|
||||
|
||||
if (uithread_shutdown_event)
|
||||
uithread_shutdown_event->Signal();
|
||||
}
|
||||
|
@@ -10,19 +10,18 @@
|
||||
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/net/cookie_store_source.h"
|
||||
#include "libcef/browser/net/network_delegate.h"
|
||||
#include "libcef/common/task_runner_impl.h"
|
||||
#include "libcef/common/time_util.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/format_macros.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "content/browser/storage_partition_impl.h"
|
||||
#include "net/cookies/cookie_util.h"
|
||||
#include "net/cookies/parsed_cookie.h"
|
||||
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -162,7 +161,7 @@ void CefCookieManagerImpl::GetCookieStore(
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(is_blocking_ || cookie_store_.get());
|
||||
DCHECK(is_blocking_ || cookie_source_);
|
||||
|
||||
// Binding ref-counted |this| to CookieStoreGetter may result in
|
||||
// heap-use-after-free if (a) the CookieStoreGetter contains the last
|
||||
@@ -185,8 +184,8 @@ void CefCookieManagerImpl::GetCookieStore(
|
||||
|
||||
net::CookieStore* CefCookieManagerImpl::GetExistingCookieStore() {
|
||||
CEF_REQUIRE_IOT();
|
||||
if (cookie_store_.get()) {
|
||||
return cookie_store_.get();
|
||||
if (cookie_source_) {
|
||||
return cookie_source_->GetCookieStore();
|
||||
} else if (request_context_impl_.get()) {
|
||||
net::CookieStore* cookie_store =
|
||||
request_context_impl_->GetExistingCookieStore();
|
||||
@@ -287,44 +286,13 @@ bool CefCookieManagerImpl::SetStoragePath(
|
||||
if (!path.empty())
|
||||
new_path = base::FilePath(path);
|
||||
|
||||
if (cookie_store_.get() &&
|
||||
((storage_path_.empty() && path.empty()) || storage_path_ == new_path)) {
|
||||
// The path has not changed so don't do anything.
|
||||
if (!cookie_source_) {
|
||||
cookie_source_.reset(new CefCookieStoreOwnerSource());
|
||||
}
|
||||
|
||||
cookie_source_->SetCookieStoragePath(new_path, persist_session_cookies);
|
||||
|
||||
RunAsyncCompletionOnIOThread(callback);
|
||||
return true;
|
||||
}
|
||||
|
||||
scoped_refptr<net::SQLitePersistentCookieStore> 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::ScopedAllowIO allow_io;
|
||||
if (base::DirectoryExists(new_path) || base::CreateDirectory(new_path)) {
|
||||
const base::FilePath& cookie_path = new_path.AppendASCII("Cookies");
|
||||
persistent_store = new net::SQLitePersistentCookieStore(
|
||||
cookie_path, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
|
||||
// Intentionally using the background task runner exposed by CEF to
|
||||
// facilitate unit test expectations. This task runner MUST be
|
||||
// configured with BLOCK_SHUTDOWN.
|
||||
CefContentBrowserClient::Get()->background_task_runner(),
|
||||
persist_session_cookies, NULL);
|
||||
} else {
|
||||
NOTREACHED() << "The cookie storage directory could not be created";
|
||||
storage_path_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new cookie store that will be used for all new requests. The old
|
||||
// cookie store, if any, will be automatically flushed and closed when no
|
||||
// longer referenced.
|
||||
cookie_store_.reset(new net::CookieMonster(persistent_store.get(), NULL));
|
||||
if (persistent_store.get() && persist_session_cookies)
|
||||
cookie_store_->SetPersistSessionCookies(true);
|
||||
storage_path_ = new_path;
|
||||
|
||||
// Restore the previously supported schemes.
|
||||
SetSupportedSchemesInternal(supported_schemes_, callback);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -502,10 +470,9 @@ void CefCookieManagerImpl::SetSupportedSchemesInternal(
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(is_blocking_ || cookie_store_.get());
|
||||
if (cookie_store_) {
|
||||
supported_schemes_ = schemes;
|
||||
SetCookieMonsterSchemes(cookie_store_.get(), supported_schemes_);
|
||||
DCHECK(is_blocking_ || cookie_source_);
|
||||
if (cookie_source_) {
|
||||
cookie_source_->SetCookieSupportedSchemes(schemes);
|
||||
}
|
||||
|
||||
RunAsyncCompletionOnIOThread(callback);
|
||||
|
@@ -15,6 +15,8 @@
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
|
||||
class CefCookieStoreOwnerSource;
|
||||
|
||||
// Implementation of the CefCookieManager interface.
|
||||
class CefCookieManagerImpl : public CefCookieManager {
|
||||
public:
|
||||
@@ -122,9 +124,7 @@ class CefCookieManagerImpl : public CefCookieManager {
|
||||
scoped_refptr<CefURLRequestContextGetterImpl> request_context_impl_;
|
||||
|
||||
// Used for cookie monsters owned by this object.
|
||||
base::FilePath storage_path_;
|
||||
std::vector<std::string> supported_schemes_;
|
||||
std::unique_ptr<net::CookieMonster> cookie_store_;
|
||||
std::unique_ptr<CefCookieStoreOwnerSource> cookie_source_;
|
||||
|
||||
// Must be the last member.
|
||||
base::WeakPtrFactory<CefCookieManagerImpl> weak_ptr_factory_;
|
||||
|
@@ -99,6 +99,7 @@
|
||||
}
|
||||
|
||||
- (void)cleanup:(id)window {
|
||||
[window_ setDelegate:nil];
|
||||
[self release];
|
||||
}
|
||||
|
||||
|
@@ -104,6 +104,7 @@ CefWindowX11::CefWindowX11(CefRefPtr<CefBrowserHostImpl> browser,
|
||||
InputOutput,
|
||||
CopyFromParent, // visual
|
||||
CWBackPixmap | CWOverrideRedirect, &swa);
|
||||
CHECK(xwindow_);
|
||||
|
||||
if (ui::PlatformEventSource::GetInstance())
|
||||
ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
|
||||
|
@@ -4,12 +4,12 @@
|
||||
|
||||
#include "libcef/browser/net/cookie_store_proxy.h"
|
||||
|
||||
#include "libcef/browser/cookie_manager_impl.h"
|
||||
#include "libcef/browser/net/url_request_context_impl.h"
|
||||
#include "include/cef_request_context.h"
|
||||
#include "libcef/browser/net/cookie_store_source.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "net/url_request/url_request_context.h"
|
||||
#include "net/cookies/cookie_change_dispatcher.h"
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -44,12 +44,10 @@ class NullCookieChangeDispatcher : public net::CookieChangeDispatcher {
|
||||
} // namespace
|
||||
|
||||
CefCookieStoreProxy::CefCookieStoreProxy(
|
||||
CefURLRequestContextImpl* parent,
|
||||
CefRefPtr<CefRequestContextHandler> handler)
|
||||
: parent_(parent), handler_(handler) {
|
||||
std::unique_ptr<CefCookieStoreSource> source)
|
||||
: source_(std::move(source)) {
|
||||
CEF_REQUIRE_IOT();
|
||||
DCHECK(parent_);
|
||||
DCHECK(handler_.get());
|
||||
DCHECK(source_);
|
||||
}
|
||||
|
||||
CefCookieStoreProxy::~CefCookieStoreProxy() {
|
||||
@@ -189,24 +187,5 @@ bool CefCookieStoreProxy::IsEphemeral() {
|
||||
|
||||
net::CookieStore* CefCookieStoreProxy::GetCookieStore() {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
CefRefPtr<CefCookieManager> manager = handler_->GetCookieManager();
|
||||
if (manager.get()) {
|
||||
// Use the cookie store provided by the manager. May be nullptr if the
|
||||
// cookie manager is blocking.
|
||||
return reinterpret_cast<CefCookieManagerImpl*>(manager.get())
|
||||
->GetExistingCookieStore();
|
||||
}
|
||||
|
||||
DCHECK(parent_);
|
||||
if (parent_) {
|
||||
// Use the cookie store from the parent.
|
||||
net::CookieStore* cookie_store = parent_->cookie_store();
|
||||
DCHECK(cookie_store);
|
||||
if (!cookie_store)
|
||||
LOG(ERROR) << "Cookie store does not exist";
|
||||
return cookie_store;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return source_->GetCookieStore();
|
||||
}
|
||||
|
@@ -6,19 +6,15 @@
|
||||
#define CEF_LIBCEF_BROWSER_COOKIE_STORE_PROXY_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_request_context_handler.h"
|
||||
|
||||
#include "net/cookies/cookie_store.h"
|
||||
|
||||
class CefURLRequestContextImpl;
|
||||
class CefCookieStoreSource;
|
||||
|
||||
// Proxies cookie requests to the CefRequestContextHandler or global cookie
|
||||
// store. Life span is controlled by CefURLRequestContextProxy. Only accessed on
|
||||
// the IO thread. See browser_context.h for an object relationship diagram.
|
||||
// Proxies cookie requests to a CefCookieStoreSource (see comments on the
|
||||
// implementation classes for details). Only accessed on the IO thread.
|
||||
class CefCookieStoreProxy : public net::CookieStore {
|
||||
public:
|
||||
CefCookieStoreProxy(CefURLRequestContextImpl* parent,
|
||||
CefRefPtr<CefRequestContextHandler> handler);
|
||||
explicit CefCookieStoreProxy(std::unique_ptr<CefCookieStoreSource> source);
|
||||
~CefCookieStoreProxy() override;
|
||||
|
||||
// net::CookieStore methods.
|
||||
@@ -52,11 +48,7 @@ class CefCookieStoreProxy : public net::CookieStore {
|
||||
private:
|
||||
net::CookieStore* GetCookieStore();
|
||||
|
||||
// The |parent_| pointer is kept alive by CefURLRequestContextGetterProxy
|
||||
// which has a ref to the owning CefURLRequestContextGetterImpl.
|
||||
CefURLRequestContextImpl* parent_;
|
||||
CefRefPtr<CefRequestContextHandler> handler_;
|
||||
|
||||
std::unique_ptr<CefCookieStoreSource> const source_;
|
||||
std::unique_ptr<net::CookieChangeDispatcher> null_dispatcher_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefCookieStoreProxy);
|
||||
|
110
libcef/browser/net/cookie_store_source.cc
Normal file
110
libcef/browser/net/cookie_store_source.cc
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
#include "libcef/browser/net/cookie_store_source.h"
|
||||
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/cookie_manager_impl.h"
|
||||
#include "libcef/browser/net/url_request_context_impl.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
|
||||
|
||||
CefCookieStoreHandlerSource::CefCookieStoreHandlerSource(
|
||||
CefURLRequestContextImpl* parent,
|
||||
CefRefPtr<CefRequestContextHandler> handler)
|
||||
: parent_(parent), handler_(handler) {
|
||||
DCHECK(parent_);
|
||||
DCHECK(handler_);
|
||||
}
|
||||
|
||||
net::CookieStore* CefCookieStoreHandlerSource::GetCookieStore() {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
CefRefPtr<CefCookieManager> manager = handler_->GetCookieManager();
|
||||
if (manager) {
|
||||
// Use the cookie store provided by the manager. May be nullptr if the
|
||||
// cookie manager is blocking.
|
||||
return reinterpret_cast<CefCookieManagerImpl*>(manager.get())
|
||||
->GetExistingCookieStore();
|
||||
}
|
||||
|
||||
DCHECK(parent_);
|
||||
if (parent_) {
|
||||
// Use the cookie store from the parent.
|
||||
net::CookieStore* cookie_store = parent_->cookie_store();
|
||||
DCHECK(cookie_store);
|
||||
if (!cookie_store)
|
||||
LOG(ERROR) << "Cookie store does not exist";
|
||||
return cookie_store;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CefCookieStoreOwnerSource::CefCookieStoreOwnerSource() {}
|
||||
|
||||
void CefCookieStoreOwnerSource::SetCookieStoragePath(
|
||||
const base::FilePath& path,
|
||||
bool persist_session_cookies) {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
if (cookie_store_ && ((path_.empty() && path.empty()) || path_ == path)) {
|
||||
// The path has not changed so don't do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_refptr<net::SQLitePersistentCookieStore> persistent_store;
|
||||
if (!path.empty()) {
|
||||
// TODO(cef): Move directory creation to the blocking pool instead of
|
||||
// allowing file IO on this thread.
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
if (base::DirectoryExists(path) || base::CreateDirectory(path)) {
|
||||
const base::FilePath& cookie_path = path.AppendASCII("Cookies");
|
||||
persistent_store = new net::SQLitePersistentCookieStore(
|
||||
cookie_path,
|
||||
content::BrowserThread::GetTaskRunnerForThread(
|
||||
content::BrowserThread::IO),
|
||||
// Intentionally using the background task runner exposed by CEF to
|
||||
// facilitate unit test expectations. This task runner MUST be
|
||||
// configured with BLOCK_SHUTDOWN.
|
||||
CefContentBrowserClient::Get()->background_task_runner(),
|
||||
persist_session_cookies, NULL);
|
||||
} else {
|
||||
NOTREACHED() << "The cookie storage directory could not be created";
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new cookie store that will be used for all new requests. The old
|
||||
// cookie store, if any, will be automatically flushed and closed when no
|
||||
// longer referenced.
|
||||
std::unique_ptr<net::CookieMonster> cookie_monster(
|
||||
new net::CookieMonster(persistent_store.get(), nullptr));
|
||||
if (persistent_store.get() && persist_session_cookies)
|
||||
cookie_monster->SetPersistSessionCookies(true);
|
||||
path_ = path;
|
||||
|
||||
// Restore the previously supported schemes.
|
||||
CefCookieManagerImpl::SetCookieMonsterSchemes(cookie_monster.get(),
|
||||
supported_schemes_);
|
||||
|
||||
cookie_store_ = std::move(cookie_monster);
|
||||
}
|
||||
|
||||
void CefCookieStoreOwnerSource::SetCookieSupportedSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
supported_schemes_ = schemes;
|
||||
CefCookieManagerImpl::SetCookieMonsterSchemes(
|
||||
static_cast<net::CookieMonster*>(cookie_store_.get()),
|
||||
supported_schemes_);
|
||||
}
|
||||
|
||||
net::CookieStore* CefCookieStoreOwnerSource::GetCookieStore() {
|
||||
CEF_REQUIRE_IOT();
|
||||
return cookie_store_.get();
|
||||
}
|
73
libcef/browser/net/cookie_store_source.h
Normal file
73
libcef/browser/net/cookie_store_source.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2018 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_COOKIE_STORE_SOURCE_H_
|
||||
#define CEF_LIBCEF_BROWSER_COOKIE_STORE_SOURCE_H_
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/cef_request_context_handler.h"
|
||||
|
||||
#include "base/macros.h"
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace net {
|
||||
class CookieStore;
|
||||
}
|
||||
|
||||
class CefURLRequestContextImpl;
|
||||
|
||||
// Abstract base class for CookieStore sources. Only accessed on the IO thread.
|
||||
class CefCookieStoreSource {
|
||||
public:
|
||||
virtual net::CookieStore* GetCookieStore() = 0;
|
||||
virtual ~CefCookieStoreSource() {}
|
||||
};
|
||||
|
||||
// Sources a cookie store that is created/owned by a CefCookieManager or the
|
||||
// parent context. Life span is controlled by CefURLRequestContextProxy. See
|
||||
// browser_context.h for an object relationship diagram.
|
||||
class CefCookieStoreHandlerSource : public CefCookieStoreSource {
|
||||
public:
|
||||
CefCookieStoreHandlerSource(CefURLRequestContextImpl* parent,
|
||||
CefRefPtr<CefRequestContextHandler> handler);
|
||||
|
||||
net::CookieStore* GetCookieStore() override;
|
||||
|
||||
private:
|
||||
// The |parent_| pointer is kept alive by CefURLRequestContextGetterProxy
|
||||
// which has a ref to the owning CefURLRequestContextGetterImpl.
|
||||
CefURLRequestContextImpl* parent_;
|
||||
CefRefPtr<CefRequestContextHandler> handler_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefCookieStoreHandlerSource);
|
||||
};
|
||||
|
||||
// Sources a cookie store that is created/owned by this object. Life span is
|
||||
// controlled by the owning URLRequestContext.
|
||||
class CefCookieStoreOwnerSource : public CefCookieStoreSource {
|
||||
public:
|
||||
CefCookieStoreOwnerSource();
|
||||
|
||||
void SetCookieStoragePath(const base::FilePath& path,
|
||||
bool persist_session_cookies);
|
||||
void SetCookieSupportedSchemes(const std::vector<std::string>& schemes);
|
||||
|
||||
net::CookieStore* GetCookieStore() override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<net::CookieStore> cookie_store_;
|
||||
base::FilePath path_;
|
||||
std::vector<std::string> supported_schemes_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefCookieStoreOwnerSource);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_COOKIE_STORE_SOURCE_H_
|
@@ -445,10 +445,7 @@ net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired(
|
||||
}
|
||||
|
||||
bool CefNetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
|
||||
const net::CookieList& cookie_list,
|
||||
bool allowed_from_caller) {
|
||||
if (!allowed_from_caller)
|
||||
return false;
|
||||
const net::CookieList& cookie_list) {
|
||||
if (net_util::IsInternalRequest(&request))
|
||||
return true;
|
||||
|
||||
@@ -475,10 +472,7 @@ bool CefNetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
|
||||
|
||||
bool CefNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
|
||||
const net::CanonicalCookie& cookie,
|
||||
net::CookieOptions* options,
|
||||
bool allowed_from_caller) {
|
||||
if (!allowed_from_caller)
|
||||
return false;
|
||||
net::CookieOptions* options) {
|
||||
if (net_util::IsInternalRequest(&request))
|
||||
return true;
|
||||
|
||||
|
@@ -41,12 +41,10 @@ class CefNetworkDelegate : public net::NetworkDelegateImpl {
|
||||
bool started,
|
||||
int net_error) override;
|
||||
bool OnCanGetCookies(const net::URLRequest& request,
|
||||
const net::CookieList& cookie_list,
|
||||
bool allowed_from_caller) override;
|
||||
const net::CookieList& cookie_list) override;
|
||||
bool OnCanSetCookie(const net::URLRequest& request,
|
||||
const net::CanonicalCookie& cookie,
|
||||
net::CookieOptions* options,
|
||||
bool allowed_from_caller) override;
|
||||
net::CookieOptions* options) override;
|
||||
bool OnCanAccessFile(const net::URLRequest& request,
|
||||
const base::FilePath& original_path,
|
||||
const base::FilePath& absolute_path) const override;
|
||||
|
@@ -10,6 +10,8 @@
|
||||
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/cookie_manager_impl.h"
|
||||
#include "libcef/browser/net/cookie_store_proxy.h"
|
||||
#include "libcef/browser/net/cookie_store_source.h"
|
||||
#include "libcef/browser/net/network_delegate.h"
|
||||
#include "libcef/browser/net/scheme_handler.h"
|
||||
#include "libcef/browser/net/url_request_interceptor.h"
|
||||
@@ -18,7 +20,6 @@
|
||||
#include "libcef/common/content_client.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/stl_util.h"
|
||||
@@ -43,7 +44,6 @@
|
||||
#include "net/cert/multi_log_ct_verifier.h"
|
||||
#include "net/cookies/cookie_monster.h"
|
||||
#include "net/dns/host_resolver.h"
|
||||
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
|
||||
#include "net/ftp/ftp_network_layer.h"
|
||||
#include "net/http/http_auth_handler_factory.h"
|
||||
#include "net/http/http_auth_preferences.h"
|
||||
@@ -473,57 +473,21 @@ void CefURLRequestContextGetterImpl::SetCookieStoragePath(
|
||||
const base::FilePath& path,
|
||||
bool persist_session_cookies) {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
if (io_state_->url_request_context_->cookie_store() &&
|
||||
((io_state_->cookie_store_path_.empty() && path.empty()) ||
|
||||
io_state_->cookie_store_path_ == path)) {
|
||||
// The path has not changed so don't do anything.
|
||||
return;
|
||||
if (!io_state_->cookie_source_) {
|
||||
// Use a proxy because we can't change the URLRequestContext's CookieStore
|
||||
// during runtime.
|
||||
io_state_->cookie_source_ = new CefCookieStoreOwnerSource();
|
||||
io_state_->storage_->set_cookie_store(std::make_unique<CefCookieStoreProxy>(
|
||||
base::WrapUnique(io_state_->cookie_source_)));
|
||||
}
|
||||
|
||||
scoped_refptr<net::SQLitePersistentCookieStore> persistent_store;
|
||||
if (!path.empty()) {
|
||||
// TODO(cef): Move directory creation to the blocking pool instead of
|
||||
// allowing file IO on this thread.
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
if (base::DirectoryExists(path) || base::CreateDirectory(path)) {
|
||||
const base::FilePath& cookie_path = path.AppendASCII("Cookies");
|
||||
persistent_store = new net::SQLitePersistentCookieStore(
|
||||
cookie_path, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
|
||||
// Intentionally using the background task runner exposed by CEF to
|
||||
// facilitate unit test expectations. This task runner MUST be
|
||||
// configured with BLOCK_SHUTDOWN.
|
||||
CefContentBrowserClient::Get()->background_task_runner(),
|
||||
persist_session_cookies, NULL);
|
||||
} else {
|
||||
NOTREACHED() << "The cookie storage directory could not be created";
|
||||
}
|
||||
}
|
||||
|
||||
// Set the new cookie store that will be used for all new requests. The old
|
||||
// cookie store, if any, will be automatically flushed and closed when no
|
||||
// longer referenced.
|
||||
std::unique_ptr<net::CookieMonster> cookie_monster(
|
||||
new net::CookieMonster(persistent_store.get(), NULL));
|
||||
if (persistent_store.get() && persist_session_cookies)
|
||||
cookie_monster->SetPersistSessionCookies(true);
|
||||
io_state_->cookie_store_path_ = path;
|
||||
|
||||
// Restore the previously supported schemes.
|
||||
CefCookieManagerImpl::SetCookieMonsterSchemes(
|
||||
cookie_monster.get(), io_state_->cookie_supported_schemes_);
|
||||
|
||||
io_state_->storage_->set_cookie_store(std::move(cookie_monster));
|
||||
io_state_->cookie_source_->SetCookieStoragePath(path,
|
||||
persist_session_cookies);
|
||||
}
|
||||
|
||||
void CefURLRequestContextGetterImpl::SetCookieSupportedSchemes(
|
||||
const std::vector<std::string>& schemes) {
|
||||
CEF_REQUIRE_IOT();
|
||||
|
||||
io_state_->cookie_supported_schemes_ = schemes;
|
||||
CefCookieManagerImpl::SetCookieMonsterSchemes(
|
||||
static_cast<net::CookieMonster*>(GetExistingCookieStore()),
|
||||
io_state_->cookie_supported_schemes_);
|
||||
io_state_->cookie_source_->SetCookieSupportedSchemes(schemes);
|
||||
}
|
||||
|
||||
void CefURLRequestContextGetterImpl::AddHandler(
|
||||
@@ -540,9 +504,8 @@ void CefURLRequestContextGetterImpl::AddHandler(
|
||||
net::CookieStore* CefURLRequestContextGetterImpl::GetExistingCookieStore()
|
||||
const {
|
||||
CEF_REQUIRE_IOT();
|
||||
if (io_state_->url_request_context_ &&
|
||||
io_state_->url_request_context_->cookie_store()) {
|
||||
return io_state_->url_request_context_->cookie_store();
|
||||
if (io_state_->cookie_source_) {
|
||||
return io_state_->cookie_source_->GetCookieStore();
|
||||
}
|
||||
|
||||
LOG(ERROR) << "Cookie store does not exist";
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "net/url_request/url_request_job_factory.h"
|
||||
|
||||
class CefCookieStoreOwnerSource;
|
||||
class PrefRegistrySimple;
|
||||
class PrefService;
|
||||
|
||||
@@ -113,8 +114,8 @@ class CefURLRequestContextGetterImpl : public CefURLRequestContextGetter {
|
||||
content::ProtocolHandlerMap protocol_handlers_;
|
||||
content::URLRequestInterceptorScopedVector request_interceptors_;
|
||||
|
||||
base::FilePath cookie_store_path_;
|
||||
std::vector<std::string> cookie_supported_schemes_;
|
||||
// Owned by the URLRequestContextStorage.
|
||||
CefCookieStoreOwnerSource* cookie_source_ = nullptr;
|
||||
|
||||
std::vector<CefRefPtr<CefRequestContextHandler>> handler_list_;
|
||||
|
||||
|
@@ -5,6 +5,7 @@
|
||||
#include "libcef/browser/net/url_request_context_proxy.h"
|
||||
|
||||
#include "libcef/browser/net/cookie_store_proxy.h"
|
||||
#include "libcef/browser/net/cookie_store_source.h"
|
||||
#include "libcef/browser/net/url_request_context_impl.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
@@ -16,7 +17,8 @@ CefURLRequestContextProxy::CefURLRequestContextProxy(
|
||||
DCHECK(handler.get());
|
||||
|
||||
// Cookie store that proxies to the browser implementation.
|
||||
cookie_store_proxy_.reset(new CefCookieStoreProxy(parent, handler));
|
||||
cookie_store_proxy_.reset(new CefCookieStoreProxy(
|
||||
std::make_unique<CefCookieStoreHandlerSource>(parent, handler)));
|
||||
set_cookie_store(cookie_store_proxy_.get());
|
||||
|
||||
// All other values refer to the parent request context.
|
||||
|
@@ -27,6 +27,7 @@
|
||||
#include "content/browser/bad_message.h"
|
||||
#include "content/browser/compositor/image_transport_factory.h"
|
||||
#include "content/browser/frame_host/render_widget_host_view_guest.h"
|
||||
#include "content/browser/renderer_host/cursor_manager.h"
|
||||
#include "content/browser/renderer_host/dip_util.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_delegate.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
@@ -278,6 +279,8 @@ CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
if (browser_impl_.get())
|
||||
ResizeRootLayer(false);
|
||||
|
||||
cursor_manager_.reset(new content::CursorManager(this));
|
||||
|
||||
// Do this last because it may result in a call to SetNeedsBeginFrames.
|
||||
render_widget_host_->SetView(this);
|
||||
}
|
||||
@@ -633,6 +636,10 @@ void CefRenderWidgetHostViewOSR::UpdateCursor(
|
||||
#endif
|
||||
}
|
||||
|
||||
content::CursorManager* CefRenderWidgetHostViewOSR::GetCursorManager() {
|
||||
return cursor_manager_.get();
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::SetIsLoading(bool is_loading) {}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::RenderProcessGone(
|
||||
|
@@ -39,6 +39,7 @@ class RenderWidgetHost;
|
||||
class RenderWidgetHostImpl;
|
||||
class RenderWidgetHostViewGuest;
|
||||
class BackingStore;
|
||||
class CursorManager;
|
||||
} // namespace content
|
||||
|
||||
class CefBeginFrameTimer;
|
||||
@@ -147,6 +148,7 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
int error_code) override;
|
||||
void Destroy() override;
|
||||
void SetTooltipText(const base::string16& tooltip_text) override;
|
||||
content::CursorManager* GetCursorManager() override;
|
||||
|
||||
gfx::Size GetCompositorViewportPixelSize() const override;
|
||||
void CopyFromSurface(
|
||||
@@ -345,6 +347,8 @@ class CefRenderWidgetHostViewOSR : public content::RenderWidgetHostViewBase,
|
||||
std::unique_ptr<ui::XScopedCursor> invisible_cursor_;
|
||||
#endif
|
||||
|
||||
std::unique_ptr<content::CursorManager> cursor_manager_;
|
||||
|
||||
// Used to control the VSync rate in subprocesses when BeginFrame scheduling
|
||||
// is enabled.
|
||||
std::unique_ptr<CefBeginFrameTimer> begin_frame_timer_;
|
||||
|
@@ -171,8 +171,8 @@ void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget(
|
||||
|
||||
mac_helper_ = new MacHelper(this);
|
||||
browser_compositor_.reset(new content::BrowserCompositorMac(
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), true,
|
||||
GetDisplay(), AllocateFrameSinkId(is_guest_view_hack)));
|
||||
mac_helper_, mac_helper_, render_widget_host_->is_hidden(), GetDisplay(),
|
||||
AllocateFrameSinkId(is_guest_view_hack)));
|
||||
}
|
||||
|
||||
void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() {
|
||||
|
@@ -323,7 +323,7 @@ void CefWindowView::CreateWidget() {
|
||||
};
|
||||
|
||||
Atom mwmHintsProperty = XInternAtom(display, "_MOTIF_WM_HINTS", 0);
|
||||
struct MwmHints hints;
|
||||
struct MwmHints hints = {};
|
||||
hints.flags = MWM_HINTS_DECORATIONS;
|
||||
hints.decorations = 0;
|
||||
XChangeProperty(display, window, mwmHintsProperty, mwmHintsProperty, 32,
|
||||
|
@@ -96,9 +96,6 @@ CefString CefDragDataImpl::GetFragmentBaseURL() {
|
||||
|
||||
CefString CefDragDataImpl::GetFileName() {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
if (data_.file_contents_content_disposition.empty())
|
||||
return CefString();
|
||||
|
||||
base::Optional<base::FilePath> filename =
|
||||
data_.GetSafeFilenameForImageFileContents();
|
||||
return filename ? CefString(filename->value()) : CefString();
|
||||
|
@@ -3,6 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "libcef/common/main_delegate.h"
|
||||
#include "libcef/browser/browser_message_loop.h"
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/common/cef_switches.h"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "libcef/renderer/content_renderer_client.h"
|
||||
#include "libcef/utility/content_utility_client.h"
|
||||
|
||||
#include "base/at_exit.h"
|
||||
#include "base/base_switches.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/files/file_path.h"
|
||||
@@ -39,7 +41,6 @@
|
||||
#include "pdf/pdf_ppapi.h"
|
||||
#include "services/service_manager/sandbox/switches.h"
|
||||
#include "ui/base/layout.h"
|
||||
#include "ui/base/material_design/material_design_controller.h"
|
||||
#include "ui/base/resource/resource_bundle.h"
|
||||
#include "ui/base/ui_base_paths.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
@@ -266,6 +267,14 @@ class CefUIThread : public base::Thread {
|
||||
browser_runner_->Shutdown();
|
||||
browser_runner_.reset(NULL);
|
||||
|
||||
// Release MessagePump resources registered with the AtExitManager.
|
||||
base::MessageLoop* ml = const_cast<base::MessageLoop*>(message_loop());
|
||||
base::MessageLoopCurrent::UnbindFromCurrentThreadInternal(ml);
|
||||
ml->ReleasePump();
|
||||
|
||||
// Run exit callbacks on the UI thread to avoid sequence check failures.
|
||||
base::AtExitManager::ProcessCallbacksNow();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Closes the COM library on the current thread. CoInitialize must
|
||||
// be balanced by a corresponding call to CoUninitialize.
|
||||
@@ -290,6 +299,11 @@ CefMainDelegate::CefMainDelegate(CefRefPtr<CefApp> application)
|
||||
|
||||
CefMainDelegate::~CefMainDelegate() {}
|
||||
|
||||
void CefMainDelegate::PreContentInitialization() {
|
||||
// Create the main message loop.
|
||||
message_loop_.reset(new CefBrowserMessageLoop());
|
||||
}
|
||||
|
||||
bool CefMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type =
|
||||
@@ -636,6 +650,9 @@ void CefMainDelegate::ShutdownBrowser() {
|
||||
browser_runner_->Shutdown();
|
||||
browser_runner_.reset(NULL);
|
||||
}
|
||||
|
||||
message_loop_.reset();
|
||||
|
||||
if (ui_thread_.get()) {
|
||||
// Blocks until the thread has stopped.
|
||||
ui_thread_->Stop();
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
namespace base {
|
||||
class CommandLine;
|
||||
class MessageLoop;
|
||||
class Thread;
|
||||
} // namespace base
|
||||
|
||||
@@ -32,6 +33,7 @@ class CefMainDelegate : public content::ContentMainDelegate {
|
||||
explicit CefMainDelegate(CefRefPtr<CefApp> application);
|
||||
~CefMainDelegate() override;
|
||||
|
||||
void PreContentInitialization() override;
|
||||
bool BasicStartupComplete(int* exit_code) override;
|
||||
void PreSandboxStartup() override;
|
||||
void SandboxInitialized(const std::string& process_type) override;
|
||||
@@ -55,6 +57,7 @@ class CefMainDelegate : public content::ContentMainDelegate {
|
||||
private:
|
||||
void InitializeResourceBundle();
|
||||
|
||||
std::unique_ptr<base::MessageLoop> message_loop_;
|
||||
std::unique_ptr<content::BrowserMainRunner> browser_runner_;
|
||||
std::unique_ptr<base::Thread> ui_thread_;
|
||||
|
||||
|
@@ -3,8 +3,13 @@
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "libcef/common/net/net_resource_provider.h"
|
||||
#include "libcef/common/content_client.h"
|
||||
|
||||
#include "chrome/common/net/net_resource_provider.h"
|
||||
|
||||
base::StringPiece NetResourceProvider(int key) {
|
||||
return CefContentClient::Get()->GetDataResource(key, ui::SCALE_FACTOR_NONE);
|
||||
// Chrome performs substitution of localized strings for directory listings.
|
||||
base::StringPiece value = chrome_common_net::NetResourceProvider(key);
|
||||
if (value.empty())
|
||||
LOG(ERROR) << "No data resource available for id " << key;
|
||||
return value;
|
||||
}
|
||||
|
@@ -117,7 +117,8 @@ class CefRenderURLRequest::Context
|
||||
|
||||
loader_ =
|
||||
CefContentRendererClient::Get()->url_loader_factory()->CreateURLLoader(
|
||||
urlRequest, task_runner_.get());
|
||||
urlRequest, blink::scheduler::WebResourceLoadingTaskRunnerHandle::
|
||||
CreateUnprioritized(task_runner_.get()));
|
||||
loader_->LoadAsynchronously(urlRequest, url_client_.get());
|
||||
return true;
|
||||
}
|
||||
|
@@ -314,6 +314,8 @@ class V8TrackArrayBuffer : public CefTrackNode {
|
||||
buffer_(buffer),
|
||||
release_callback_(release_callback) {
|
||||
DCHECK(isolate_);
|
||||
isolate_->AdjustAmountOfExternalAllocatedMemory(
|
||||
static_cast<int>(sizeof(V8TrackArrayBuffer)));
|
||||
}
|
||||
|
||||
~V8TrackArrayBuffer() {
|
||||
@@ -330,6 +332,13 @@ class V8TrackArrayBuffer : public CefTrackNode {
|
||||
|
||||
void Neuter() { buffer_ = nullptr; }
|
||||
|
||||
// Attach this track object to the specified V8 object.
|
||||
void AttachTo(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::ArrayBuffer> arrayBuffer) {
|
||||
SetPrivate(context, arrayBuffer, kCefTrackObject,
|
||||
v8::External::New(isolate_, this));
|
||||
}
|
||||
|
||||
// Retrieve the track object for the specified V8 object.
|
||||
static V8TrackArrayBuffer* Unwrap(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::Object> object) {
|
||||
@@ -341,35 +350,10 @@ class V8TrackArrayBuffer : public CefTrackNode {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Attach this track object to the specified V8 object.
|
||||
void AttachTo(v8::Local<v8::Context> context,
|
||||
v8::Local<v8::ArrayBuffer> arrayBuffer) {
|
||||
isolate_->AdjustAmountOfExternalAllocatedMemory(
|
||||
static_cast<int>(sizeof(V8TrackArrayBuffer)));
|
||||
|
||||
SetPrivate(context, arrayBuffer, kCefTrackObject,
|
||||
v8::External::New(isolate_, this));
|
||||
|
||||
handle_.Reset(isolate_, arrayBuffer);
|
||||
handle_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
|
||||
handle_.MarkIndependent();
|
||||
}
|
||||
|
||||
private:
|
||||
static void FirstWeakCallback(
|
||||
const v8::WeakCallbackInfo<V8TrackArrayBuffer>& data) {
|
||||
V8TrackArrayBuffer* wrapper = data.GetParameter();
|
||||
if (wrapper->buffer_ != nullptr) {
|
||||
wrapper->release_callback_->ReleaseBuffer(wrapper->buffer_);
|
||||
wrapper->buffer_ = nullptr;
|
||||
}
|
||||
wrapper->handle_.Reset();
|
||||
}
|
||||
|
||||
v8::Isolate* isolate_;
|
||||
void* buffer_;
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback_;
|
||||
v8::Persistent<v8::ArrayBuffer> handle_;
|
||||
};
|
||||
|
||||
// Object wrapped in a v8::External and passed as the Data argument to
|
||||
|
@@ -52,6 +52,10 @@ patches = [
|
||||
#
|
||||
# Revert change that removes MessageLoopForUI constructor.
|
||||
# https://chromium-review.googlesource.com/751322
|
||||
#
|
||||
# Add MessageLoop::ReleasePump to fix crashes during shutdown with multi-
|
||||
# threaded message loop mode.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2362
|
||||
'name': 'message_loop',
|
||||
},
|
||||
{
|
||||
@@ -125,12 +129,6 @@ patches = [
|
||||
# https://codereview.chromium.org/208313009
|
||||
'name': 'ui_dragdrop_355390',
|
||||
},
|
||||
{
|
||||
# Windows: Fix AtExitManager assertion on *ServiceFactory destruction during
|
||||
# multi-threaded message loop shutdown.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/1680
|
||||
'name': 'service_factory_1680',
|
||||
},
|
||||
{
|
||||
# Make URLRequest::set_is_pending() public so that it can be called from
|
||||
# CefRequestInterceptor::MaybeInterceptResponse().
|
||||
@@ -382,11 +380,32 @@ patches = [
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2466
|
||||
'name': 'linux_poll_2466',
|
||||
},
|
||||
{
|
||||
# Allow ResourceBundle creation/destruction on the main thread and usage on
|
||||
# the UI thread.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2398
|
||||
'name': 'resource_bundle_2512',
|
||||
},
|
||||
{
|
||||
# Fix tools/clang/scripts/update.py failure with custom VS toolchain on
|
||||
# Windows. This needs to be done in DEPS because it executes during the
|
||||
# `gclient runhooks` step.
|
||||
# https://bugs.chromium.org/p/chromium/issues/detail?id=863130
|
||||
'name': 'DEPS',
|
||||
},
|
||||
{
|
||||
# RTL document in <iframe> should have left-hand scrollbar.
|
||||
# https://bugs.chromium.org/p/chromium/issues/detail?id=250514#c34
|
||||
'name': 'webkit_rtl_scrollbars_250514',
|
||||
},
|
||||
{
|
||||
# Fix redraw of OSR PDF viewer.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2507
|
||||
'name': 'browser_child_frame_2507',
|
||||
},
|
||||
{
|
||||
# macOS: Fix crash when showing a select popup with CefDoMessageLoopWork.
|
||||
# https://bitbucket.org/chromiumembedded/cef/issues/2495
|
||||
'name': 'message_pump_mac_2495',
|
||||
}
|
||||
]
|
||||
|
20
patch/patches/browser_child_frame_2507.patch
Normal file
20
patch/patches/browser_child_frame_2507.patch
Normal file
@@ -0,0 +1,20 @@
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_child_frame.cc content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
index 08e68296f2a6..0bcc696cf0cc 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
@@ -623,6 +623,7 @@ void RenderWidgetHostViewChildFrame::SubmitCompositorFrame(
|
||||
"RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
|
||||
support_->SubmitCompositorFrame(local_surface_id, std::move(frame),
|
||||
std::move(hit_test_region_list));
|
||||
+ ProcessFrameSwappedCallbacks();
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewChildFrame::OnDidNotProduceFrame(
|
||||
@@ -914,7 +915,6 @@ void RenderWidgetHostViewChildFrame::OnFirstSurfaceActivation(
|
||||
last_activated_surface_info_ = surface_info;
|
||||
has_frame_ = true;
|
||||
FirstSurfaceActivation(surface_info);
|
||||
- ProcessFrameSwappedCallbacks();
|
||||
}
|
||||
|
||||
void RenderWidgetHostViewChildFrame::OnFrameTokenChanged(uint32_t frame_token) {
|
@@ -1,8 +1,8 @@
|
||||
diff --git content/browser/renderer_host/browser_compositor_view_mac.h content/browser/renderer_host/browser_compositor_view_mac.h
|
||||
index 513e70d2b738..f821043e0a4e 100644
|
||||
index 46be85eea4b5..06177efbb25d 100644
|
||||
--- content/browser/renderer_host/browser_compositor_view_mac.h
|
||||
+++ content/browser/renderer_host/browser_compositor_view_mac.h
|
||||
@@ -59,6 +59,8 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
|
||||
@@ -58,6 +58,8 @@ class CONTENT_EXPORT BrowserCompositorMac : public DelegatedFrameHostClient,
|
||||
|
||||
// These will not return nullptr until Destroy is called.
|
||||
DelegatedFrameHost* GetDelegatedFrameHost();
|
||||
@@ -12,10 +12,10 @@ index 513e70d2b738..f821043e0a4e 100644
|
||||
// Ensure that the currect compositor frame be cleared (even if it is
|
||||
// potentially visible).
|
||||
diff --git content/browser/renderer_host/browser_compositor_view_mac.mm content/browser/renderer_host/browser_compositor_view_mac.mm
|
||||
index 72ad272b4d1a..0b4cd87019bf 100644
|
||||
index 92afcc779106..222e7a528522 100644
|
||||
--- content/browser/renderer_host/browser_compositor_view_mac.mm
|
||||
+++ content/browser/renderer_host/browser_compositor_view_mac.mm
|
||||
@@ -87,6 +87,12 @@ DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
|
||||
@@ -86,6 +86,12 @@ DelegatedFrameHost* BrowserCompositorMac::GetDelegatedFrameHost() {
|
||||
return delegated_frame_host_.get();
|
||||
}
|
||||
|
||||
|
@@ -208,10 +208,10 @@ index 9e3511a9dabc..83dfee968d59 100644
|
||||
RenderWidgetHost* render_widget_host) override;
|
||||
void SetPageTitle(const base::string16& title) override;
|
||||
diff --git content/browser/web_contents/web_contents_view_mac.h content/browser/web_contents/web_contents_view_mac.h
|
||||
index 2e3f4f8a56d4..75ef26b5381a 100644
|
||||
index 7f80c1b1d829..bcbd04bc4e6c 100644
|
||||
--- content/browser/web_contents/web_contents_view_mac.h
|
||||
+++ content/browser/web_contents/web_contents_view_mac.h
|
||||
@@ -96,7 +96,7 @@ class WebContentsViewMac : public WebContentsView,
|
||||
@@ -97,7 +97,7 @@ class WebContentsViewMac : public WebContentsView,
|
||||
gfx::NativeView context) override;
|
||||
RenderWidgetHostViewBase* CreateViewForWidget(
|
||||
RenderWidgetHost* render_widget_host,
|
||||
@@ -221,7 +221,7 @@ index 2e3f4f8a56d4..75ef26b5381a 100644
|
||||
RenderWidgetHost* render_widget_host) override;
|
||||
void SetPageTitle(const base::string16& title) override;
|
||||
diff --git content/browser/web_contents/web_contents_view_mac.mm content/browser/web_contents/web_contents_view_mac.mm
|
||||
index 03d7c9c7dcce..e84c1787a84d 100644
|
||||
index 94848b568363..4dea19adb512 100644
|
||||
--- content/browser/web_contents/web_contents_view_mac.mm
|
||||
+++ content/browser/web_contents/web_contents_view_mac.mm
|
||||
@@ -345,7 +345,8 @@ void WebContentsViewMac::CreateView(
|
||||
@@ -266,10 +266,10 @@ index d05dd5421458..fa13775f0512 100644
|
||||
// a BrowserPlugin even when we are using cross process frames for guests. It
|
||||
// should be removed after resolving https://crbug.com/642826).
|
||||
diff --git extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
index 1930af130f24..77695f7844d7 100644
|
||||
index d59bfbac79cd..e5e60edf5174 100644
|
||||
--- extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
+++ extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
|
||||
@@ -198,6 +198,8 @@ void MimeHandlerViewGuest::CreateWebContents(
|
||||
@@ -200,6 +200,8 @@ void MimeHandlerViewGuest::CreateWebContents(
|
||||
WebContents::CreateParams params(browser_context(),
|
||||
guest_site_instance.get());
|
||||
params.guest_delegate = this;
|
||||
@@ -278,7 +278,7 @@ index 1930af130f24..77695f7844d7 100644
|
||||
// TODO(erikchen): Fix ownership semantics for guest views.
|
||||
// https://crbug.com/832879.
|
||||
std::move(callback).Run(
|
||||
@@ -239,6 +241,18 @@ bool MimeHandlerViewGuest::ShouldDestroyOnDetach() const {
|
||||
@@ -244,6 +246,18 @@ bool MimeHandlerViewGuest::ShouldDestroyOnDetach() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
|
||||
index 343c8a0fbfeb..68c73fa1c5f0 100644
|
||||
index b5d398fd0882..11552886dc36 100644
|
||||
--- chrome/browser/BUILD.gn
|
||||
+++ chrome/browser/BUILD.gn
|
||||
@@ -8,6 +8,7 @@ import("//build/config/features.gni")
|
||||
|
@@ -70,7 +70,7 @@ index e8e76ce5b954..1dd338dd0142 100644
|
||||
content::BrowserContext* GetBrowserContextRedirectedInIncognito(
|
||||
content::BrowserContext* context);
|
||||
diff --git chrome/browser/profiles/profile_manager.cc chrome/browser/profiles/profile_manager.cc
|
||||
index be5d79034fea..617ab398fff8 100644
|
||||
index 4aa9dd926ccb..35c940b08f7d 100644
|
||||
--- chrome/browser/profiles/profile_manager.cc
|
||||
+++ chrome/browser/profiles/profile_manager.cc
|
||||
@@ -383,7 +383,7 @@ ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/plugins/plugin_info_host_impl.cc chrome/browser/plugins/plugin_info_host_impl.cc
|
||||
index 484e07af5a98..0e62e20095c7 100644
|
||||
index 484e07af5a98..d9807243e2b5 100644
|
||||
--- chrome/browser/plugins/plugin_info_host_impl.cc
|
||||
+++ chrome/browser/plugins/plugin_info_host_impl.cc
|
||||
@@ -16,6 +16,7 @@
|
||||
@@ -22,39 +22,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#include "components/guest_view/browser/guest_view_base.h"
|
||||
#include "extensions/browser/extension_registry.h"
|
||||
@@ -74,12 +80,10 @@ namespace {
|
||||
class PluginInfoHostImplShutdownNotifierFactory
|
||||
: public BrowserContextKeyedServiceShutdownNotifierFactory {
|
||||
public:
|
||||
- static PluginInfoHostImplShutdownNotifierFactory* GetInstance() {
|
||||
- return base::Singleton<PluginInfoHostImplShutdownNotifierFactory>::get();
|
||||
- }
|
||||
+ static PluginInfoHostImplShutdownNotifierFactory* GetInstance();
|
||||
|
||||
private:
|
||||
- friend struct base::DefaultSingletonTraits<
|
||||
+ friend struct base::LazyInstanceTraitsBase<
|
||||
PluginInfoHostImplShutdownNotifierFactory>;
|
||||
|
||||
PluginInfoHostImplShutdownNotifierFactory()
|
||||
@@ -91,6 +95,16 @@ class PluginInfoHostImplShutdownNotifierFactory
|
||||
DISALLOW_COPY_AND_ASSIGN(PluginInfoHostImplShutdownNotifierFactory);
|
||||
};
|
||||
|
||||
+base::LazyInstance<PluginInfoHostImplShutdownNotifierFactory>::Leaky
|
||||
+ g_plugin_info_host_impl_shutdown_notifier_factory =
|
||||
+ LAZY_INSTANCE_INITIALIZER;
|
||||
+
|
||||
+// static
|
||||
+PluginInfoHostImplShutdownNotifierFactory*
|
||||
+PluginInfoHostImplShutdownNotifierFactory::GetInstance() {
|
||||
+ return g_plugin_info_host_impl_shutdown_notifier_factory.Pointer();
|
||||
+}
|
||||
+
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
// Returns whether a request from a plugin to load |resource| from a renderer
|
||||
// with process id |process_id| is a request for an internal resource by an app
|
||||
@@ -99,6 +113,9 @@ bool IsPluginLoadingAccessibleResourceInWebView(
|
||||
@@ -99,6 +105,9 @@ bool IsPluginLoadingAccessibleResourceInWebView(
|
||||
extensions::ExtensionRegistry* extension_registry,
|
||||
int process_id,
|
||||
const GURL& resource) {
|
||||
@@ -64,7 +32,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
extensions::WebViewRendererState* renderer_state =
|
||||
extensions::WebViewRendererState::GetInstance();
|
||||
std::string partition_id;
|
||||
@@ -128,12 +145,16 @@ bool IsPluginLoadingAccessibleResourceInWebView(
|
||||
@@ -128,12 +137,16 @@ bool IsPluginLoadingAccessibleResourceInWebView(
|
||||
PluginInfoHostImpl::Context::Context(int render_process_id, Profile* profile)
|
||||
: render_process_id_(render_process_id),
|
||||
resource_context_(profile->GetResourceContext()),
|
||||
@@ -84,7 +52,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
allow_outdated_plugins_.Init(prefs::kPluginsAllowOutdated,
|
||||
profile->GetPrefs());
|
||||
allow_outdated_plugins_.MoveToThread(
|
||||
@@ -232,6 +253,7 @@ void PluginInfoHostImpl::PluginsLoaded(
|
||||
@@ -232,6 +245,7 @@ void PluginInfoHostImpl::PluginsLoaded(
|
||||
plugin_metadata->identifier(), &output->status);
|
||||
}
|
||||
|
||||
@@ -92,7 +60,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
if (output->status == chrome::mojom::PluginStatus::kNotFound) {
|
||||
// Check to see if the component updater can fetch an implementation.
|
||||
base::PostTaskAndReplyWithResult(
|
||||
@@ -243,7 +265,9 @@ void PluginInfoHostImpl::PluginsLoaded(
|
||||
@@ -243,7 +257,9 @@ void PluginInfoHostImpl::PluginsLoaded(
|
||||
base::BindOnce(&PluginInfoHostImpl::ComponentPluginLookupDone, this,
|
||||
params, std::move(output), std::move(callback),
|
||||
std::move(plugin_metadata)));
|
||||
@@ -103,7 +71,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
GetPluginInfoFinish(params, std::move(output), std::move(callback),
|
||||
std::move(plugin_metadata));
|
||||
}
|
||||
@@ -256,6 +280,14 @@ void PluginInfoHostImpl::Context::DecidePluginStatus(
|
||||
@@ -256,6 +272,14 @@ void PluginInfoHostImpl::Context::DecidePluginStatus(
|
||||
PluginMetadata::SecurityStatus security_status,
|
||||
const std::string& plugin_identifier,
|
||||
chrome::mojom::PluginStatus* status) const {
|
||||
@@ -118,7 +86,7 @@ index 484e07af5a98..0e62e20095c7 100644
|
||||
if (security_status == PluginMetadata::SECURITY_STATUS_FULLY_TRUSTED) {
|
||||
*status = chrome::mojom::PluginStatus::kAllowed;
|
||||
return;
|
||||
@@ -380,16 +412,36 @@ bool PluginInfoHostImpl::Context::FindEnabledPlugin(
|
||||
@@ -380,16 +404,36 @@ bool PluginInfoHostImpl::Context::FindEnabledPlugin(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git content/browser/compositor/gpu_process_transport_factory.cc content/browser/compositor/gpu_process_transport_factory.cc
|
||||
index 20fa23379c4b..87d8ba911d53 100644
|
||||
index 511d805187b1..5fb01fee0378 100644
|
||||
--- content/browser/compositor/gpu_process_transport_factory.cc
|
||||
+++ content/browser/compositor/gpu_process_transport_factory.cc
|
||||
@@ -494,10 +494,20 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
|
||||
@@ -26,7 +26,7 @@ index 20fa23379c4b..87d8ba911d53 100644
|
||||
} else {
|
||||
DCHECK(context_provider);
|
||||
diff --git ui/compositor/compositor.h ui/compositor/compositor.h
|
||||
index fccba71bf856..85e305a783b9 100644
|
||||
index e0ec33400b17..34fb1c987189 100644
|
||||
--- ui/compositor/compositor.h
|
||||
+++ ui/compositor/compositor.h
|
||||
@@ -24,6 +24,7 @@
|
||||
@@ -37,7 +37,7 @@ index fccba71bf856..85e305a783b9 100644
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkMatrix44.h"
|
||||
#include "ui/compositor/compositor_animation_observer.h"
|
||||
@@ -193,6 +194,17 @@ class COMPOSITOR_EXPORT ContextFactory {
|
||||
@@ -199,6 +200,17 @@ class COMPOSITOR_EXPORT ContextFactory {
|
||||
virtual bool SyncTokensRequiredForDisplayCompositor() = 0;
|
||||
};
|
||||
|
||||
@@ -55,7 +55,7 @@ index fccba71bf856..85e305a783b9 100644
|
||||
// Compositor object to take care of GPU painting.
|
||||
// A Browser compositor object is responsible for generating the final
|
||||
// displayable form of pixels comprising a single widget's contents. It draws an
|
||||
@@ -233,6 +245,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
@@ -239,6 +251,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
// Schedules a redraw of the layer tree associated with this compositor.
|
||||
void ScheduleDraw();
|
||||
|
||||
@@ -65,7 +65,7 @@ index fccba71bf856..85e305a783b9 100644
|
||||
// Sets the root of the layer tree drawn by this Compositor. The root layer
|
||||
// must have no parent. The compositor's root layer is reset if the root layer
|
||||
// is destroyed. NULL can be passed to reset the root layer, in which case the
|
||||
@@ -455,6 +470,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
@@ -461,6 +476,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
|
||||
ui::ContextFactory* context_factory_;
|
||||
ui::ContextFactoryPrivate* context_factory_private_;
|
||||
|
||||
|
@@ -94,10 +94,10 @@ index 201f23b9b422..4664c6b32c22 100644
|
||||
"WillFailRequest state should come before WillProcessResponse");
|
||||
return render_frame_host_;
|
||||
diff --git content/browser/frame_host/render_frame_host_impl.cc content/browser/frame_host/render_frame_host_impl.cc
|
||||
index 36b5e3bf6853..9303e53b9094 100644
|
||||
index 8e5af3e3b9c5..5517c7363590 100644
|
||||
--- content/browser/frame_host/render_frame_host_impl.cc
|
||||
+++ content/browser/frame_host/render_frame_host_impl.cc
|
||||
@@ -842,8 +842,8 @@ void RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
|
||||
@@ -843,8 +843,8 @@ void RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
|
||||
RenderFrameDevToolsAgentHost::WillCreateURLLoaderFactory(
|
||||
this, false /* is_navigation */, false /* is_download */,
|
||||
&default_factory_request);
|
||||
@@ -108,7 +108,7 @@ index 36b5e3bf6853..9303e53b9094 100644
|
||||
if (g_create_network_factory_callback_for_test.Get().is_null()) {
|
||||
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
|
||||
std::move(default_factory_request), std::move(params));
|
||||
@@ -1672,6 +1672,7 @@ void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
|
||||
@@ -1673,6 +1673,7 @@ void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
|
||||
if (GetNavigationHandle()) {
|
||||
GetNavigationHandle()->set_net_error_code(
|
||||
static_cast<net::Error>(params.error_code));
|
||||
@@ -116,7 +116,7 @@ index 36b5e3bf6853..9303e53b9094 100644
|
||||
}
|
||||
|
||||
frame_tree_node_->navigator()->DidFailProvisionalLoadWithError(this, params);
|
||||
@@ -4050,9 +4051,9 @@ void RenderFrameHostImpl::CommitNavigation(
|
||||
@@ -4069,9 +4070,9 @@ void RenderFrameHostImpl::CommitNavigation(
|
||||
// is used. Currently we have this here to make sure we have non-racy
|
||||
// situation (https://crbug.com/849929).
|
||||
DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
|
||||
@@ -285,10 +285,10 @@ index 3009401dac6b..b4c5a9e2db50 100644
|
||||
};
|
||||
|
||||
diff --git content/common/frame_messages.h content/common/frame_messages.h
|
||||
index 67a66d040a08..76867658db44 100644
|
||||
index 4d0712eca8d0..ef1d88a7d42c 100644
|
||||
--- content/common/frame_messages.h
|
||||
+++ content/common/frame_messages.h
|
||||
@@ -1382,9 +1382,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_PepperStopsPlayback,
|
||||
@@ -1379,9 +1379,10 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_PepperStopsPlayback,
|
||||
// type. If there is no matching plugin, |found| is false.
|
||||
// |actual_mime_type| is the actual mime type supported by the
|
||||
// found plugin.
|
||||
@@ -364,10 +364,10 @@ index 2f1f46075b27..94f300dfea5d 100644
|
||||
virtual void FocusedNodeChanged(const blink::WebNode& node) {}
|
||||
|
||||
diff --git content/renderer/render_frame_impl.cc content/renderer/render_frame_impl.cc
|
||||
index 61ee2a0d203a..f03a4ff9ee98 100644
|
||||
index 9571ea0233e8..c7c4b0bb737b 100644
|
||||
--- content/renderer/render_frame_impl.cc
|
||||
+++ content/renderer/render_frame_impl.cc
|
||||
@@ -3471,7 +3471,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
|
||||
@@ -3473,7 +3473,8 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
|
||||
std::string mime_type;
|
||||
bool found = false;
|
||||
Send(new FrameHostMsg_GetPluginInfo(
|
||||
@@ -377,7 +377,7 @@ index 61ee2a0d203a..f03a4ff9ee98 100644
|
||||
params.mime_type.Utf8(), &found, &info, &mime_type));
|
||||
if (!found)
|
||||
return nullptr;
|
||||
@@ -3836,6 +3837,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
|
||||
@@ -3847,6 +3848,8 @@ void RenderFrameImpl::FrameDetached(DetachType type) {
|
||||
|
||||
void RenderFrameImpl::FrameFocused() {
|
||||
Send(new FrameHostMsg_FrameFocused(routing_id_));
|
||||
@@ -387,10 +387,10 @@ index 61ee2a0d203a..f03a4ff9ee98 100644
|
||||
|
||||
void RenderFrameImpl::WillCommitProvisionalLoad() {
|
||||
diff --git content/renderer/render_thread_impl.cc content/renderer/render_thread_impl.cc
|
||||
index ca6a21b03082..a090b13d65e5 100644
|
||||
index c078565cef71..841601d8fc24 100644
|
||||
--- content/renderer/render_thread_impl.cc
|
||||
+++ content/renderer/render_thread_impl.cc
|
||||
@@ -866,6 +866,8 @@ void RenderThreadImpl::Init(
|
||||
@@ -865,6 +865,8 @@ void RenderThreadImpl::Init(
|
||||
|
||||
StartServiceManagerConnection();
|
||||
|
||||
|
@@ -27,7 +27,7 @@ index 53c7404ef1f9..ac33df7cfe0e 100644
|
||||
auto* browser_context = web_contents->GetBrowserContext();
|
||||
StreamsPrivateAPI* streams_private = GetStreamsPrivateAPI(browser_context);
|
||||
diff --git content/browser/frame_host/render_frame_host_manager.cc content/browser/frame_host/render_frame_host_manager.cc
|
||||
index 29386263f0db..11fa39c54d43 100644
|
||||
index 872e4609c94f..a82e6af8a7db 100644
|
||||
--- content/browser/frame_host/render_frame_host_manager.cc
|
||||
+++ content/browser/frame_host/render_frame_host_manager.cc
|
||||
@@ -928,10 +928,11 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
|
||||
|
@@ -12,10 +12,10 @@ index 959a59231746..67335e852219 100644
|
||||
}
|
||||
|
||||
diff --git chrome/browser/ui/libgtkui/gtk_util.cc chrome/browser/ui/libgtkui/gtk_util.cc
|
||||
index 96f8c0e71472..49c462b37e12 100644
|
||||
index 39bf49c7b111..ad7b054e185f 100644
|
||||
--- chrome/browser/ui/libgtkui/gtk_util.cc
|
||||
+++ chrome/browser/ui/libgtkui/gtk_util.cc
|
||||
@@ -237,6 +237,7 @@ float GetDeviceScaleFactor() {
|
||||
@@ -239,6 +239,7 @@ float GetDeviceScaleFactor() {
|
||||
return linux_ui ? linux_ui->GetDeviceScaleFactor() : 1;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ index 96f8c0e71472..49c462b37e12 100644
|
||||
using GtkSetState = void (*)(GtkWidgetPath*, gint, GtkStateFlags);
|
||||
PROTECTED_MEMORY_SECTION base::ProtectedMemory<GtkSetState>
|
||||
_gtk_widget_path_iter_set_state;
|
||||
@@ -244,6 +245,7 @@ PROTECTED_MEMORY_SECTION base::ProtectedMemory<GtkSetState>
|
||||
@@ -246,6 +247,7 @@ PROTECTED_MEMORY_SECTION base::ProtectedMemory<GtkSetState>
|
||||
using GtkSetObjectName = void (*)(GtkWidgetPath*, gint, const char*);
|
||||
PROTECTED_MEMORY_SECTION base::ProtectedMemory<GtkSetObjectName>
|
||||
_gtk_widget_path_iter_set_object_name;
|
||||
@@ -31,7 +31,7 @@ index 96f8c0e71472..49c462b37e12 100644
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -401,10 +403,12 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
@@ -403,10 +405,12 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
NOTREACHED();
|
||||
}
|
||||
} else {
|
||||
@@ -44,7 +44,7 @@ index 96f8c0e71472..49c462b37e12 100644
|
||||
switch (part_type) {
|
||||
case CSS_NAME: {
|
||||
if (GtkVersionCheck(3, 20)) {
|
||||
@@ -449,6 +453,7 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
@@ -451,6 +455,7 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
// widgets specially if they want to.
|
||||
gtk_widget_path_iter_add_class(path, -1, "chromium");
|
||||
|
||||
@@ -52,7 +52,7 @@ index 96f8c0e71472..49c462b37e12 100644
|
||||
if (GtkVersionCheck(3, 14)) {
|
||||
static base::ProtectedMemory<GtkSetState>::Initializer init(
|
||||
&_gtk_widget_path_iter_set_state,
|
||||
@@ -457,6 +462,7 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
@@ -459,6 +464,7 @@ ScopedStyleContext AppendCssNodeToStyleContext(GtkStyleContext* context,
|
||||
DCHECK(*_gtk_widget_path_iter_set_state);
|
||||
base::UnsanitizedCfiCall(_gtk_widget_path_iter_set_state)(path, -1, state);
|
||||
}
|
||||
@@ -60,19 +60,6 @@ index 96f8c0e71472..49c462b37e12 100644
|
||||
|
||||
ScopedStyleContext child_context(gtk_style_context_new());
|
||||
gtk_style_context_set_path(child_context, path);
|
||||
diff --git chrome/browser/ui/libgtkui/native_theme_gtk2.cc chrome/browser/ui/libgtkui/native_theme_gtk2.cc
|
||||
index b24ff4b95f97..49e80717b1d6 100644
|
||||
--- chrome/browser/ui/libgtkui/native_theme_gtk2.cc
|
||||
+++ chrome/browser/ui/libgtkui/native_theme_gtk2.cc
|
||||
@@ -163,6 +163,8 @@ SkColor NativeThemeGtk2::GetSystemColor(ColorId color_id) const {
|
||||
return GetBgColor(GetMenu(), NORMAL);
|
||||
|
||||
// Label
|
||||
+ case kColorId_ActionableSubmenuVerticalSeparatorColor:
|
||||
+ case kColorId_TouchableMenuItemLabelColor:
|
||||
case kColorId_LabelEnabledColor:
|
||||
return GetTextColor(GetEntry(), NORMAL);
|
||||
case kColorId_LabelDisabledColor:
|
||||
diff --git ui/accessibility/platform/atk_util_auralinux_gtk2.cc ui/accessibility/platform/atk_util_auralinux_gtk2.cc
|
||||
index ac11b5626f67..6355d0283de1 100644
|
||||
--- ui/accessibility/platform/atk_util_auralinux_gtk2.cc
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git base/message_loop/message_loop.cc base/message_loop/message_loop.cc
|
||||
index 4571c726ec4a..ad1479647400 100644
|
||||
index 3723960a5c0c..fa924f020f4e 100644
|
||||
--- base/message_loop/message_loop.cc
|
||||
+++ base/message_loop/message_loop.cc
|
||||
@@ -573,6 +573,9 @@ MessageLoopForUI::MessageLoopForUI(Type type) : MessageLoop(type) {
|
||||
@@ -577,6 +577,9 @@ MessageLoopForUI::MessageLoopForUI(Type type) : MessageLoop(type) {
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -13,10 +13,20 @@ index 4571c726ec4a..ad1479647400 100644
|
||||
MessageLoopCurrentForUI MessageLoopForUI::current() {
|
||||
return MessageLoopCurrentForUI::Get();
|
||||
diff --git base/message_loop/message_loop.h base/message_loop/message_loop.h
|
||||
index 6010333616eb..f9479daaa4b8 100644
|
||||
index 7c31a128b53d..7549d388cccb 100644
|
||||
--- base/message_loop/message_loop.h
|
||||
+++ base/message_loop/message_loop.h
|
||||
@@ -343,6 +343,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
|
||||
@@ -195,6 +195,9 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
|
||||
// Runs the specified PendingTask.
|
||||
void RunTask(PendingTask* pending_task);
|
||||
|
||||
+ // Called from Thread::CleanUp() to release resources.
|
||||
+ void ReleasePump() { pump_ = nullptr; }
|
||||
+
|
||||
//----------------------------------------------------------------------------
|
||||
protected:
|
||||
std::unique_ptr<MessagePump> pump_;
|
||||
@@ -351,6 +354,7 @@ class BASE_EXPORT MessageLoop : public MessagePump::Delegate,
|
||||
class BASE_EXPORT MessageLoopForUI : public MessageLoop {
|
||||
public:
|
||||
explicit MessageLoopForUI(Type type = TYPE_UI);
|
||||
@@ -24,6 +34,19 @@ index 6010333616eb..f9479daaa4b8 100644
|
||||
|
||||
// TODO(gab): Mass migrate callers to MessageLoopCurrentForUI::Get()/IsSet().
|
||||
static MessageLoopCurrentForUI current();
|
||||
diff --git base/message_loop/message_loop_current.cc base/message_loop/message_loop_current.cc
|
||||
index 4959b70e0676..fdffe799433f 100644
|
||||
--- base/message_loop/message_loop_current.cc
|
||||
+++ base/message_loop/message_loop_current.cc
|
||||
@@ -43,6 +43,8 @@ void MessageLoopCurrent::AddDestructionObserver(
|
||||
|
||||
void MessageLoopCurrent::RemoveDestructionObserver(
|
||||
DestructionObserver* destruction_observer) {
|
||||
+ if (!current_)
|
||||
+ return;
|
||||
DCHECK_CALLED_ON_VALID_THREAD(current_->bound_thread_checker_);
|
||||
current_->destruction_observers_.RemoveObserver(destruction_observer);
|
||||
}
|
||||
diff --git base/message_loop/message_loop_current.h base/message_loop/message_loop_current.h
|
||||
index 61d1607e31e7..656b3a9c9f68 100644
|
||||
--- base/message_loop/message_loop_current.h
|
||||
|
24
patch/patches/message_pump_mac_2495.patch
Normal file
24
patch/patches/message_pump_mac_2495.patch
Normal file
@@ -0,0 +1,24 @@
|
||||
diff --git base/message_loop/message_pump_mac.mm base/message_loop/message_pump_mac.mm
|
||||
index fb2520179995..165a8d4b4b29 100644
|
||||
--- base/message_loop/message_pump_mac.mm
|
||||
+++ base/message_loop/message_pump_mac.mm
|
||||
@@ -761,7 +761,8 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) :
|
||||
#else
|
||||
|
||||
ScopedPumpMessagesInPrivateModes::ScopedPumpMessagesInPrivateModes() {
|
||||
- DCHECK(g_app_pump);
|
||||
+ if (!g_app_pump)
|
||||
+ return;
|
||||
DCHECK_EQ(kNSApplicationModalSafeModeMask, g_app_pump->GetModeMask());
|
||||
// Pumping events in private runloop modes is known to interact badly with
|
||||
// app modal windows like NSAlert.
|
||||
@@ -770,7 +771,8 @@ explicit MessagePumpScopedAutoreleasePool(MessagePumpCFRunLoopBase* pump) :
|
||||
}
|
||||
|
||||
ScopedPumpMessagesInPrivateModes::~ScopedPumpMessagesInPrivateModes() {
|
||||
- DCHECK(g_app_pump);
|
||||
+ if (!g_app_pump)
|
||||
+ return;
|
||||
g_app_pump->SetModeMask(kNSApplicationModalSafeModeMask);
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git net/base/network_delegate.h net/base/network_delegate.h
|
||||
index c28d0bb3b676..1acbb4c94495 100644
|
||||
index ea4316257a61..58bf1443f1ae 100644
|
||||
--- net/base/network_delegate.h
|
||||
+++ net/base/network_delegate.h
|
||||
@@ -17,6 +17,7 @@
|
||||
@@ -10,7 +10,7 @@ index c28d0bb3b676..1acbb4c94495 100644
|
||||
#include "net/proxy_resolution/proxy_retry_info.h"
|
||||
|
||||
class GURL;
|
||||
@@ -125,6 +126,10 @@ class NET_EXPORT NetworkDelegate {
|
||||
@@ -122,6 +123,10 @@ class NET_EXPORT NetworkDelegate {
|
||||
bool CanUseReportingClient(const url::Origin& origin,
|
||||
const GURL& endpoint) const;
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
|
||||
index c6d7d9d076a9..79fe6745a829 100644
|
||||
index 1b14d628a63b..b29e7741ffa3 100644
|
||||
--- chrome/browser/ui/BUILD.gn
|
||||
+++ chrome/browser/ui/BUILD.gn
|
||||
@@ -901,6 +901,7 @@ split_static_library("ui") {
|
||||
|
45
patch/patches/resource_bundle_2512.patch
Normal file
45
patch/patches/resource_bundle_2512.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
diff --git ui/base/resource/resource_bundle.cc ui/base/resource/resource_bundle.cc
|
||||
index 2a00d4e..d2328b7 100644
|
||||
--- ui/base/resource/resource_bundle.cc
|
||||
+++ ui/base/resource/resource_bundle.cc
|
||||
@@ -737,6 +737,12 @@ ResourceBundle::ResourceBundle(Delegate* delegate)
|
||||
: delegate_(delegate),
|
||||
locale_resources_data_lock_(new base::Lock),
|
||||
max_scale_factor_(SCALE_FACTOR_100P) {
|
||||
+ // With CEF's multi-threaded mode the ResourceBundle may be created on the
|
||||
+ // main thread and then accessed on the UI thread. Allow the SequenceChecker
|
||||
+ // to re-bind on the UI thread when CalledOnValidSequence() is called for the
|
||||
+ // first time.
|
||||
+ DETACH_FROM_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
mangle_localized_strings_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
switches::kMangleLocalizedStrings);
|
||||
}
|
||||
@@ -746,6 +752,11 @@ ResourceBundle::~ResourceBundle() {
|
||||
UnloadLocaleResources();
|
||||
}
|
||||
|
||||
+void ResourceBundle::CleanupOnUIThread() {
|
||||
+ FreeImages();
|
||||
+ font_cache_.clear();
|
||||
+}
|
||||
+
|
||||
// static
|
||||
void ResourceBundle::InitSharedInstance(Delegate* delegate) {
|
||||
DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
|
||||
diff --git ui/base/resource/resource_bundle.h ui/base/resource/resource_bundle.h
|
||||
index 422d84b..669522fd 100644
|
||||
--- ui/base/resource/resource_bundle.h
|
||||
+++ ui/base/resource/resource_bundle.h
|
||||
@@ -150,6 +150,11 @@ class UI_BASE_EXPORT ResourceBundle {
|
||||
// Return the global resource loader instance.
|
||||
static ResourceBundle& GetSharedInstance();
|
||||
|
||||
+ // With CEF's multi-threaded mode the ResourceBundle may be created/destroyed
|
||||
+ // on the main thread but accessed on the UI thread. Call this method on the
|
||||
+ // UI thread to clean up resources before destruction.
|
||||
+ void CleanupOnUIThread();
|
||||
+
|
||||
// Loads a secondary locale data pack using the given file region.
|
||||
void LoadSecondaryLocaleDataWithPakFileRegion(
|
||||
base::File pak_file,
|
@@ -1,146 +0,0 @@
|
||||
diff --git chrome/browser/spellchecker/spellcheck_factory.cc chrome/browser/spellchecker/spellcheck_factory.cc
|
||||
index 64b5243d510a..8ae3001f85fc 100644
|
||||
--- chrome/browser/spellchecker/spellcheck_factory.cc
|
||||
+++ chrome/browser/spellchecker/spellcheck_factory.cc
|
||||
@@ -17,6 +17,13 @@
|
||||
#include "services/service_manager/public/cpp/identity.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+static base::LazyInstance<SpellcheckServiceFactory>::Leaky
|
||||
+ g_spellcheck_service_factory = LAZY_INSTANCE_INITIALIZER;
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
// static
|
||||
SpellcheckService* SpellcheckServiceFactory::GetForContext(
|
||||
content::BrowserContext* context) {
|
||||
@@ -37,7 +44,7 @@ SpellcheckService* SpellcheckServiceFactory::GetForRenderer(
|
||||
|
||||
// static
|
||||
SpellcheckServiceFactory* SpellcheckServiceFactory::GetInstance() {
|
||||
- return base::Singleton<SpellcheckServiceFactory>::get();
|
||||
+ return g_spellcheck_service_factory.Pointer();
|
||||
}
|
||||
|
||||
SpellcheckServiceFactory::SpellcheckServiceFactory()
|
||||
diff --git chrome/browser/spellchecker/spellcheck_factory.h chrome/browser/spellchecker/spellcheck_factory.h
|
||||
index fd4e6643725c..fcdbb8e4db88 100644
|
||||
--- chrome/browser/spellchecker/spellcheck_factory.h
|
||||
+++ chrome/browser/spellchecker/spellcheck_factory.h
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/macros.h"
|
||||
-#include "base/memory/singleton.h"
|
||||
+#include "base/lazy_instance.h"
|
||||
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
|
||||
|
||||
class SpellcheckService;
|
||||
@@ -31,7 +31,7 @@ class SpellcheckServiceFactory : public BrowserContextKeyedServiceFactory {
|
||||
static SpellcheckServiceFactory* GetInstance();
|
||||
|
||||
private:
|
||||
- friend struct base::DefaultSingletonTraits<SpellcheckServiceFactory>;
|
||||
+ friend struct base::LazyInstanceTraitsBase<SpellcheckServiceFactory>;
|
||||
|
||||
SpellcheckServiceFactory();
|
||||
~SpellcheckServiceFactory() override;
|
||||
diff --git chrome/browser/supervised_user/supervised_user_settings_service_factory.cc chrome/browser/supervised_user/supervised_user_settings_service_factory.cc
|
||||
index 173ac3132161..473e56161cca 100644
|
||||
--- chrome/browser/supervised_user/supervised_user_settings_service_factory.cc
|
||||
+++ chrome/browser/supervised_user/supervised_user_settings_service_factory.cc
|
||||
@@ -9,6 +9,13 @@
|
||||
#include "chrome/browser/supervised_user/supervised_user_settings_service.h"
|
||||
#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+base::LazyInstance<SupervisedUserSettingsServiceFactory>::Leaky
|
||||
+ g_service_factory = LAZY_INSTANCE_INITIALIZER;
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
// static
|
||||
SupervisedUserSettingsService*
|
||||
SupervisedUserSettingsServiceFactory::GetForProfile(Profile* profile) {
|
||||
@@ -19,7 +26,7 @@ SupervisedUserSettingsServiceFactory::GetForProfile(Profile* profile) {
|
||||
// static
|
||||
SupervisedUserSettingsServiceFactory*
|
||||
SupervisedUserSettingsServiceFactory::GetInstance() {
|
||||
- return base::Singleton<SupervisedUserSettingsServiceFactory>::get();
|
||||
+ return g_service_factory.Pointer();
|
||||
}
|
||||
|
||||
SupervisedUserSettingsServiceFactory::SupervisedUserSettingsServiceFactory()
|
||||
diff --git chrome/browser/supervised_user/supervised_user_settings_service_factory.h chrome/browser/supervised_user/supervised_user_settings_service_factory.h
|
||||
index 2907619549ba..f941fba363b5 100644
|
||||
--- chrome/browser/supervised_user/supervised_user_settings_service_factory.h
|
||||
+++ chrome/browser/supervised_user/supervised_user_settings_service_factory.h
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SETTINGS_SERVICE_FACTORY_H_
|
||||
#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_SETTINGS_SERVICE_FACTORY_H_
|
||||
|
||||
-#include "base/memory/singleton.h"
|
||||
+#include "base/lazy_instance.h"
|
||||
#include "chrome/browser/supervised_user/supervised_users.h"
|
||||
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
|
||||
|
||||
@@ -20,7 +20,7 @@ class SupervisedUserSettingsServiceFactory
|
||||
static SupervisedUserSettingsServiceFactory* GetInstance();
|
||||
|
||||
private:
|
||||
- friend struct base::DefaultSingletonTraits<
|
||||
+ friend struct base::LazyInstanceTraitsBase<
|
||||
SupervisedUserSettingsServiceFactory>;
|
||||
|
||||
SupervisedUserSettingsServiceFactory();
|
||||
diff --git chrome/browser/ui/prefs/prefs_tab_helper.cc chrome/browser/ui/prefs/prefs_tab_helper.cc
|
||||
index b9b2f059f694..a7b11cb75f22 100644
|
||||
--- chrome/browser/ui/prefs/prefs_tab_helper.cc
|
||||
+++ chrome/browser/ui/prefs/prefs_tab_helper.cc
|
||||
@@ -11,8 +11,8 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/command_line.h"
|
||||
+#include "base/lazy_instance.h"
|
||||
#include "base/macros.h"
|
||||
-#include "base/memory/singleton.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
@@ -389,12 +389,10 @@ class PrefWatcherFactory : public BrowserContextKeyedServiceFactory {
|
||||
GetInstance()->GetServiceForBrowserContext(profile, true));
|
||||
}
|
||||
|
||||
- static PrefWatcherFactory* GetInstance() {
|
||||
- return base::Singleton<PrefWatcherFactory>::get();
|
||||
- }
|
||||
+ static PrefWatcherFactory* GetInstance();
|
||||
|
||||
private:
|
||||
- friend struct base::DefaultSingletonTraits<PrefWatcherFactory>;
|
||||
+ friend struct base::LazyInstanceTraitsBase<PrefWatcherFactory>;
|
||||
|
||||
PrefWatcherFactory() : BrowserContextKeyedServiceFactory(
|
||||
"PrefWatcher",
|
||||
@@ -415,6 +413,18 @@ class PrefWatcherFactory : public BrowserContextKeyedServiceFactory {
|
||||
}
|
||||
};
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+base::LazyInstance<PrefWatcherFactory>::Leaky g_pref_watcher_factory =
|
||||
+ LAZY_INSTANCE_INITIALIZER;
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+// static
|
||||
+PrefWatcherFactory* PrefWatcherFactory::GetInstance() {
|
||||
+ return g_pref_watcher_factory.Pointer();
|
||||
+}
|
||||
+
|
||||
// static
|
||||
PrefWatcher* PrefWatcher::Get(Profile* profile) {
|
||||
return PrefWatcherFactory::GetForProfile(profile);
|
@@ -296,10 +296,10 @@ index 3cfa0bde2bca..96da49496944 100644
|
||||
partition->GetPaymentAppContext();
|
||||
|
||||
diff --git content/browser/renderer_host/render_process_host_impl.cc content/browser/renderer_host/render_process_host_impl.cc
|
||||
index 3887d68c6d22..629c16724145 100644
|
||||
index 05e0ee79e5ad..578d43ae8b3e 100644
|
||||
--- content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -739,11 +739,10 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data,
|
||||
@@ -734,11 +734,10 @@ class DefaultSubframeProcessHostHolder : public base::SupportsUserData::Data,
|
||||
// Gets the correct render process to use for this SiteInstance.
|
||||
RenderProcessHost* GetProcessHost(SiteInstance* site_instance,
|
||||
bool is_for_guests_only) {
|
||||
@@ -315,7 +315,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
|
||||
// Is this the default storage partition? If it isn't, then just give it its
|
||||
// own non-shared process.
|
||||
@@ -1341,7 +1340,7 @@ int RenderProcessHost::GetCurrentRenderProcessCountForTesting() {
|
||||
@@ -1396,7 +1395,7 @@ int RenderProcessHost::GetCurrentRenderProcessCountForTesting() {
|
||||
// static
|
||||
RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost(
|
||||
BrowserContext* browser_context,
|
||||
@@ -324,7 +324,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
SiteInstance* site_instance,
|
||||
bool is_for_guests_only) {
|
||||
if (g_render_process_host_factory_) {
|
||||
@@ -1350,8 +1349,8 @@ RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost(
|
||||
@@ -1405,8 +1404,8 @@ RenderProcessHost* RenderProcessHostImpl::CreateRenderProcessHost(
|
||||
}
|
||||
|
||||
if (!storage_partition_impl) {
|
||||
@@ -335,7 +335,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
}
|
||||
// If we've made a StoragePartition for guests (e.g., for the <webview> tag),
|
||||
// stash the Site URL on it. This way, when we start a service worker inside
|
||||
@@ -1376,7 +1375,7 @@ const unsigned int RenderProcessHostImpl::kMaxFrameDepthForPriority =
|
||||
@@ -1431,7 +1430,7 @@ const unsigned int RenderProcessHostImpl::kMaxFrameDepthForPriority =
|
||||
|
||||
RenderProcessHostImpl::RenderProcessHostImpl(
|
||||
BrowserContext* browser_context,
|
||||
@@ -344,7 +344,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
bool is_for_guests_only)
|
||||
: fast_shutdown_started_(false),
|
||||
deleting_soon_(false),
|
||||
@@ -1409,10 +1408,12 @@ RenderProcessHostImpl::RenderProcessHostImpl(
|
||||
@@ -1483,10 +1482,12 @@ RenderProcessHostImpl::RenderProcessHostImpl(
|
||||
indexed_db_factory_(new IndexedDBDispatcherHost(
|
||||
id_,
|
||||
storage_partition_impl_->GetURLRequestContext(),
|
||||
@@ -359,7 +359,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
id_)),
|
||||
channel_connected_(false),
|
||||
sent_render_process_ready_(false),
|
||||
@@ -1447,7 +1448,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
|
||||
@@ -1521,7 +1522,8 @@ RenderProcessHostImpl::RenderProcessHostImpl(
|
||||
}
|
||||
|
||||
push_messaging_manager_.reset(new PushMessagingManager(
|
||||
@@ -369,7 +369,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
|
||||
AddObserver(indexed_db_factory_.get());
|
||||
AddObserver(service_worker_dispatcher_host_.get());
|
||||
@@ -1780,6 +1782,17 @@ void RenderProcessHostImpl::ResetChannelProxy() {
|
||||
@@ -1854,6 +1856,17 @@ void RenderProcessHostImpl::ResetChannelProxy() {
|
||||
|
||||
void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
@@ -387,7 +387,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
MediaInternals* media_internals = MediaInternals::GetInstance();
|
||||
// Add BrowserPluginMessageFilter to ensure it gets the first stab at messages
|
||||
// from guests.
|
||||
@@ -1792,7 +1805,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
@@ -1866,7 +1879,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
base::MakeRefCounted<RenderMessageFilter>(
|
||||
GetID(), GetBrowserContext(), request_context.get(),
|
||||
widget_helper_.get(), media_internals,
|
||||
@@ -396,7 +396,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
AddFilter(render_message_filter.get());
|
||||
|
||||
render_frame_message_filter_ = new RenderFrameMessageFilter(
|
||||
@@ -1819,10 +1832,10 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
@@ -1893,10 +1906,10 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
ChromeBlobStorageContext::GetFor(browser_context);
|
||||
|
||||
resource_message_filter_ = new ResourceMessageFilter(
|
||||
@@ -409,7 +409,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
storage_partition_impl_->GetPrefetchURLLoaderService(),
|
||||
std::move(get_contexts_callback),
|
||||
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
|
||||
@@ -1831,8 +1844,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
@@ -1905,8 +1918,7 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
|
||||
AddFilter(
|
||||
new MidiHost(GetID(), BrowserMainLoop::GetInstance()->midi_service()));
|
||||
@@ -419,7 +419,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
|
||||
peer_connection_tracker_host_ = new PeerConnectionTrackerHost(GetID());
|
||||
AddFilter(peer_connection_tracker_host_.get());
|
||||
@@ -1854,10 +1866,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
@@ -1928,10 +1940,6 @@ void RenderProcessHostImpl::CreateMessageFilters() {
|
||||
|
||||
AddFilter(new TraceMessageFilter(GetID()));
|
||||
AddFilter(new ResolveProxyMsgHelper(request_context.get()));
|
||||
@@ -430,7 +430,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
}
|
||||
|
||||
void RenderProcessHostImpl::BindCacheStorage(
|
||||
@@ -1869,7 +1877,8 @@ void RenderProcessHostImpl::BindCacheStorage(
|
||||
@@ -1943,7 +1951,8 @@ void RenderProcessHostImpl::BindCacheStorage(
|
||||
cache_storage_dispatcher_host_ =
|
||||
base::MakeRefCounted<CacheStorageDispatcherHost>();
|
||||
cache_storage_dispatcher_host_->Init(
|
||||
@@ -440,7 +440,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
}
|
||||
// Send the binding to IO thread, because Cache Storage handles Mojo IPC on IO
|
||||
// thread entirely.
|
||||
@@ -2019,7 +2028,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
|
||||
@@ -2093,7 +2102,8 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
|
||||
|
||||
registry->AddInterface(base::BindRepeating(
|
||||
&AppCacheDispatcherHost::Create,
|
||||
@@ -450,7 +450,7 @@ index 3887d68c6d22..629c16724145 100644
|
||||
GetID()));
|
||||
|
||||
AddUIThreadInterface(registry.get(), base::Bind(&FieldTrialRecorder::Create));
|
||||
@@ -2050,6 +2060,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
|
||||
@@ -2124,6 +2134,9 @@ void RenderProcessHostImpl::RegisterMojoInterfaces() {
|
||||
plugin_registry_.reset(
|
||||
new PluginRegistryImpl(GetBrowserContext()->GetResourceContext()));
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
index c61199d5dd8f..f2c19e4e5f3c 100644
|
||||
index 5561b7a1f386..929d799fc696 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
@@ -480,6 +480,14 @@ float RenderWidgetHostViewBase::GetDeviceScaleFactor() const {
|
||||
@@ -73,7 +73,7 @@ index 8ed6ffd3a284..91db6f55c396 100644
|
||||
void SynchronizeVisualProperties();
|
||||
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_event_handler.cc content/browser/renderer_host/render_widget_host_view_event_handler.cc
|
||||
index 0f9d0a1c4269..cd9a314887cb 100644
|
||||
index 940d9c107664..f7a35655c757 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_event_handler.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_view_event_handler.cc
|
||||
@@ -30,6 +30,10 @@
|
||||
@@ -87,7 +87,7 @@ index 0f9d0a1c4269..cd9a314887cb 100644
|
||||
#if defined(OS_WIN)
|
||||
#include "content/browser/frame_host/render_frame_host_impl.h"
|
||||
#include "content/public/common/context_menu_params.h"
|
||||
@@ -889,6 +893,14 @@ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
|
||||
@@ -891,6 +895,14 @@ void RenderWidgetHostViewEventHandler::SetKeyboardFocus() {
|
||||
::SetFocus(hwnd);
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ index f772f64d656e..7d13f9f81b6c 100644
|
||||
return host ? host->GetAcceleratedWidget() : NULL;
|
||||
}
|
||||
diff --git ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
|
||||
index 9ec5fdb9bb5c..0694641f11db 100644
|
||||
index 9c6b588516f2..90e804d0cc68 100644
|
||||
--- ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
|
||||
+++ ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
|
||||
@@ -87,6 +87,7 @@ DesktopWindowTreeHostWin::DesktopWindowTreeHostWin(
|
||||
@@ -160,7 +160,7 @@ index 9ec5fdb9bb5c..0694641f11db 100644
|
||||
|
||||
remove_standard_frame_ = params.remove_standard_frame;
|
||||
has_non_client_view_ = Widget::RequiresNonClientView(params.type);
|
||||
@@ -871,11 +876,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
|
||||
@@ -873,11 +878,15 @@ void DesktopWindowTreeHostWin::HandleFrameChanged() {
|
||||
}
|
||||
|
||||
void DesktopWindowTreeHostWin::HandleNativeFocus(HWND last_focused_window) {
|
||||
@@ -427,10 +427,10 @@ index c7296fed234d..244d0034a1c4 100644
|
||||
if (native_widget_delegate->IsDialogBox()) {
|
||||
*style |= DS_MODALFRAME;
|
||||
diff --git ui/views/win/hwnd_message_handler.cc ui/views/win/hwnd_message_handler.cc
|
||||
index 65ee52f582c9..b8f60b87ce21 100644
|
||||
index d5f442f71da7..1343399efbb8 100644
|
||||
--- ui/views/win/hwnd_message_handler.cc
|
||||
+++ ui/views/win/hwnd_message_handler.cc
|
||||
@@ -2817,10 +2817,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
|
||||
@@ -2872,10 +2872,13 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
|
||||
} else if (event.type() == ui::ET_MOUSEWHEEL) {
|
||||
ui::MouseWheelEvent mouse_wheel_event(msg);
|
||||
// Reroute the mouse wheel to the window under the pointer if applicable.
|
||||
|
@@ -65,7 +65,7 @@ index 976bae9c792b..10fb75b0af57 100644
|
||||
|
||||
void WebDevToolsAgentImpl::Session::SendProtocolResponse(int session_id,
|
||||
diff --git third_party/blink/renderer/core/frame/local_frame.cc third_party/blink/renderer/core/frame/local_frame.cc
|
||||
index 464a41e6f278..7e29a6a66bf4 100644
|
||||
index 52810bba03b0..88f5bd7066c8 100644
|
||||
--- third_party/blink/renderer/core/frame/local_frame.cc
|
||||
+++ third_party/blink/renderer/core/frame/local_frame.cc
|
||||
@@ -1264,7 +1264,7 @@ FrameResourceCoordinator* LocalFrame::GetFrameResourceCoordinator() {
|
||||
|
86
patch/patches/webkit_rtl_scrollbars_250514.patch
Normal file
86
patch/patches/webkit_rtl_scrollbars_250514.patch
Normal file
@@ -0,0 +1,86 @@
|
||||
diff --git third_party/blink/renderer/core/layout/layout_box.cc third_party/blink/renderer/core/layout/layout_box.cc
|
||||
index 9435e5ffc886..204bd88ceb8f 100644
|
||||
--- third_party/blink/renderer/core/layout/layout_box.cc
|
||||
+++ third_party/blink/renderer/core/layout/layout_box.cc
|
||||
@@ -4408,6 +4408,7 @@ void LayoutBox::ComputePositionedLogicalWidthUsing(
|
||||
}
|
||||
|
||||
if (container_block->IsBox() &&
|
||||
+ container_block->IsHorizontalWritingMode() == IsHorizontalWritingMode() &&
|
||||
ToLayoutBox(container_block)->ScrollsOverflowY() &&
|
||||
ToLayoutBox(container_block)
|
||||
->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
|
||||
@@ -4764,6 +4765,15 @@ void LayoutBox::ComputePositionedLogicalHeightUsing(
|
||||
}
|
||||
computed_values.extent_ = logical_height_value;
|
||||
|
||||
+ if (container_block->IsBox() &&
|
||||
+ container_block->IsHorizontalWritingMode() != IsHorizontalWritingMode() &&
|
||||
+ ToLayoutBox(container_block)->ScrollsOverflowY() &&
|
||||
+ ToLayoutBox(container_block)
|
||||
+ ->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
|
||||
+ logical_top_value = logical_top_value +
|
||||
+ ToLayoutBox(container_block)->VerticalScrollbarWidth();
|
||||
+ }
|
||||
+
|
||||
// Use computed values to calculate the vertical position.
|
||||
computed_values.position_ =
|
||||
logical_top_value + computed_values.margins_.before_;
|
||||
diff --git third_party/blink/renderer/core/layout/layout_view.cc third_party/blink/renderer/core/layout/layout_view.cc
|
||||
index c71691161e5a..52975440a043 100644
|
||||
--- third_party/blink/renderer/core/layout/layout_view.cc
|
||||
+++ third_party/blink/renderer/core/layout/layout_view.cc
|
||||
@@ -262,6 +262,22 @@ void LayoutView::SetShouldDoFullPaintInvalidationOnResizeIfNeeded(
|
||||
}
|
||||
}
|
||||
|
||||
+bool LayoutView::ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const {
|
||||
+ LocalFrame& frame = GetFrameView()->GetFrame();
|
||||
+ // See crbug.com/249860
|
||||
+ if (frame.IsMainFrame())
|
||||
+ return false;
|
||||
+ // <body> inherits 'direction' from <html>, so checking style on the body is
|
||||
+ // sufficient.
|
||||
+ if (Element* body = GetDocument().body()) {
|
||||
+ if (LayoutObject* body_layout_object = body->GetLayoutObject()) {
|
||||
+ return body_layout_object->Style()
|
||||
+ ->ShouldPlaceBlockDirectionScrollbarOnLogicalLeft();
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
void LayoutView::UpdateBlockLayout(bool relayout_children) {
|
||||
SubtreeLayoutScope layout_scope(*this);
|
||||
|
||||
diff --git third_party/blink/renderer/core/layout/layout_view.h third_party/blink/renderer/core/layout/layout_view.h
|
||||
index fed51c0988ff..0954c1e7de21 100644
|
||||
--- third_party/blink/renderer/core/layout/layout_view.h
|
||||
+++ third_party/blink/renderer/core/layout/layout_view.h
|
||||
@@ -241,13 +241,7 @@ class CORE_EXPORT LayoutView final : public LayoutBlockFlow {
|
||||
void SetShouldDoFullPaintInvalidationOnResizeIfNeeded(bool width_changed,
|
||||
bool height_changed);
|
||||
|
||||
- // The document scrollbar is always on the right, even in RTL. This is to
|
||||
- // prevent it from moving around on navigations.
|
||||
- // TODO(skobes): This is not quite the ideal behavior, see
|
||||
- // http://crbug.com/250514 and http://crbug.com/249860.
|
||||
- bool ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const override {
|
||||
- return false;
|
||||
- }
|
||||
+ bool ShouldPlaceBlockDirectionScrollbarOnLogicalLeft() const override;
|
||||
|
||||
LayoutRect DebugRect() const override;
|
||||
|
||||
diff --git third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
|
||||
index 5f13a443aff2..17066cc18e50 100644
|
||||
--- third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
|
||||
+++ third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
|
||||
@@ -1342,6 +1342,7 @@ void CompositedLayerMapping::ComputeGraphicsLayerParentLocation(
|
||||
IntSize scroll_offset = layout_box.ScrolledContentOffset();
|
||||
IntPoint scroll_origin =
|
||||
compositing_container->GetScrollableArea()->ScrollOrigin();
|
||||
+ scroll_origin.Move(-layout_box.OriginAdjustmentForScrollbars());
|
||||
scroll_origin.Move(-layout_box.BorderLeft().ToInt(),
|
||||
-layout_box.BorderTop().ToInt());
|
||||
graphics_layer_parent_location = -(scroll_origin + scroll_offset);
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/app/generated_resources.grd chrome/app/generated_resources.grd
|
||||
index 45d8533d283f..71e3b67d2554 100644
|
||||
index b68d4210285c..71a7956c5da1 100644
|
||||
--- chrome/app/generated_resources.grd
|
||||
+++ chrome/app/generated_resources.grd
|
||||
@@ -4457,7 +4457,7 @@ Keep your key file in a safe place. You will need it to create new versions of y
|
||||
|
@@ -42,6 +42,8 @@ void BrowserWindow::OnBrowserClosing(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK_EQ(browser->GetIdentifier(), browser_->GetIdentifier());
|
||||
is_closing_ = true;
|
||||
|
||||
delegate_->OnBrowserWindowClosing();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnBrowserClosed(CefRefPtr<CefBrowser> browser) {
|
||||
|
@@ -25,6 +25,9 @@ class BrowserWindow : public ClientHandler::Delegate {
|
||||
// Called when the browser has been created.
|
||||
virtual void OnBrowserCreated(CefRefPtr<CefBrowser> browser) = 0;
|
||||
|
||||
// Called when the BrowserWindow is closing.
|
||||
virtual void OnBrowserWindowClosing() {}
|
||||
|
||||
// Called when the BrowserWindow has been destroyed.
|
||||
virtual void OnBrowserWindowDestroyed() = 0;
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
#include "tests/shared/browser/geometry_util.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
|
||||
@@ -922,6 +923,7 @@ class ScopedGLContext {
|
||||
bool swap_buffers_;
|
||||
GdkGLDrawable* gldrawable_;
|
||||
bool is_valid_;
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -930,23 +932,26 @@ BrowserWindowOsrGtk::BrowserWindowOsrGtk(BrowserWindow::Delegate* delegate,
|
||||
const std::string& startup_url,
|
||||
const OsrRenderer::Settings& settings)
|
||||
: BrowserWindow(delegate),
|
||||
xdisplay_(nullptr),
|
||||
renderer_(settings),
|
||||
glarea_(NULL),
|
||||
hidden_(false),
|
||||
gl_enabled_(false),
|
||||
painting_popup_(false),
|
||||
device_scale_factor_(1.0f),
|
||||
hidden_(false),
|
||||
glarea_(NULL),
|
||||
drag_trigger_event_(NULL),
|
||||
drag_data_(NULL),
|
||||
drag_operation_(DRAG_OPERATION_NONE),
|
||||
drag_context_(NULL),
|
||||
drag_targets_(gtk_target_list_new(NULL, 0)),
|
||||
drag_leave_(false),
|
||||
drag_drop_(false) {
|
||||
drag_drop_(false),
|
||||
device_scale_factor_(1.0f) {
|
||||
client_handler_ = new ClientHandlerOsr(this, this, startup_url);
|
||||
}
|
||||
|
||||
BrowserWindowOsrGtk::~BrowserWindowOsrGtk() {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (drag_trigger_event_) {
|
||||
gdk_event_free(drag_trigger_event_);
|
||||
}
|
||||
@@ -956,6 +961,12 @@ BrowserWindowOsrGtk::~BrowserWindowOsrGtk() {
|
||||
gtk_target_list_unref(drag_targets_);
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::set_xdisplay(XDisplay* xdisplay) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!xdisplay_);
|
||||
xdisplay_ = xdisplay;
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::CreateBrowser(
|
||||
ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
@@ -966,6 +977,8 @@ void BrowserWindowOsrGtk::CreateBrowser(
|
||||
// Create the native window.
|
||||
Create(parent_handle);
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// Retrieve the X11 Window ID for the GTK parent window.
|
||||
GtkWidget* window =
|
||||
gtk_widget_get_ancestor(GTK_WIDGET(parent_handle), GTK_TYPE_WINDOW);
|
||||
@@ -1045,12 +1058,16 @@ void BrowserWindowOsrGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
|
||||
void BrowserWindowOsrGtk::SetFocus(bool focus) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
if (glarea_ && focus)
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
if (glarea_ && focus) {
|
||||
gtk_widget_grab_focus(glarea_);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
if (device_scale_factor == device_scale_factor_)
|
||||
return;
|
||||
|
||||
@@ -1059,6 +1076,7 @@ void BrowserWindowOsrGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
return;
|
||||
|
||||
device_scale_factor_ = device_scale_factor;
|
||||
}
|
||||
|
||||
if (browser_) {
|
||||
browser_->GetHost()->NotifyScreenInfoChanged();
|
||||
@@ -1068,6 +1086,7 @@ void BrowserWindowOsrGtk::SetDeviceScaleFactor(float device_scale_factor) {
|
||||
|
||||
float BrowserWindowOsrGtk::GetDeviceScaleFactor() const {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
base::AutoLock lock_scope(lock_);
|
||||
return device_scale_factor_;
|
||||
}
|
||||
|
||||
@@ -1082,11 +1101,12 @@ void BrowserWindowOsrGtk::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
|
||||
void BrowserWindowOsrGtk::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// Detach |this| from the ClientHandlerOsr.
|
||||
static_cast<ClientHandlerOsr*>(client_handler_.get())->DetachOsrDelegate();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
UnregisterDragDrop();
|
||||
|
||||
// Disconnect all signal handlers that reference |this|.
|
||||
@@ -1105,17 +1125,22 @@ bool BrowserWindowOsrGtk::GetRootScreenRect(CefRefPtr<CefBrowser> browser,
|
||||
bool BrowserWindowOsrGtk::GetViewRect(CefRefPtr<CefBrowser> browser,
|
||||
CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!glarea_)
|
||||
return false;
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
device_scale_factor = device_scale_factor_;
|
||||
}
|
||||
|
||||
// The simulated screen and view rectangle are the same. This is necessary
|
||||
// for popup menus to be located and sized inside the view.
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = DeviceToLogical(glarea_->allocation.width, device_scale_factor_);
|
||||
rect.width = DeviceToLogical(glarea_->allocation.width, device_scale_factor);
|
||||
rect.height =
|
||||
DeviceToLogical(glarea_->allocation.height, device_scale_factor_);
|
||||
DeviceToLogical(glarea_->allocation.height, device_scale_factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1125,12 +1150,17 @@ bool BrowserWindowOsrGtk::GetScreenPoint(CefRefPtr<CefBrowser> browser,
|
||||
int& screenX,
|
||||
int& screenY) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
device_scale_factor = device_scale_factor_;
|
||||
}
|
||||
|
||||
GdkRectangle screen_rect;
|
||||
GetWidgetRectInScreen(glarea_, &screen_rect);
|
||||
screenX = screen_rect.x + LogicalToDevice(viewX, device_scale_factor_);
|
||||
screenY = screen_rect.y + LogicalToDevice(viewY, device_scale_factor_);
|
||||
screenX = screen_rect.x + LogicalToDevice(viewX, device_scale_factor);
|
||||
screenY = screen_rect.y + LogicalToDevice(viewY, device_scale_factor);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1141,7 +1171,13 @@ bool BrowserWindowOsrGtk::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
CefRect view_rect;
|
||||
GetViewRect(browser, view_rect);
|
||||
|
||||
screen_info.device_scale_factor = device_scale_factor_;
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
device_scale_factor = device_scale_factor_;
|
||||
}
|
||||
|
||||
screen_info.device_scale_factor = device_scale_factor;
|
||||
|
||||
// The screen info rectangles are used by the renderer to create and position
|
||||
// popups. Keep popups inside the view rectangle.
|
||||
@@ -1153,7 +1189,6 @@ bool BrowserWindowOsrGtk::GetScreenInfo(CefRefPtr<CefBrowser> browser,
|
||||
void BrowserWindowOsrGtk::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
bool show) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!show) {
|
||||
renderer_.ClearPopupRects();
|
||||
@@ -1165,9 +1200,14 @@ void BrowserWindowOsrGtk::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
void BrowserWindowOsrGtk::OnPopupSize(CefRefPtr<CefBrowser> browser,
|
||||
const CefRect& rect) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
renderer_.OnPopupSize(browser, LogicalToDevice(rect, device_scale_factor_));
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
device_scale_factor = device_scale_factor_;
|
||||
}
|
||||
|
||||
renderer_.OnPopupSize(browser, LogicalToDevice(rect, device_scale_factor));
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
@@ -1177,7 +1217,6 @@ void BrowserWindowOsrGtk::OnPaint(CefRefPtr<CefBrowser> browser,
|
||||
int width,
|
||||
int height) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (width <= 2 && height <= 2) {
|
||||
// Ignore really small buffer sizes while the widget is starting up.
|
||||
@@ -1211,17 +1250,17 @@ void BrowserWindowOsrGtk::OnCursorChange(
|
||||
CefRenderHandler::CursorType type,
|
||||
const CefCursorInfo& custom_cursor_info) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// Retrieve the X11 display shared with Chromium.
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
DCHECK(xdisplay);
|
||||
CHECK(xdisplay_ != 0);
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// Retrieve the X11 window handle for the GTK widget.
|
||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(glarea_));
|
||||
|
||||
// Set the cursor.
|
||||
XDefineCursor(xdisplay, xwindow, cursor);
|
||||
XDefineCursor(xdisplay_, xwindow, cursor);
|
||||
}
|
||||
|
||||
bool BrowserWindowOsrGtk::StartDragging(
|
||||
@@ -1231,7 +1270,6 @@ bool BrowserWindowOsrGtk::StartDragging(
|
||||
int x,
|
||||
int y) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (!drag_data->HasImage()) {
|
||||
LOG(ERROR) << "Drag image representation not available";
|
||||
@@ -1241,6 +1279,8 @@ bool BrowserWindowOsrGtk::StartDragging(
|
||||
DragReset();
|
||||
drag_data_ = drag_data;
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// Begin drag.
|
||||
if (drag_trigger_event_) {
|
||||
LOG(ERROR) << "Dragging started, but last mouse event is missing";
|
||||
@@ -1271,7 +1311,6 @@ void BrowserWindowOsrGtk::UpdateDragCursor(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRenderHandler::DragOperation operation) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
drag_operation_ = operation;
|
||||
}
|
||||
|
||||
@@ -1290,6 +1329,8 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!glarea_);
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
glarea_ = gtk_drawing_area_new();
|
||||
DCHECK(glarea_);
|
||||
|
||||
@@ -1344,8 +1385,7 @@ void BrowserWindowOsrGtk::Create(ClientWindowHandle parent_handle) {
|
||||
gint BrowserWindowOsrGtk::SizeAllocation(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (self->browser_.get()) {
|
||||
// Results in a call to GetViewRect().
|
||||
self->browser_->GetHost()->WasResized();
|
||||
@@ -1357,7 +1397,7 @@ gint BrowserWindowOsrGtk::SizeAllocation(GtkWidget* widget,
|
||||
gint BrowserWindowOsrGtk::ClickEvent(GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!self->browser_.get())
|
||||
return TRUE;
|
||||
@@ -1379,16 +1419,23 @@ gint BrowserWindowOsrGtk::ClickEvent(GtkWidget* widget,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(self->lock_);
|
||||
device_scale_factor = self->device_scale_factor_;
|
||||
}
|
||||
|
||||
CefMouseEvent mouse_event;
|
||||
mouse_event.x = event->x;
|
||||
mouse_event.y = event->y;
|
||||
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
|
||||
DeviceToLogical(mouse_event, self->device_scale_factor_);
|
||||
DeviceToLogical(mouse_event, device_scale_factor);
|
||||
mouse_event.modifiers = GetCefStateModifiers(event->state);
|
||||
|
||||
bool mouse_up = (event->type == GDK_BUTTON_RELEASE);
|
||||
if (!mouse_up)
|
||||
if (!mouse_up) {
|
||||
gtk_widget_grab_focus(widget);
|
||||
}
|
||||
|
||||
int click_count = 1;
|
||||
switch (event->type) {
|
||||
@@ -1420,7 +1467,7 @@ gint BrowserWindowOsrGtk::ClickEvent(GtkWidget* widget,
|
||||
gint BrowserWindowOsrGtk::KeyEvent(GtkWidget* widget,
|
||||
GdkEventKey* event,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!self->browser_.get())
|
||||
return TRUE;
|
||||
@@ -1476,7 +1523,7 @@ gint BrowserWindowOsrGtk::KeyEvent(GtkWidget* widget,
|
||||
gint BrowserWindowOsrGtk::MoveEvent(GtkWidget* widget,
|
||||
GdkEventMotion* event,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!self->browser_.get())
|
||||
return TRUE;
|
||||
@@ -1500,11 +1547,17 @@ gint BrowserWindowOsrGtk::MoveEvent(GtkWidget* widget,
|
||||
}
|
||||
}
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(self->lock_);
|
||||
device_scale_factor = self->device_scale_factor_;
|
||||
}
|
||||
|
||||
CefMouseEvent mouse_event;
|
||||
mouse_event.x = x;
|
||||
mouse_event.y = y;
|
||||
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
|
||||
DeviceToLogical(mouse_event, self->device_scale_factor_);
|
||||
DeviceToLogical(mouse_event, device_scale_factor);
|
||||
mouse_event.modifiers = GetCefStateModifiers(state);
|
||||
|
||||
bool mouse_leave = (event->type == GDK_LEAVE_NOTIFY);
|
||||
@@ -1527,18 +1580,24 @@ gint BrowserWindowOsrGtk::MoveEvent(GtkWidget* widget,
|
||||
gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget,
|
||||
GdkEventScroll* event,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!self->browser_.get())
|
||||
return TRUE;
|
||||
|
||||
CefRefPtr<CefBrowserHost> host = self->browser_->GetHost();
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(self->lock_);
|
||||
device_scale_factor = self->device_scale_factor_;
|
||||
}
|
||||
|
||||
CefMouseEvent mouse_event;
|
||||
mouse_event.x = event->x;
|
||||
mouse_event.y = event->y;
|
||||
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
|
||||
DeviceToLogical(mouse_event, self->device_scale_factor_);
|
||||
DeviceToLogical(mouse_event, device_scale_factor);
|
||||
mouse_event.modifiers = GetCefStateModifiers(event->state);
|
||||
|
||||
static const int scrollbarPixelsPerGtkTick = 40;
|
||||
@@ -1567,8 +1626,7 @@ gint BrowserWindowOsrGtk::ScrollEvent(GtkWidget* widget,
|
||||
gint BrowserWindowOsrGtk::FocusEvent(GtkWidget* widget,
|
||||
GdkEventFocus* event,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
// May be called on the main thread and the UI thread.
|
||||
if (self->browser_.get())
|
||||
self->browser_->GetHost()->SendFocusEvent(event->in == TRUE);
|
||||
return TRUE;
|
||||
@@ -1597,7 +1655,7 @@ void BrowserWindowOsrGtk::ApplyPopupOffset(int& x, int& y) const {
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::EnableGL() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (gl_enabled_)
|
||||
return;
|
||||
@@ -1612,7 +1670,7 @@ void BrowserWindowOsrGtk::EnableGL() {
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::DisableGL() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!gl_enabled_)
|
||||
return;
|
||||
@@ -1629,6 +1687,8 @@ void BrowserWindowOsrGtk::DisableGL() {
|
||||
void BrowserWindowOsrGtk::RegisterDragDrop() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// Succession of CEF d&d calls:
|
||||
// 1. DragTargetDragEnter
|
||||
// 2. DragTargetDragOver
|
||||
@@ -1679,14 +1739,15 @@ void BrowserWindowOsrGtk::RegisterDragDrop() {
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::UnregisterDragDrop() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
gtk_drag_dest_unset(glarea_);
|
||||
// Drag events are unregistered in OnBeforeClose by calling
|
||||
// g_signal_handlers_disconnect_matched.
|
||||
}
|
||||
|
||||
void BrowserWindowOsrGtk::DragReset() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
if (drag_trigger_event_) {
|
||||
gdk_event_free(drag_trigger_event_);
|
||||
drag_trigger_event_ = NULL;
|
||||
@@ -1705,22 +1766,30 @@ void BrowserWindowOsrGtk::DragReset() {
|
||||
void BrowserWindowOsrGtk::DragBegin(GtkWidget* widget,
|
||||
GdkDragContext* drag_context,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Load drag icon.
|
||||
if (!self->drag_data_->HasImage()) {
|
||||
LOG(ERROR) << "Failed to set drag icon, drag image not available";
|
||||
return;
|
||||
}
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(self->lock_);
|
||||
device_scale_factor = self->device_scale_factor_;
|
||||
}
|
||||
|
||||
int pixel_width = 0;
|
||||
int pixel_height = 0;
|
||||
CefRefPtr<CefBinaryValue> image_binary =
|
||||
self->drag_data_->GetImage()->GetAsPNG(self->device_scale_factor_, true,
|
||||
self->drag_data_->GetImage()->GetAsPNG(device_scale_factor, true,
|
||||
pixel_width, pixel_height);
|
||||
if (!image_binary) {
|
||||
LOG(ERROR) << "Failed to set drag icon, drag image error";
|
||||
return;
|
||||
}
|
||||
|
||||
size_t image_size = image_binary->GetSize();
|
||||
guint8* image_buffer = (guint8*)malloc(image_size); // must free
|
||||
image_binary->GetData((void*)image_buffer, image_size, 0);
|
||||
@@ -1768,7 +1837,7 @@ void BrowserWindowOsrGtk::DragDataGet(GtkWidget* widget,
|
||||
guint info,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
// No drag targets are set so this callback is never called.
|
||||
}
|
||||
|
||||
@@ -1776,7 +1845,7 @@ void BrowserWindowOsrGtk::DragDataGet(GtkWidget* widget,
|
||||
void BrowserWindowOsrGtk::DragEnd(GtkWidget* widget,
|
||||
GdkDragContext* drag_context,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (self->browser_) {
|
||||
// Sometimes there is DragEnd event generated without prior DragDrop.
|
||||
@@ -1799,7 +1868,13 @@ gboolean BrowserWindowOsrGtk::DragMotion(GtkWidget* widget,
|
||||
gint y,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
float device_scale_factor;
|
||||
{
|
||||
base::AutoLock lock_scope(self->lock_);
|
||||
device_scale_factor = self->device_scale_factor_;
|
||||
}
|
||||
|
||||
// MoveEvent is never called during drag & drop, so must call
|
||||
// SendMouseMoveEvent here.
|
||||
@@ -1808,7 +1883,7 @@ gboolean BrowserWindowOsrGtk::DragMotion(GtkWidget* widget,
|
||||
mouse_event.y = y;
|
||||
mouse_event.modifiers = EVENTFLAG_LEFT_MOUSE_BUTTON;
|
||||
self->ApplyPopupOffset(mouse_event.x, mouse_event.y);
|
||||
DeviceToLogical(mouse_event, self->device_scale_factor_);
|
||||
DeviceToLogical(mouse_event, device_scale_factor);
|
||||
if (self->browser_) {
|
||||
bool mouse_leave = self->drag_leave_;
|
||||
self->browser_->GetHost()->SendMouseMoveEvent(mouse_event, mouse_leave);
|
||||
@@ -1853,7 +1928,7 @@ void BrowserWindowOsrGtk::DragLeave(GtkWidget* widget,
|
||||
GdkDragContext* drag_context,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// There is no drag-enter event in GTK. The first drag-motion event
|
||||
// after drag-leave will be a drag-enter event.
|
||||
@@ -1875,7 +1950,7 @@ gboolean BrowserWindowOsrGtk::DragFailed(GtkWidget* widget,
|
||||
GdkDragContext* drag_context,
|
||||
GtkDragResult result,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Send drag end coordinates and system drag ended event.
|
||||
if (self->browser_) {
|
||||
@@ -1895,7 +1970,7 @@ gboolean BrowserWindowOsrGtk::DragDrop(GtkWidget* widget,
|
||||
gint y,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Finish GTK drag.
|
||||
gtk_drag_finish(drag_context, TRUE, FALSE, time);
|
||||
@@ -1939,7 +2014,7 @@ void BrowserWindowOsrGtk::DragDataReceived(GtkWidget* widget,
|
||||
guint info,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
// This callback is never called because DragDrop does not call
|
||||
// gtk_drag_get_data, as only dragging inside web view is supported.
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_BROWSER_WINDOW_OSR_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_lock.h"
|
||||
|
||||
#include "tests/cefclient/browser/browser_window.h"
|
||||
#include "tests/cefclient/browser/client_handler_osr.h"
|
||||
#include "tests/cefclient/browser/osr_renderer.h"
|
||||
@@ -24,6 +26,9 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
const std::string& startup_url,
|
||||
const OsrRenderer::Settings& settings);
|
||||
|
||||
// Called from RootWindowGtk::CreateRootWindow before CreateBrowser.
|
||||
void set_xdisplay(XDisplay* xdisplay);
|
||||
|
||||
// BrowserWindow methods.
|
||||
void CreateBrowser(ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
@@ -162,15 +167,18 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
guint time,
|
||||
BrowserWindowOsrGtk* self);
|
||||
|
||||
// The below members will only be accessed on the main thread which should be
|
||||
// the same as the CEF UI thread.
|
||||
XDisplay* xdisplay_;
|
||||
|
||||
// Members only accessed on the UI thread.
|
||||
OsrRenderer renderer_;
|
||||
ClientWindowHandle glarea_;
|
||||
bool hidden_;
|
||||
bool gl_enabled_;
|
||||
bool painting_popup_;
|
||||
|
||||
float device_scale_factor_;
|
||||
// Members only accessed on the main thread.
|
||||
bool hidden_;
|
||||
|
||||
// Members protected by the GDK global lock.
|
||||
ClientWindowHandle glarea_;
|
||||
|
||||
// Drag & drop
|
||||
GdkEvent* drag_trigger_event_; // mouse event, a possible trigger for drag
|
||||
@@ -181,6 +189,11 @@ class BrowserWindowOsrGtk : public BrowserWindow,
|
||||
bool drag_leave_;
|
||||
bool drag_drop_;
|
||||
|
||||
mutable base::Lock lock_;
|
||||
|
||||
// Access to these members must be protected by |lock_|.
|
||||
float device_scale_factor_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindowOsrGtk);
|
||||
};
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "tests/cefclient/browser/client_handler_std.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
@@ -21,14 +22,16 @@ namespace client {
|
||||
namespace {
|
||||
|
||||
::Window GetXWindowForWidget(GtkWidget* widget) {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// The GTK window must be visible before we can retrieve the XID.
|
||||
::Window xwindow = GDK_WINDOW_XID(gtk_widget_get_window(widget));
|
||||
DCHECK(xwindow);
|
||||
return xwindow;
|
||||
}
|
||||
|
||||
void SetXWindowVisible(::Window xwindow, bool visible) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
void SetXWindowVisible(XDisplay* xdisplay, ::Window xwindow, bool visible) {
|
||||
CHECK(xdisplay != 0);
|
||||
|
||||
// Retrieve the atoms required by the below XChangeProperty call.
|
||||
const char* kAtoms[] = {"_NET_WM_STATE", "ATOM", "_NET_WM_STATE_HIDDEN"};
|
||||
@@ -61,12 +64,13 @@ void SetXWindowVisible(::Window xwindow, bool visible) {
|
||||
}
|
||||
}
|
||||
|
||||
void SetXWindowBounds(::Window xwindow,
|
||||
void SetXWindowBounds(XDisplay* xdisplay,
|
||||
::Window xwindow,
|
||||
int x,
|
||||
int y,
|
||||
size_t width,
|
||||
size_t height) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
CHECK(xdisplay != 0);
|
||||
XWindowChanges changes = {0};
|
||||
changes.x = x;
|
||||
changes.y = y;
|
||||
@@ -79,10 +83,16 @@ void SetXWindowBounds(::Window xwindow,
|
||||
|
||||
BrowserWindowStdGtk::BrowserWindowStdGtk(Delegate* delegate,
|
||||
const std::string& startup_url)
|
||||
: BrowserWindow(delegate) {
|
||||
: BrowserWindow(delegate), xdisplay_(nullptr) {
|
||||
client_handler_ = new ClientHandlerStd(this, startup_url);
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::set_xdisplay(XDisplay* xdisplay) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
DCHECK(!xdisplay_);
|
||||
xdisplay_ = xdisplay;
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::CreateBrowser(
|
||||
ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
@@ -118,14 +128,14 @@ void BrowserWindowStdGtk::ShowPopup(ClientWindowHandle parent_handle,
|
||||
|
||||
if (browser_) {
|
||||
::Window parent_xwindow = GetXWindowForWidget(parent_handle);
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
CHECK(xdisplay_ != 0);
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
|
||||
XReparentWindow(xdisplay, xwindow, parent_xwindow, x, y);
|
||||
XReparentWindow(xdisplay_, xwindow, parent_xwindow, x, y);
|
||||
|
||||
SetXWindowBounds(xwindow, x, y, width, height);
|
||||
SetXWindowVisible(xwindow, true);
|
||||
SetXWindowBounds(xdisplay_, xwindow, x, y, width, height);
|
||||
SetXWindowVisible(xdisplay_, xwindow, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +145,7 @@ void BrowserWindowStdGtk::Show() {
|
||||
if (browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowVisible(xwindow, true);
|
||||
SetXWindowVisible(xdisplay_, xwindow, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,17 +155,17 @@ void BrowserWindowStdGtk::Hide() {
|
||||
if (browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowVisible(xwindow, false);
|
||||
SetXWindowVisible(xdisplay_, xwindow, false);
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserWindowStdGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (browser_) {
|
||||
if (xdisplay_ && browser_) {
|
||||
::Window xwindow = browser_->GetHost()->GetWindowHandle();
|
||||
DCHECK(xwindow);
|
||||
SetXWindowBounds(xwindow, x, y, width, height);
|
||||
SetXWindowBounds(xdisplay_, xwindow, x, y, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,9 @@ class BrowserWindowStdGtk : public BrowserWindow {
|
||||
// |delegate| must outlive this object.
|
||||
BrowserWindowStdGtk(Delegate* delegate, const std::string& startup_url);
|
||||
|
||||
// Called from RootWindowGtk::CreateRootWindow before CreateBrowser.
|
||||
void set_xdisplay(XDisplay* xdisplay);
|
||||
|
||||
// BrowserWindow methods.
|
||||
void CreateBrowser(ClientWindowHandle parent_handle,
|
||||
const CefRect& rect,
|
||||
@@ -40,6 +43,8 @@ class BrowserWindowStdGtk : public BrowserWindow {
|
||||
ClientWindowHandle GetWindowHandle() const OVERRIDE;
|
||||
|
||||
private:
|
||||
XDisplay* xdisplay_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(BrowserWindowStdGtk);
|
||||
};
|
||||
|
||||
|
@@ -77,7 +77,7 @@ int BytesWriteHandler::Flush() {
|
||||
}
|
||||
|
||||
size_t BytesWriteHandler::Grow(size_t size) {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
lock_.AssertAcquired();
|
||||
size_t rv;
|
||||
size_t s = (size > grow_ ? size : grow_);
|
||||
void* tmp = realloc(data_, datasize_ + s);
|
||||
|
@@ -11,6 +11,7 @@
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
@@ -130,6 +131,7 @@ void AddFilters(GtkFileChooser* chooser,
|
||||
}
|
||||
|
||||
GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||
if (root_window) {
|
||||
@@ -141,6 +143,10 @@ GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RunCallback(base::Callback<void(GtkWindow*)> callback, GtkWindow* window) {
|
||||
callback.Run(window);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ClientDialogHandlerGtk::ClientDialogHandlerGtk() : gtk_dialog_(NULL) {}
|
||||
@@ -153,6 +159,78 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
const std::vector<CefString>& accept_filters,
|
||||
int selected_accept_filter,
|
||||
CefRefPtr<CefFileDialogCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
OnFileDialogParams params;
|
||||
params.browser = browser;
|
||||
params.mode = mode;
|
||||
params.title = title;
|
||||
params.default_file_path = default_file_path;
|
||||
params.accept_filters = accept_filters;
|
||||
params.selected_accept_filter = selected_accept_filter;
|
||||
params.callback = callback;
|
||||
|
||||
GetWindowAndContinue(
|
||||
browser,
|
||||
base::Bind(&ClientDialogHandlerGtk::OnFileDialogContinue, this, params));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
JSDialogType dialog_type,
|
||||
const CefString& message_text,
|
||||
const CefString& default_prompt_text,
|
||||
CefRefPtr<CefJSDialogCallback> callback,
|
||||
bool& suppress_message) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
OnJSDialogParams params;
|
||||
params.browser = browser;
|
||||
params.origin_url = origin_url;
|
||||
params.dialog_type = dialog_type;
|
||||
params.message_text = message_text;
|
||||
params.default_prompt_text = default_prompt_text;
|
||||
params.callback = callback;
|
||||
|
||||
GetWindowAndContinue(
|
||||
browser,
|
||||
base::Bind(&ClientDialogHandlerGtk::OnJSDialogContinue, this, params));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnBeforeUnloadDialog(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message_text,
|
||||
bool is_reload,
|
||||
CefRefPtr<CefJSDialogCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const std::string& new_message_text =
|
||||
message_text.ToString() + "\n\nIs it OK to leave/reload this page?";
|
||||
bool suppress_message = false;
|
||||
|
||||
return OnJSDialog(browser, CefString(), JSDIALOGTYPE_CONFIRM,
|
||||
new_message_text, CefString(), callback, suppress_message);
|
||||
}
|
||||
|
||||
void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!gtk_dialog_)
|
||||
return;
|
||||
|
||||
gtk_widget_destroy(gtk_dialog_);
|
||||
gtk_dialog_ = NULL;
|
||||
js_dialog_callback_ = NULL;
|
||||
}
|
||||
|
||||
void ClientDialogHandlerGtk::OnFileDialogContinue(OnFileDialogParams params,
|
||||
GtkWindow* window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
std::vector<CefString> files;
|
||||
|
||||
GtkFileChooserAction action;
|
||||
@@ -160,7 +238,7 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
|
||||
// Remove any modifier flags.
|
||||
FileDialogMode mode_type =
|
||||
static_cast<FileDialogMode>(mode & FILE_DIALOG_TYPE_MASK);
|
||||
static_cast<FileDialogMode>(params.mode & FILE_DIALOG_TYPE_MASK);
|
||||
|
||||
if (mode_type == FILE_DIALOG_OPEN || mode_type == FILE_DIALOG_OPEN_MULTIPLE) {
|
||||
action = GTK_FILE_CHOOSER_ACTION_OPEN;
|
||||
@@ -173,12 +251,12 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
accept_button = GTK_STOCK_SAVE;
|
||||
} else {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
params.callback->Cancel();
|
||||
}
|
||||
|
||||
std::string title_str;
|
||||
if (!title.empty()) {
|
||||
title_str = title;
|
||||
if (!params.title.empty()) {
|
||||
title_str = params.title;
|
||||
} else {
|
||||
switch (mode_type) {
|
||||
case FILE_DIALOG_OPEN:
|
||||
@@ -198,10 +276,6 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
}
|
||||
}
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
GtkWidget* dialog = gtk_file_chooser_dialog_new(
|
||||
title_str.c_str(), GTK_WINDOW(window), action, GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_CANCEL, accept_button, GTK_RESPONSE_ACCEPT, NULL);
|
||||
@@ -211,14 +285,15 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
|
||||
if (mode_type == FILE_DIALOG_SAVE) {
|
||||
gtk_file_chooser_set_do_overwrite_confirmation(
|
||||
GTK_FILE_CHOOSER(dialog), !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
||||
GTK_FILE_CHOOSER(dialog),
|
||||
!!(params.mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG));
|
||||
}
|
||||
|
||||
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
||||
!(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
||||
gtk_file_chooser_set_show_hidden(
|
||||
GTK_FILE_CHOOSER(dialog), !(params.mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
||||
|
||||
if (!default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
|
||||
const std::string& file_path = default_file_path;
|
||||
if (!params.default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
|
||||
const std::string& file_path = params.default_file_path;
|
||||
bool exists = false;
|
||||
|
||||
struct stat sb;
|
||||
@@ -237,10 +312,10 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
}
|
||||
|
||||
std::vector<GtkFileFilter*> filters;
|
||||
AddFilters(GTK_FILE_CHOOSER(dialog), accept_filters, true, &filters);
|
||||
if (selected_accept_filter < static_cast<int>(filters.size())) {
|
||||
AddFilters(GTK_FILE_CHOOSER(dialog), params.accept_filters, true, &filters);
|
||||
if (params.selected_accept_filter < static_cast<int>(filters.size())) {
|
||||
gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog),
|
||||
filters[selected_accept_filter]);
|
||||
filters[params.selected_accept_filter]);
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
@@ -267,7 +342,7 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
}
|
||||
}
|
||||
|
||||
int filter_index = selected_accept_filter;
|
||||
int filter_index = params.selected_accept_filter;
|
||||
if (success) {
|
||||
GtkFileFilter* selected_filter =
|
||||
gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog));
|
||||
@@ -284,27 +359,22 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
gtk_widget_destroy(dialog);
|
||||
|
||||
if (success)
|
||||
callback->Continue(filter_index, files);
|
||||
params.callback->Continue(filter_index, files);
|
||||
else
|
||||
callback->Cancel();
|
||||
|
||||
return true;
|
||||
params.callback->Cancel();
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
JSDialogType dialog_type,
|
||||
const CefString& message_text,
|
||||
const CefString& default_prompt_text,
|
||||
CefRefPtr<CefJSDialogCallback> callback,
|
||||
bool& suppress_message) {
|
||||
void ClientDialogHandlerGtk::OnJSDialogContinue(OnJSDialogParams params,
|
||||
GtkWindow* window) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkButtonsType buttons = GTK_BUTTONS_NONE;
|
||||
GtkMessageType gtk_message_type = GTK_MESSAGE_OTHER;
|
||||
std::string title;
|
||||
|
||||
switch (dialog_type) {
|
||||
switch (params.dialog_type) {
|
||||
case JSDIALOGTYPE_ALERT:
|
||||
buttons = GTK_BUTTONS_NONE;
|
||||
gtk_message_type = GTK_MESSAGE_WARNING;
|
||||
@@ -324,20 +394,16 @@ bool ClientDialogHandlerGtk::OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
break;
|
||||
}
|
||||
|
||||
js_dialog_callback_ = callback;
|
||||
js_dialog_callback_ = params.callback;
|
||||
|
||||
if (!origin_url.empty()) {
|
||||
if (!params.origin_url.empty()) {
|
||||
title += " - ";
|
||||
title += CefFormatUrlForSecurityDisplay(origin_url).ToString();
|
||||
title += CefFormatUrlForSecurityDisplay(params.origin_url).ToString();
|
||||
}
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
return false;
|
||||
|
||||
gtk_dialog_ = gtk_message_dialog_new(GTK_WINDOW(window), GTK_DIALOG_MODAL,
|
||||
gtk_message_type, buttons, "%s",
|
||||
message_text.ToString().c_str());
|
||||
params.message_text.ToString().c_str());
|
||||
g_signal_connect(gtk_dialog_, "delete-event",
|
||||
G_CALLBACK(gtk_widget_hide_on_delete), NULL);
|
||||
|
||||
@@ -346,15 +412,15 @@ bool ClientDialogHandlerGtk::OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
GtkWidget* ok_button = gtk_dialog_add_button(GTK_DIALOG(gtk_dialog_),
|
||||
GTK_STOCK_OK, GTK_RESPONSE_OK);
|
||||
|
||||
if (dialog_type != JSDIALOGTYPE_PROMPT)
|
||||
if (params.dialog_type != JSDIALOGTYPE_PROMPT)
|
||||
gtk_widget_grab_focus(ok_button);
|
||||
|
||||
if (dialog_type == JSDIALOGTYPE_PROMPT) {
|
||||
if (params.dialog_type == JSDIALOGTYPE_PROMPT) {
|
||||
GtkWidget* content_area =
|
||||
gtk_dialog_get_content_area(GTK_DIALOG(gtk_dialog_));
|
||||
GtkWidget* text_box = gtk_entry_new();
|
||||
gtk_entry_set_text(GTK_ENTRY(text_box),
|
||||
default_prompt_text.ToString().c_str());
|
||||
params.default_prompt_text.ToString().c_str());
|
||||
gtk_box_pack_start(GTK_BOX(content_area), text_box, TRUE, TRUE, 0);
|
||||
g_object_set_data(G_OBJECT(gtk_dialog_), kPromptTextId, text_box);
|
||||
gtk_entry_set_activates_default(GTK_ENTRY(text_box), TRUE);
|
||||
@@ -363,33 +429,21 @@ bool ClientDialogHandlerGtk::OnJSDialog(CefRefPtr<CefBrowser> browser,
|
||||
gtk_dialog_set_default_response(GTK_DIALOG(gtk_dialog_), GTK_RESPONSE_OK);
|
||||
g_signal_connect(gtk_dialog_, "response", G_CALLBACK(OnDialogResponse), this);
|
||||
gtk_widget_show_all(GTK_WIDGET(gtk_dialog_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientDialogHandlerGtk::OnBeforeUnloadDialog(
|
||||
void ClientDialogHandlerGtk::GetWindowAndContinue(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& message_text,
|
||||
bool is_reload,
|
||||
CefRefPtr<CefJSDialogCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const std::string& new_message_text =
|
||||
message_text.ToString() + "\n\nIs it OK to leave/reload this page?";
|
||||
bool suppress_message = false;
|
||||
|
||||
return OnJSDialog(browser, CefString(), JSDIALOGTYPE_CONFIRM,
|
||||
new_message_text, CefString(), callback, suppress_message);
|
||||
}
|
||||
|
||||
void ClientDialogHandlerGtk::OnResetDialogState(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!gtk_dialog_)
|
||||
base::Callback<void(GtkWindow*)> callback) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&ClientDialogHandlerGtk::GetWindowAndContinue,
|
||||
this, browser, callback));
|
||||
return;
|
||||
gtk_widget_destroy(gtk_dialog_);
|
||||
gtk_dialog_ = NULL;
|
||||
js_dialog_callback_ = NULL;
|
||||
}
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (window) {
|
||||
CefPostTask(TID_UI, base::Bind(RunCallback, callback, window));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "include/base/cef_callback_forward.h"
|
||||
#include "include/cef_dialog_handler.h"
|
||||
#include "include/cef_jsdialog_handler.h"
|
||||
|
||||
@@ -42,6 +43,30 @@ class ClientDialogHandlerGtk : public CefDialogHandler,
|
||||
void OnResetDialogState(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
||||
private:
|
||||
struct OnFileDialogParams {
|
||||
CefRefPtr<CefBrowser> browser;
|
||||
FileDialogMode mode;
|
||||
CefString title;
|
||||
CefString default_file_path;
|
||||
std::vector<CefString> accept_filters;
|
||||
int selected_accept_filter;
|
||||
CefRefPtr<CefFileDialogCallback> callback;
|
||||
};
|
||||
void OnFileDialogContinue(OnFileDialogParams params, GtkWindow* window);
|
||||
|
||||
struct OnJSDialogParams {
|
||||
CefRefPtr<CefBrowser> browser;
|
||||
CefString origin_url;
|
||||
JSDialogType dialog_type;
|
||||
CefString message_text;
|
||||
CefString default_prompt_text;
|
||||
CefRefPtr<CefJSDialogCallback> callback;
|
||||
};
|
||||
void OnJSDialogContinue(OnJSDialogParams params, GtkWindow* window);
|
||||
|
||||
void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
|
||||
base::Callback<void(GtkWindow*)> callback);
|
||||
|
||||
static void OnDialogResponse(GtkDialog* dialog,
|
||||
gint response_id,
|
||||
ClientDialogHandlerGtk* handler);
|
||||
|
@@ -135,7 +135,7 @@ bool MainContextImpl::UseWindowlessRendering() {
|
||||
}
|
||||
|
||||
void MainContextImpl::PopulateSettings(CefSettings* settings) {
|
||||
#if defined(OS_WIN)
|
||||
#if defined(OS_WIN) || defined(OS_LINUX)
|
||||
settings->multi_threaded_message_loop =
|
||||
command_line_->HasSwitch(switches::kMultiThreadedMessageLoop);
|
||||
#endif
|
||||
|
155
tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc
Normal file
155
tests/cefclient/browser/main_message_loop_multithreaded_gtk.cc
Normal file
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
#include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
base::Lock g_global_lock;
|
||||
base::PlatformThreadId g_global_lock_thread = kInvalidPlatformThreadId;
|
||||
|
||||
void lock_enter() {
|
||||
// The GDK lock is not reentrant, so check that we're using it correctly.
|
||||
// See comments on ScopedGdkThreadsEnter.
|
||||
base::PlatformThreadId current_thread = base::PlatformThread::CurrentId();
|
||||
CHECK(current_thread != g_global_lock_thread);
|
||||
|
||||
g_global_lock.Acquire();
|
||||
g_global_lock_thread = current_thread;
|
||||
}
|
||||
|
||||
void lock_leave() {
|
||||
g_global_lock_thread = kInvalidPlatformThreadId;
|
||||
g_global_lock.Release();
|
||||
}
|
||||
|
||||
// Same as g_idle_add() but specifying the GMainContext.
|
||||
guint idle_add(GMainContext* main_context,
|
||||
GSourceFunc function,
|
||||
gpointer data) {
|
||||
GSource* source = g_idle_source_new();
|
||||
g_source_set_callback(source, function, data, nullptr);
|
||||
guint id = g_source_attach(source, main_context);
|
||||
g_source_unref(source);
|
||||
return id;
|
||||
}
|
||||
|
||||
// Same as g_timeout_add() but specifying the GMainContext.
|
||||
guint timeout_add(GMainContext* main_context,
|
||||
guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data) {
|
||||
GSource* source = g_timeout_source_new(interval);
|
||||
g_source_set_callback(source, function, data, nullptr);
|
||||
guint id = g_source_attach(source, main_context);
|
||||
g_source_unref(source);
|
||||
return id;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
MainMessageLoopMultithreadedGtk::MainMessageLoopMultithreadedGtk()
|
||||
: thread_id_(base::PlatformThread::CurrentId()) {
|
||||
// Initialize Xlib support for concurrent threads. This function must be the
|
||||
// first Xlib function a multi-threaded program calls, and it must complete
|
||||
// before any other Xlib call is made.
|
||||
CHECK(XInitThreads() != 0);
|
||||
|
||||
// Initialize GDK thread support. See comments on ScopedGdkThreadsEnter.
|
||||
gdk_threads_set_lock_functions(lock_enter, lock_leave);
|
||||
gdk_threads_init();
|
||||
}
|
||||
|
||||
MainMessageLoopMultithreadedGtk::~MainMessageLoopMultithreadedGtk() {
|
||||
DCHECK(RunsTasksOnCurrentThread());
|
||||
DCHECK(queued_tasks_.empty());
|
||||
}
|
||||
|
||||
int MainMessageLoopMultithreadedGtk::Run() {
|
||||
DCHECK(RunsTasksOnCurrentThread());
|
||||
|
||||
// Chromium uses the default GLib context so we create our own context and
|
||||
// make it the default for this thread.
|
||||
main_context_ = g_main_context_new();
|
||||
g_main_context_push_thread_default(main_context_);
|
||||
|
||||
main_loop_ = g_main_loop_new(main_context_, TRUE);
|
||||
|
||||
// Check the queue when GTK is idle, or at least every 100ms.
|
||||
// TODO(cef): It might be more efficient to use input functions
|
||||
// (gdk_input_add) and trigger by writing to an fd.
|
||||
idle_add(main_context_, MainMessageLoopMultithreadedGtk::TriggerRunTasks,
|
||||
this);
|
||||
timeout_add(main_context_, 100,
|
||||
MainMessageLoopMultithreadedGtk::TriggerRunTasks, this);
|
||||
|
||||
// Block until g_main_loop_quit().
|
||||
g_main_loop_run(main_loop_);
|
||||
|
||||
// Release GLib resources.
|
||||
g_main_loop_unref(main_loop_);
|
||||
main_loop_ = nullptr;
|
||||
|
||||
g_main_context_pop_thread_default(main_context_);
|
||||
g_main_context_unref(main_context_);
|
||||
main_context_ = nullptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MainMessageLoopMultithreadedGtk::Quit() {
|
||||
PostTask(CefCreateClosureTask(base::Bind(
|
||||
&MainMessageLoopMultithreadedGtk::DoQuit, base::Unretained(this))));
|
||||
}
|
||||
|
||||
void MainMessageLoopMultithreadedGtk::PostTask(CefRefPtr<CefTask> task) {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
|
||||
// Queue the task.
|
||||
queued_tasks_.push(task);
|
||||
}
|
||||
|
||||
bool MainMessageLoopMultithreadedGtk::RunsTasksOnCurrentThread() const {
|
||||
return (thread_id_ == base::PlatformThread::CurrentId());
|
||||
}
|
||||
|
||||
// static
|
||||
int MainMessageLoopMultithreadedGtk::TriggerRunTasks(void* self) {
|
||||
static_cast<MainMessageLoopMultithreadedGtk*>(self)->RunTasks();
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
void MainMessageLoopMultithreadedGtk::RunTasks() {
|
||||
DCHECK(RunsTasksOnCurrentThread());
|
||||
|
||||
std::queue<CefRefPtr<CefTask>> tasks;
|
||||
|
||||
{
|
||||
base::AutoLock lock_scope(lock_);
|
||||
tasks.swap(queued_tasks_);
|
||||
}
|
||||
|
||||
// Execute all queued tasks.
|
||||
while (!tasks.empty()) {
|
||||
CefRefPtr<CefTask> task = tasks.front();
|
||||
tasks.pop();
|
||||
task->Execute();
|
||||
}
|
||||
}
|
||||
|
||||
void MainMessageLoopMultithreadedGtk::DoQuit() {
|
||||
DCHECK(RunsTasksOnCurrentThread());
|
||||
g_main_loop_quit(main_loop_);
|
||||
}
|
||||
|
||||
} // namespace client
|
@@ -0,0 +1,54 @@
|
||||
// Copyright (c) 2018 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_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_MULTITHREADED_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_MULTITHREADED_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include "include/base/cef_lock.h"
|
||||
#include "include/base/cef_platform_thread.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Represents the main message loop in the browser process when using multi-
|
||||
// threaded message loop mode on Linux. In this mode there is no Chromium
|
||||
// message loop running on the main application thread. Instead, this
|
||||
// implementation utilizes a Glib context for running tasks.
|
||||
class MainMessageLoopMultithreadedGtk : public MainMessageLoop {
|
||||
public:
|
||||
MainMessageLoopMultithreadedGtk();
|
||||
~MainMessageLoopMultithreadedGtk();
|
||||
|
||||
// MainMessageLoop methods.
|
||||
int Run() OVERRIDE;
|
||||
void Quit() OVERRIDE;
|
||||
void PostTask(CefRefPtr<CefTask> task) OVERRIDE;
|
||||
bool RunsTasksOnCurrentThread() const OVERRIDE;
|
||||
|
||||
private:
|
||||
static int TriggerRunTasks(void* self);
|
||||
void RunTasks();
|
||||
void DoQuit();
|
||||
|
||||
base::PlatformThreadId thread_id_;
|
||||
|
||||
GMainContext* main_context_;
|
||||
GMainLoop* main_loop_;
|
||||
|
||||
base::Lock lock_;
|
||||
|
||||
// Must be protected by |lock_|.
|
||||
std::queue<CefRefPtr<CefTask>> queued_tasks_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MainMessageLoopMultithreadedGtk);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_MAIN_MESSAGE_LOOP_MULTITHREADED_GTK_H_
|
@@ -10,11 +10,13 @@
|
||||
#include <gtk/gtk.h>
|
||||
#include <gtk/gtkunixprint.h>
|
||||
|
||||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
@@ -270,6 +272,33 @@ void InitPrintSettings(GtkPrintSettings* settings,
|
||||
printable_area_device_units, true);
|
||||
}
|
||||
|
||||
// Returns the GtkWindow* for the browser. Will return NULL when using the Views
|
||||
// framework.
|
||||
GtkWindow* GetWindow(CefRefPtr<CefBrowser> browser) {
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::GetForBrowser(browser->GetIdentifier());
|
||||
if (root_window)
|
||||
return GTK_WINDOW(root_window->GetWindowHandle());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void RunCallback(base::Callback<void(GtkWindow*)> callback, GtkWindow* window) {
|
||||
callback.Run(window);
|
||||
}
|
||||
|
||||
void GetWindowAndContinue(CefRefPtr<CefBrowser> browser,
|
||||
base::Callback<void(GtkWindow*)> callback) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(GetWindowAndContinue, browser, callback));
|
||||
return;
|
||||
}
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (window) {
|
||||
CefPostTask(TID_UI, base::Bind(RunCallback, callback, window));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
struct ClientPrintHandlerGtk::PrintHandler {
|
||||
@@ -281,6 +310,8 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
printer_(NULL) {}
|
||||
|
||||
~PrintHandler() {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (dialog_) {
|
||||
gtk_widget_destroy(dialog_);
|
||||
dialog_ = NULL;
|
||||
@@ -301,6 +332,8 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
|
||||
void OnPrintSettings(CefRefPtr<CefPrintSettings> settings,
|
||||
bool get_defaults) {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (get_defaults) {
|
||||
DCHECK(!page_setup_);
|
||||
DCHECK(!printer_);
|
||||
@@ -369,11 +402,13 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
InitPrintSettings(gtk_settings_, page_setup_, settings);
|
||||
}
|
||||
|
||||
bool OnPrintDialog(bool has_selection,
|
||||
CefRefPtr<CefPrintDialogCallback> callback) {
|
||||
void OnPrintDialog(bool has_selection,
|
||||
CefRefPtr<CefPrintDialogCallback> callback,
|
||||
GtkWindow* parent) {
|
||||
dialog_callback_ = callback;
|
||||
|
||||
GtkWindow* parent = GetWindow();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// TODO(estade): We need a window title here.
|
||||
dialog_ = gtk_print_unix_dialog_new(NULL, parent);
|
||||
g_signal_connect(dialog_, "delete-event",
|
||||
@@ -401,8 +436,6 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
g_signal_connect(dialog_, "response", G_CALLBACK(OnDialogResponseThunk),
|
||||
this);
|
||||
gtk_widget_show(dialog_);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OnPrintJob(const CefString& document_name,
|
||||
@@ -413,6 +446,8 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
if (!printer_)
|
||||
return false;
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
job_callback_ = callback;
|
||||
|
||||
// Save the settings for next time.
|
||||
@@ -428,16 +463,6 @@ struct ClientPrintHandlerGtk::PrintHandler {
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns the GtkWindow* for the browser. Will return NULL when using the
|
||||
// Views framework.
|
||||
GtkWindow* GetWindow() {
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
RootWindow::GetForBrowser(browser_->GetIdentifier());
|
||||
if (root_window)
|
||||
return GTK_WINDOW(root_window->GetWindowHandle());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void OnDialogResponse(GtkDialog* dialog, gint response_id) {
|
||||
int num_matched_handlers = g_signal_handlers_disconnect_by_func(
|
||||
dialog_, reinterpret_cast<gpointer>(&OnDialogResponseThunk), this);
|
||||
@@ -581,7 +606,11 @@ bool ClientPrintHandlerGtk::OnPrintDialog(
|
||||
CefRefPtr<CefPrintDialogCallback> callback) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
return GetPrintHandler(browser)->OnPrintDialog(has_selection, callback);
|
||||
PrintHandler* print_handler = GetPrintHandler(browser);
|
||||
GetWindowAndContinue(browser, base::Bind(&PrintHandler::OnPrintDialog,
|
||||
base::Unretained(print_handler),
|
||||
has_selection, callback));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ClientPrintHandlerGtk::OnPrintJob(
|
||||
@@ -609,6 +638,8 @@ void ClientPrintHandlerGtk::OnPrintReset(CefRefPtr<CefBrowser> browser) {
|
||||
CefSize ClientPrintHandlerGtk::GetPdfPaperSize(int device_units_per_inch) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkPageSetup* page_setup = gtk_page_setup_new();
|
||||
|
||||
float width = gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH);
|
||||
|
@@ -18,6 +18,7 @@
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/resource.h"
|
||||
#include "tests/cefclient/browser/temp_window.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
#include "tests/cefclient/browser/window_test_runner_gtk.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
@@ -62,9 +63,10 @@ RootWindowGtk::RootWindowGtk()
|
||||
url_entry_(NULL),
|
||||
toolbar_height_(0),
|
||||
menubar_height_(0),
|
||||
force_close_(false),
|
||||
window_destroyed_(false),
|
||||
browser_destroyed_(false) {}
|
||||
browser_destroyed_(false),
|
||||
force_close_(false),
|
||||
is_closing_(false) {}
|
||||
|
||||
RootWindowGtk::~RootWindowGtk() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
@@ -140,6 +142,8 @@ void RootWindowGtk::Show(ShowMode mode) {
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
// Show the GTK window.
|
||||
gtk_widget_show_all(window_);
|
||||
|
||||
@@ -158,6 +162,8 @@ void RootWindowGtk::Show(ShowMode mode) {
|
||||
void RootWindowGtk::Hide() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (window_)
|
||||
gtk_widget_hide(window_);
|
||||
}
|
||||
@@ -168,6 +174,8 @@ void RootWindowGtk::SetBounds(int x, int y, size_t width, size_t height) {
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GTK_WINDOW(window_);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
||||
|
||||
@@ -184,7 +192,11 @@ void RootWindowGtk::Close(bool force) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (window_) {
|
||||
force_close_ = force;
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
if (force) {
|
||||
NotifyForceClose();
|
||||
}
|
||||
gtk_widget_destroy(window_);
|
||||
}
|
||||
}
|
||||
@@ -258,7 +270,11 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
height = start_rect_.height;
|
||||
}
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||
CHECK(window_);
|
||||
|
||||
gtk_window_set_default_size(GTK_WINDOW(window_), width, height);
|
||||
g_signal_connect(G_OBJECT(window_), "focus-in-event",
|
||||
G_CALLBACK(&RootWindowGtk::WindowFocusIn), this);
|
||||
@@ -345,6 +361,17 @@ void RootWindowGtk::CreateRootWindow(const CefBrowserSettings& settings,
|
||||
// added to the Vbox container for automatic layout-based sizing.
|
||||
GtkWidget* parent = with_osr_ ? vbox : window_;
|
||||
|
||||
// Set the Display associated with the browser.
|
||||
::Display* xdisplay = GDK_WINDOW_XDISPLAY(gtk_widget_get_window(window_));
|
||||
CHECK(xdisplay);
|
||||
if (with_osr_) {
|
||||
static_cast<BrowserWindowOsrGtk*>(browser_window_.get())
|
||||
->set_xdisplay(xdisplay);
|
||||
} else {
|
||||
static_cast<BrowserWindowStdGtk*>(browser_window_.get())
|
||||
->set_xdisplay(xdisplay);
|
||||
}
|
||||
|
||||
if (!is_popup_) {
|
||||
// Create the browser window.
|
||||
browser_window_->CreateBrowser(parent, browser_bounds_, settings,
|
||||
@@ -368,6 +395,16 @@ void RootWindowGtk::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
|
||||
delegate_->OnBrowserCreated(this, browser);
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnBrowserWindowClosing() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&RootWindowGtk::OnBrowserWindowClosing, this));
|
||||
return;
|
||||
}
|
||||
|
||||
is_closing_ = true;
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnBrowserWindowDestroyed() {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
@@ -380,14 +417,15 @@ void RootWindowGtk::OnBrowserWindowDestroyed() {
|
||||
Close(true);
|
||||
}
|
||||
|
||||
browser_destroyed_ = true;
|
||||
NotifyDestroyedIfDone();
|
||||
NotifyDestroyedIfDone(false, true);
|
||||
}
|
||||
|
||||
void RootWindowGtk::OnSetAddress(const std::string& url) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (url_entry_) {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
std::string urlStr(url);
|
||||
gtk_entry_set_text(GTK_ENTRY(url_entry_), urlStr.c_str());
|
||||
}
|
||||
@@ -397,6 +435,8 @@ void RootWindowGtk::OnSetTitle(const std::string& title) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (window_) {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
std::string titleStr(title);
|
||||
gtk_window_set_title(GTK_WINDOW(window_), titleStr.c_str());
|
||||
}
|
||||
@@ -422,6 +462,8 @@ void RootWindowGtk::OnAutoResize(const CefSize& new_size) {
|
||||
if (!window_)
|
||||
return;
|
||||
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GTK_WINDOW(window_);
|
||||
GdkWindow* gdk_window = gtk_widget_get_window(window_);
|
||||
|
||||
@@ -440,6 +482,8 @@ void RootWindowGtk::OnSetLoadingState(bool isLoading,
|
||||
REQUIRE_MAIN_THREAD();
|
||||
|
||||
if (with_controls_) {
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(stop_button_), isLoading);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(reload_button_), !isLoading);
|
||||
gtk_widget_set_sensitive(GTK_WIDGET(back_button_), canGoBack);
|
||||
@@ -453,7 +497,176 @@ void RootWindowGtk::OnSetDraggableRegions(
|
||||
// TODO(cef): Implement support for draggable regions on this platform.
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyDestroyedIfDone() {
|
||||
void RootWindowGtk::NotifyMoveOrResizeStarted() {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::NotifyMoveOrResizeStarted, this));
|
||||
return;
|
||||
}
|
||||
|
||||
// Called when size, position or stack order changes.
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
if (browser.get()) {
|
||||
// Notify the browser of move/resize events so that:
|
||||
// - Popup windows are displayed in the correct location and dismissed
|
||||
// when the window moves.
|
||||
// - Drag&drop areas are updated accordingly.
|
||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifySetFocus() {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifySetFocus, this));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!browser_window_.get())
|
||||
return;
|
||||
|
||||
browser_window_->SetFocus(true);
|
||||
delegate_->OnRootWindowActivated(this);
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyVisibilityChange(bool show) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::NotifyVisibilityChange, this, show));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!browser_window_.get())
|
||||
return;
|
||||
|
||||
if (show)
|
||||
browser_window_->Show();
|
||||
else
|
||||
browser_window_->Hide();
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyMenuBarHeight(int height) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::NotifyMenuBarHeight, this, height));
|
||||
return;
|
||||
}
|
||||
|
||||
menubar_height_ = height;
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyContentBounds(int x, int y, int width, int height) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyContentBounds, this, x,
|
||||
y, width, height));
|
||||
return;
|
||||
}
|
||||
|
||||
// Offset browser positioning by any controls that will appear in the client
|
||||
// area.
|
||||
const int ux_height = toolbar_height_ + menubar_height_;
|
||||
const int browser_x = x;
|
||||
const int browser_y = y + ux_height;
|
||||
const int browser_width = width;
|
||||
const int browser_height = height - ux_height;
|
||||
|
||||
// Size the browser window to match the GTK widget.
|
||||
browser_bounds_ =
|
||||
CefRect(browser_x, browser_y, browser_width, browser_height);
|
||||
if (browser_window_.get()) {
|
||||
browser_window_->SetBounds(browser_x, browser_y, browser_width,
|
||||
browser_height);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyLoadURL(const std::string& url) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyLoadURL, this, url));
|
||||
return;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
if (browser.get()) {
|
||||
browser->GetMainFrame()->LoadURL(url);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyButtonClicked(int id) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(
|
||||
base::Bind(&RootWindowGtk::NotifyButtonClicked, this, id));
|
||||
return;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
if (!browser.get())
|
||||
return;
|
||||
|
||||
switch (id) {
|
||||
case IDC_NAV_BACK:
|
||||
browser->GoBack();
|
||||
break;
|
||||
case IDC_NAV_FORWARD:
|
||||
browser->GoForward();
|
||||
break;
|
||||
case IDC_NAV_RELOAD:
|
||||
browser->Reload();
|
||||
break;
|
||||
case IDC_NAV_STOP:
|
||||
browser->StopLoad();
|
||||
break;
|
||||
default:
|
||||
NOTREACHED() << "id=" << id;
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyMenuItem(int id) {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyMenuItem, this, id));
|
||||
return;
|
||||
}
|
||||
|
||||
// Run the test.
|
||||
if (delegate_)
|
||||
delegate_->OnTest(this, id);
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyForceClose() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI, base::Bind(&RootWindowGtk::NotifyForceClose, this));
|
||||
return;
|
||||
}
|
||||
|
||||
force_close_ = true;
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyCloseBrowser() {
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyCloseBrowser, this));
|
||||
return;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> browser = GetBrowser();
|
||||
if (browser) {
|
||||
browser->GetHost()->CloseBrowser(false);
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowGtk::NotifyDestroyedIfDone(bool window_destroyed,
|
||||
bool browser_destroyed) {
|
||||
// Each call will to this method will set only one state flag.
|
||||
DCHECK_EQ(1, window_destroyed + browser_destroyed);
|
||||
|
||||
if (!CURRENTLY_ON_MAIN_THREAD()) {
|
||||
MAIN_POST_CLOSURE(base::Bind(&RootWindowGtk::NotifyDestroyedIfDone, this,
|
||||
window_destroyed, browser_destroyed));
|
||||
return;
|
||||
}
|
||||
|
||||
if (window_destroyed)
|
||||
window_destroyed_ = true;
|
||||
if (browser_destroyed)
|
||||
browser_destroyed_ = true;
|
||||
|
||||
// Notify once both the window and the browser have been destroyed.
|
||||
if (window_destroyed_ && browser_destroyed_)
|
||||
delegate_->OnRootWindowDestroyed(this);
|
||||
@@ -463,9 +676,11 @@ void RootWindowGtk::NotifyDestroyedIfDone() {
|
||||
gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
|
||||
GdkEventFocus* event,
|
||||
RootWindowGtk* self) {
|
||||
if (event->in && self->browser_window_.get()) {
|
||||
self->browser_window_->SetFocus(true);
|
||||
self->delegate_->OnRootWindowActivated(self);
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (event->in) {
|
||||
self->NotifySetFocus();
|
||||
|
||||
// Return true for a windowed browser so that focus is not passed to GTK.
|
||||
return self->with_osr_ ? FALSE : TRUE;
|
||||
}
|
||||
@@ -477,14 +692,13 @@ gboolean RootWindowGtk::WindowFocusIn(GtkWidget* widget,
|
||||
gboolean RootWindowGtk::WindowState(GtkWidget* widget,
|
||||
GdkEventWindowState* event,
|
||||
RootWindowGtk* self) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Called when the root window is iconified or restored. Hide the browser
|
||||
// window when the root window is iconified to reduce resource usage.
|
||||
if ((event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) &&
|
||||
self->browser_window_.get()) {
|
||||
if (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED)
|
||||
self->browser_window_->Hide();
|
||||
else
|
||||
self->browser_window_->Show();
|
||||
if (event->changed_mask & GDK_WINDOW_STATE_ICONIFIED) {
|
||||
self->NotifyVisibilityChange(
|
||||
!(event->new_window_state & GDK_WINDOW_STATE_ICONIFIED));
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
@@ -494,46 +708,36 @@ gboolean RootWindowGtk::WindowState(GtkWidget* widget,
|
||||
gboolean RootWindowGtk::WindowConfigure(GtkWindow* window,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self) {
|
||||
// Called when size, position or stack order changes.
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get()) {
|
||||
// Notify the browser of move/resize events so that:
|
||||
// - Popup windows are displayed in the correct location and dismissed
|
||||
// when the window moves.
|
||||
// - Drag&drop areas are updated accordingly.
|
||||
browser->GetHost()->NotifyMoveOrResizeStarted();
|
||||
}
|
||||
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
self->NotifyMoveOrResizeStarted();
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::WindowDestroy(GtkWidget* widget, RootWindowGtk* self) {
|
||||
// Called when the root window is destroyed.
|
||||
self->window_destroyed_ = true;
|
||||
self->NotifyDestroyedIfDone();
|
||||
// May be called on the main thread or the UI thread.
|
||||
self->NotifyDestroyedIfDone(true, false);
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
|
||||
GdkEvent* event,
|
||||
RootWindowGtk* self) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Called to query whether the root window should be closed.
|
||||
if (self->force_close_)
|
||||
return FALSE; // Allow the close.
|
||||
|
||||
if (self->browser_window_.get() && !self->browser_window_->IsClosing()) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser) {
|
||||
if (!self->is_closing_) {
|
||||
// Notify the browser window that we would like to close it. This
|
||||
// will result in a call to ClientHandler::DoClose() if the
|
||||
// JavaScript 'onbeforeunload' event handler allows it.
|
||||
browser->GetHost()->CloseBrowser(false);
|
||||
self->NotifyCloseBrowser();
|
||||
|
||||
// Cancel the close.
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow the close.
|
||||
return FALSE;
|
||||
@@ -543,35 +747,27 @@ gboolean RootWindowGtk::WindowDelete(GtkWidget* widget,
|
||||
void RootWindowGtk::VboxSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self) {
|
||||
// Offset browser positioning by any controls that will appear in the client
|
||||
// area.
|
||||
const int ux_height = self->toolbar_height_ + self->menubar_height_;
|
||||
const int x = allocation->x;
|
||||
const int y = allocation->y + ux_height;
|
||||
const int width = allocation->width;
|
||||
const int height = allocation->height - ux_height;
|
||||
|
||||
// Size the browser window to match the GTK widget.
|
||||
self->browser_bounds_ = CefRect(x, y, width, height);
|
||||
if (self->browser_window_.get())
|
||||
self->browser_window_->SetBounds(x, y, width, height);
|
||||
// May be called on the main thread and the UI thread.
|
||||
self->NotifyContentBounds(allocation->x, allocation->y, allocation->width,
|
||||
allocation->height);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::MenubarSizeAllocated(GtkWidget* widget,
|
||||
GtkAllocation* allocation,
|
||||
RootWindowGtk* self) {
|
||||
self->menubar_height_ = allocation->height;
|
||||
// May be called on the main thread and the UI thread.
|
||||
self->NotifyMenuBarHeight(allocation->height);
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::MenuItemActivated(GtkWidget* widget,
|
||||
RootWindowGtk* self) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Retrieve the menu ID set in AddMenuEntry.
|
||||
int id = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), kMenuIdKey));
|
||||
// Run the test.
|
||||
if (self->delegate_)
|
||||
self->delegate_->OnTest(self, id);
|
||||
self->NotifyMenuItem(id);
|
||||
|
||||
return FALSE; // Don't stop this message.
|
||||
}
|
||||
@@ -585,47 +781,43 @@ void RootWindowGtk::ToolbarSizeAllocated(GtkWidget* widget,
|
||||
|
||||
// static
|
||||
void RootWindowGtk::BackButtonClicked(GtkButton* button, RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->GoBack();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
self->NotifyButtonClicked(IDC_NAV_BACK);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::ForwardButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->GoForward();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
self->NotifyButtonClicked(IDC_NAV_FORWARD);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::StopButtonClicked(GtkButton* button, RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->StopLoad();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
self->NotifyButtonClicked(IDC_NAV_STOP);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::ReloadButtonClicked(GtkButton* button,
|
||||
RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get())
|
||||
browser->Reload();
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
self->NotifyButtonClicked(IDC_NAV_RELOAD);
|
||||
}
|
||||
|
||||
// static
|
||||
void RootWindowGtk::URLEntryActivate(GtkEntry* entry, RootWindowGtk* self) {
|
||||
CefRefPtr<CefBrowser> browser = self->GetBrowser();
|
||||
if (browser.get()) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
const gchar* url = gtk_entry_get_text(entry);
|
||||
browser->GetMainFrame()->LoadURL(std::string(url).c_str());
|
||||
}
|
||||
self->NotifyLoadURL(std::string(url));
|
||||
}
|
||||
|
||||
// static
|
||||
gboolean RootWindowGtk::URLEntryButtonPress(GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
RootWindowGtk* self) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Give focus to the GTK window. This is a work-around for bad focus-related
|
||||
// interaction between the root window managed by GTK and the browser managed
|
||||
// by X11.
|
||||
|
@@ -53,6 +53,7 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
// BrowserWindow::Delegate methods.
|
||||
void OnBrowserCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBrowserWindowClosing() OVERRIDE;
|
||||
void OnBrowserWindowDestroyed() OVERRIDE;
|
||||
void OnSetAddress(const std::string& url) OVERRIDE;
|
||||
void OnSetTitle(const std::string& title) OVERRIDE;
|
||||
@@ -64,7 +65,17 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
void OnSetDraggableRegions(
|
||||
const std::vector<CefDraggableRegion>& regions) OVERRIDE;
|
||||
|
||||
void NotifyDestroyedIfDone();
|
||||
void NotifyMoveOrResizeStarted();
|
||||
void NotifySetFocus();
|
||||
void NotifyVisibilityChange(bool show);
|
||||
void NotifyMenuBarHeight(int height);
|
||||
void NotifyContentBounds(int x, int y, int width, int height);
|
||||
void NotifyLoadURL(const std::string& url);
|
||||
void NotifyButtonClicked(int id);
|
||||
void NotifyMenuItem(int id);
|
||||
void NotifyForceClose();
|
||||
void NotifyCloseBrowser();
|
||||
void NotifyDestroyedIfDone(bool window_destroyed, bool browser_destroyed);
|
||||
|
||||
GtkWidget* CreateMenuBar();
|
||||
GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text);
|
||||
@@ -139,10 +150,14 @@ class RootWindowGtk : public RootWindow, public BrowserWindow::Delegate {
|
||||
|
||||
CefRect browser_bounds_;
|
||||
|
||||
bool force_close_;
|
||||
bool window_destroyed_;
|
||||
bool browser_destroyed_;
|
||||
|
||||
// Members only accessed on the UI thread because they're needed for
|
||||
// WindowDelete.
|
||||
bool force_close_;
|
||||
bool is_closing_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(RootWindowGtk);
|
||||
};
|
||||
|
||||
|
@@ -159,6 +159,11 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
|
||||
CefBrowserSettings& settings) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (!temp_window_) {
|
||||
// TempWindow must be created on the UI thread.
|
||||
temp_window_.reset(new TempWindow());
|
||||
}
|
||||
|
||||
MainContext::Get()->PopulateBrowserSettings(&settings);
|
||||
|
||||
scoped_refptr<RootWindow> root_window =
|
||||
@@ -390,8 +395,9 @@ void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) {
|
||||
}
|
||||
|
||||
if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
|
||||
// Quit the main message loop after all windows have closed.
|
||||
MainMessageLoop::Get()->Quit();
|
||||
// All windows have closed. Clean up on the UI thread.
|
||||
CefPostTask(TID_UI, base::Bind(&RootWindowManager::CleanupOnUIThread,
|
||||
base::Unretained(this)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,4 +446,16 @@ void RootWindowManager::CreateExtensionWindow(
|
||||
}
|
||||
}
|
||||
|
||||
void RootWindowManager::CleanupOnUIThread() {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (temp_window_) {
|
||||
// TempWindow must be destroyed on the UI thread.
|
||||
temp_window_.reset(nullptr);
|
||||
}
|
||||
|
||||
// Quit the main message loop.
|
||||
MainMessageLoop::Get()->Quit();
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
@@ -106,6 +106,8 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
const base::Closure& close_callback,
|
||||
bool with_osr) OVERRIDE;
|
||||
|
||||
void CleanupOnUIThread();
|
||||
|
||||
const bool terminate_when_all_windows_closed_;
|
||||
bool request_context_per_browser_;
|
||||
bool request_context_shared_cache_;
|
||||
@@ -124,7 +126,7 @@ class RootWindowManager : public RootWindow::Delegate {
|
||||
CefRefPtr<CefBrowser> active_browser_;
|
||||
|
||||
// Singleton window used as the temporary parent for popup browsers.
|
||||
TempWindow temp_window_;
|
||||
scoped_ptr<TempWindow> temp_window_;
|
||||
|
||||
CefRefPtr<CefRequestContext> shared_request_context_;
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
namespace client {
|
||||
|
||||
// Represents a singleton hidden window that acts as a temporary parent for
|
||||
// popup browsers.
|
||||
// popup browsers. Only accessed on the UI thread.
|
||||
class TempWindowMac {
|
||||
public:
|
||||
// Returns the singleton window handle.
|
||||
@@ -20,6 +20,8 @@ class TempWindowMac {
|
||||
private:
|
||||
// A single instance will be created/owned by RootWindowManager.
|
||||
friend class RootWindowManager;
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<TempWindowMac>;
|
||||
|
||||
TempWindowMac();
|
||||
~TempWindowMac();
|
||||
|
@@ -11,7 +11,7 @@
|
||||
namespace client {
|
||||
|
||||
// Represents a singleton hidden window that acts as a temporary parent for
|
||||
// popup browsers.
|
||||
// popup browsers. Only accessed on the UI thread.
|
||||
class TempWindowWin {
|
||||
public:
|
||||
// Returns the singleton window handle.
|
||||
@@ -20,6 +20,8 @@ class TempWindowWin {
|
||||
private:
|
||||
// A single instance will be created/owned by RootWindowManager.
|
||||
friend class RootWindowManager;
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<TempWindowWin>;
|
||||
|
||||
TempWindowWin();
|
||||
~TempWindowWin();
|
||||
|
@@ -16,6 +16,7 @@ namespace {
|
||||
// Create the temp window.
|
||||
::Window CreateTempWindow() {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
CHECK(xdisplay != 0);
|
||||
::Window parent_xwindow = DefaultRootWindow(xdisplay);
|
||||
|
||||
XSetWindowAttributes swa;
|
||||
@@ -33,6 +34,7 @@ namespace {
|
||||
// Close the temp window.
|
||||
void CloseTempWindow(::Window xwindow) {
|
||||
::Display* xdisplay = cef_get_xdisplay();
|
||||
CHECK(xdisplay != 0);
|
||||
XDestroyWindow(xdisplay, xwindow);
|
||||
}
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
namespace client {
|
||||
|
||||
// Represents a singleton hidden window that acts as a temporary parent for
|
||||
// popup browsers.
|
||||
// popup browsers. Only accessed on the UI thread.
|
||||
class TempWindowX11 {
|
||||
public:
|
||||
// Returns the singleton window handle.
|
||||
@@ -20,6 +20,8 @@ class TempWindowX11 {
|
||||
private:
|
||||
// A single instance will be created/owned by RootWindowManager.
|
||||
friend class RootWindowManager;
|
||||
// Allow deletion via scoped_ptr only.
|
||||
friend struct base::DefaultDeleter<TempWindowX11>;
|
||||
|
||||
TempWindowX11();
|
||||
~TempWindowX11();
|
||||
|
33
tests/cefclient/browser/util_gtk.cc
Normal file
33
tests/cefclient/browser/util_gtk.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2018 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.
|
||||
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
namespace client {
|
||||
|
||||
base::PlatformThreadId ScopedGdkThreadsEnter::locked_thread_ =
|
||||
kInvalidPlatformThreadId;
|
||||
|
||||
ScopedGdkThreadsEnter::ScopedGdkThreadsEnter() {
|
||||
// The GDK lock is not reentrant, so don't try to lock again if the current
|
||||
// thread already holds it.
|
||||
base::PlatformThreadId current_thread = base::PlatformThread::CurrentId();
|
||||
take_lock_ = current_thread != locked_thread_;
|
||||
|
||||
if (take_lock_) {
|
||||
gdk_threads_enter();
|
||||
locked_thread_ = current_thread;
|
||||
}
|
||||
}
|
||||
|
||||
ScopedGdkThreadsEnter::~ScopedGdkThreadsEnter() {
|
||||
if (take_lock_) {
|
||||
locked_thread_ = kInvalidPlatformThreadId;
|
||||
gdk_threads_leave();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace client
|
41
tests/cefclient/browser/util_gtk.h
Normal file
41
tests/cefclient/browser/util_gtk.h
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2018 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_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_macros.h"
|
||||
#include "include/base/cef_platform_thread.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
// Scoped helper that manages the global GDK lock by calling gdk_threads_enter()
|
||||
// and gdk_threads_leave(). The lock is not reentrant so this helper implements
|
||||
// additional checking to avoid deadlocks.
|
||||
//
|
||||
// When using GTK in multi-threaded mode you must do the following:
|
||||
// 1. Call gdk_threads_init() before making any other GTK/GDK/GLib calls.
|
||||
// 2. Acquire the global lock before making any GTK/GDK calls, and release the
|
||||
// lock afterwards. This should only be done with callbacks that do not
|
||||
// originate from GTK signals (because those callbacks already hold the
|
||||
// lock).
|
||||
//
|
||||
// See https://www.geany.org/manual/gtk/gtk-faq/x482.html for more information.
|
||||
class ScopedGdkThreadsEnter {
|
||||
public:
|
||||
ScopedGdkThreadsEnter();
|
||||
~ScopedGdkThreadsEnter();
|
||||
|
||||
private:
|
||||
bool take_lock_;
|
||||
|
||||
static base::PlatformThreadId locked_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedGdkThreadsEnter);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_UTIL_GTK_H_
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/util_gtk.h"
|
||||
#include "tests/shared/browser/main_message_loop.h"
|
||||
|
||||
namespace client {
|
||||
@@ -33,17 +34,13 @@ bool IsMaximized(GtkWindow* window) {
|
||||
return (state & GDK_WINDOW_STATE_MAXIMIZED) ? true : false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WindowTestRunnerGtk::WindowTestRunnerGtk() {}
|
||||
|
||||
void WindowTestRunnerGtk::SetPos(CefRefPtr<CefBrowser> browser,
|
||||
void SetPosImpl(CefRefPtr<CefBrowser> browser,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
REQUIRE_MAIN_THREAD();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
@@ -65,15 +62,15 @@ void WindowTestRunnerGtk::SetPos(CefRefPtr<CefBrowser> browser,
|
||||
// Make sure the window is inside the display.
|
||||
CefRect display_rect(rect.x, rect.y, rect.width, rect.height);
|
||||
CefRect window_rect(x, y, width, height);
|
||||
ModifyBounds(display_rect, window_rect);
|
||||
WindowTestRunner::ModifyBounds(display_rect, window_rect);
|
||||
|
||||
gdk_window_move_resize(gdk_window, window_rect.x, window_rect.y,
|
||||
window_rect.width, window_rect.height);
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
void MinimizeImpl(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
@@ -86,9 +83,9 @@ void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||
gtk_window_iconify(window);
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
void MaximizeImpl(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
@@ -96,9 +93,9 @@ void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||
gtk_window_maximize(window);
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
void RestoreImpl(CefRefPtr<CefBrowser> browser) {
|
||||
REQUIRE_MAIN_THREAD();
|
||||
ScopedGdkThreadsEnter scoped_gdk_threads;
|
||||
|
||||
GtkWindow* window = GetWindow(browser);
|
||||
if (!window)
|
||||
@@ -109,5 +106,29 @@ void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
|
||||
gtk_window_present(window);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WindowTestRunnerGtk::WindowTestRunnerGtk() {}
|
||||
|
||||
void WindowTestRunnerGtk::SetPos(CefRefPtr<CefBrowser> browser,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height) {
|
||||
MAIN_POST_CLOSURE(base::Bind(SetPosImpl, browser, x, y, width, height));
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Minimize(CefRefPtr<CefBrowser> browser) {
|
||||
MAIN_POST_CLOSURE(base::Bind(MinimizeImpl, browser));
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Maximize(CefRefPtr<CefBrowser> browser) {
|
||||
MAIN_POST_CLOSURE(base::Bind(MaximizeImpl, browser));
|
||||
}
|
||||
|
||||
void WindowTestRunnerGtk::Restore(CefRefPtr<CefBrowser> browser) {
|
||||
MAIN_POST_CLOSURE(base::Bind(RestoreImpl, browser));
|
||||
}
|
||||
|
||||
} // namespace window_test
|
||||
} // namespace client
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include "include/cef_command_line.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/main_context_impl.h"
|
||||
#include "tests/cefclient/browser/main_message_loop_multithreaded_gtk.h"
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
#include "tests/shared/browser/client_app_browser.h"
|
||||
#include "tests/shared/browser/main_message_loop_external_pump.h"
|
||||
@@ -92,7 +93,9 @@ int RunMain(int argc, char* argv[]) {
|
||||
|
||||
// Create the main message loop object.
|
||||
scoped_ptr<MainMessageLoop> message_loop;
|
||||
if (settings.external_message_pump)
|
||||
if (settings.multi_threaded_message_loop)
|
||||
message_loop.reset(new MainMessageLoopMultithreadedGtk);
|
||||
else if (settings.external_message_pump)
|
||||
message_loop = MainMessageLoopExternalPump::Create();
|
||||
else
|
||||
message_loop.reset(new MainMessageLoopStd);
|
||||
|
@@ -318,6 +318,24 @@ PERF_TEST_FUNC(V8ObjectGetValueWithAccessor) {
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ArrayBufferCreate) {
|
||||
class ReleaseCallback : public CefV8ArrayBufferReleaseCallback {
|
||||
public:
|
||||
void ReleaseBuffer(void* buffer) override { std::free(buffer); }
|
||||
IMPLEMENT_REFCOUNTING(ReleaseCallback);
|
||||
};
|
||||
|
||||
size_t len = 1;
|
||||
size_t byte_len = len * sizeof(float);
|
||||
CefRefPtr<CefV8ArrayBufferReleaseCallback> callback = new ReleaseCallback();
|
||||
|
||||
PERF_ITERATIONS_START()
|
||||
float* buffer = (float*)std::malloc(byte_len);
|
||||
CefRefPtr<CefV8Value> ret =
|
||||
CefV8Value::CreateArrayBuffer(buffer, byte_len, callback);
|
||||
PERF_ITERATIONS_END()
|
||||
}
|
||||
|
||||
PERF_TEST_FUNC(V8ContextEnterExit) {
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
|
||||
@@ -363,6 +381,7 @@ const PerfTestEntry kPerfTests[] = {
|
||||
PERF_TEST_ENTRY(V8ObjectGetValue),
|
||||
PERF_TEST_ENTRY(V8ObjectSetValueWithAccessor),
|
||||
PERF_TEST_ENTRY(V8ObjectGetValueWithAccessor),
|
||||
PERF_TEST_ENTRY(V8ArrayBufferCreate),
|
||||
PERF_TEST_ENTRY(V8ContextEnterExit),
|
||||
PERF_TEST_ENTRY(V8ContextEval),
|
||||
};
|
||||
|
@@ -200,8 +200,6 @@ class AccessibilityTestHandler : public TestHandler,
|
||||
EXPECT_EQ(VTYPE_LIST, value->GetType());
|
||||
CefRefPtr<CefListValue> list = value->GetList();
|
||||
EXPECT_TRUE(list.get());
|
||||
// Always empty events after https://crrev.com/c101cb728a.
|
||||
EXPECT_EQ(0U, list->GetSize());
|
||||
|
||||
got_accessibility_location_change_.yes();
|
||||
}
|
||||
|
@@ -119,7 +119,7 @@ int CefTestSuite::Run() {
|
||||
}
|
||||
|
||||
void CefTestSuite::GetSettings(CefSettings& settings) const {
|
||||
#if defined(OS_WIN)
|
||||
#if (defined(OS_WIN) || defined(OS_LINUX))
|
||||
settings.multi_threaded_message_loop =
|
||||
command_line_->HasSwitch(client::switches::kMultiThreadedMessageLoop);
|
||||
#endif
|
||||
|
@@ -14,13 +14,17 @@ cefclient.app/
|
||||
Frameworks/
|
||||
Chromium Embedded Framework.framework/
|
||||
Chromium Embedded Framework <= main application library
|
||||
Libraries/
|
||||
libEGL.dylib <= angle support libraries
|
||||
libGLESv2.dylib <=^
|
||||
libswiftshader_libEGL.dylib <= swiftshader support libraries
|
||||
libswiftshader_libGLESv2.dylib <=^
|
||||
Resources/
|
||||
cef.pak <= non-localized resources and strings
|
||||
cef_100_percent.pak <====^
|
||||
cef_200_percent.pak <====^
|
||||
cef_extensions.pak <=====^
|
||||
devtools_resources.pak <=^
|
||||
crash_inspector, crash_report_sender <= breakpad support
|
||||
icudtl.dat <= unicode support
|
||||
natives_blob.bin, snapshot_blob.bin, v8_context_snapshot.bin <= V8 initial snapshot
|
||||
en.lproj/, ... <= locale-specific resources and strings
|
||||
@@ -99,8 +103,14 @@ run but any related functionality may become broken or disabled.
|
||||
This file contains non-localized resources required for Chrome Developer
|
||||
Tools. Without this file Chrome Developer Tools will not function.
|
||||
|
||||
* Breakpad support.
|
||||
* Chromium Embedded Framework.framework/Resources/crash_inspector
|
||||
* Chromium Embedded Framework.framework/Resources/crash_report_sender
|
||||
* Chromium Embedded Framework.framework/Resources/Info.plist
|
||||
Without these files breakpad support (crash reporting) will not function.
|
||||
* Angle support.
|
||||
* Chromium Embedded Framework.framework/Libraries/libEGL.dylib
|
||||
* Chromium Embedded Framework.framework/Libraries/libGLESv2.dylib
|
||||
Without these files HTML5 accelerated content like 2D canvas, 3D CSS and WebGL
|
||||
will not function.
|
||||
|
||||
* SwiftShader support.
|
||||
* Chromium Embedded Framework.framework/Libraries/libswiftshader_libEGL.dylib
|
||||
* Chromium Embedded Framework.framework/Libraries/libswiftshader_libGLESv2.dylib
|
||||
Without these files WebGL will not function in software-only mode when the GPU
|
||||
is not available or disabled.
|
||||
|
Reference in New Issue
Block a user