diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 7a1b6ea29..a95591105 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -34,7 +34,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=fcc19532b6143e9c445fcde9947260b1c93a5e68$ +// $hash=3a0c73e396fa3857e28d388def4fbd3029f22572$ // #ifndef CEF_INCLUDE_API_HASH_H_ @@ -47,13 +47,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "114e74f2c52d90fbb3fe6b3855dba9e544e40e85" +#define CEF_API_HASH_UNIVERSAL "270f0270e88d272207bd83c60e36ceb45f4b690c" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "25d0b5c8337691e2bcc21148686e4eacbe1255a6" +#define CEF_API_HASH_PLATFORM "66d5f7568c90b1fcf60c4b8278b2465e94044426" #elif defined(OS_MACOSX) -#define CEF_API_HASH_PLATFORM "905d65b97689874873222e99869c8c5a361bbdb7" +#define CEF_API_HASH_PLATFORM "2eaac3385943011ba69f8c02ff81fcc779fa1d39" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "ef345d85855d8d5c34de2fb26d25397c5e0e3534" +#define CEF_API_HASH_PLATFORM "32502dcfde9333af005bae482dec534ce2e26d67" #endif #ifdef __cplusplus diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 11df1b34f..218dcb8e8 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -219,15 +219,27 @@ typedef struct _cef_settings_t { int command_line_args_disabled; /// - // The location where cache data will be stored on disk. If empty then - // browsers will be created in "incognito mode" where in-memory caches are - // used for storage and no data is persisted to disk. HTML5 databases such as - // localStorage will only persist across sessions if a cache path is - // specified. Can be overridden for individual CefRequestContext instances via - // the CefRequestContextSettings.cache_path value. + // The location where data for the global browser cache will be stored on + // disk. In non-empty this must be either equal to or a child directory of + // CefSettings.root_cache_path. If empty then browsers will be created in + // "incognito mode" where in-memory caches are used for storage and no data is + // persisted to disk. HTML5 databases such as localStorage will only persist + // across sessions if a cache path is specified. Can be overridden for + // individual CefRequestContext instances via the + // CefRequestContextSettings.cache_path value. /// cef_string_t cache_path; + /// + // The root directory that all CefSettings.cache_path and + // CefRequestContextSettings.cache_path values must have in common. If this + // value is empty and CefSettings.cache_path is non-empty then this value will + // default to the CefSettings.cache_path value. Failure to set this value + // correctly may result in the sandbox blocking read/write access to the + // cache_path directory. + /// + cef_string_t root_cache_path; + /// // The location where user data such as spell checking dictionary files will // be stored on disk. If empty then the default platform-specific user data @@ -413,12 +425,14 @@ typedef struct _cef_request_context_settings_t { size_t size; /// - // The location where cache data will be stored on disk. If empty then - // browsers will be created in "incognito mode" where in-memory caches are - // used for storage and no data is persisted to disk. HTML5 databases such as - // localStorage will only persist across sessions if a cache path is - // specified. To share the global browser cache and related configuration set - // this value to match the CefSettings.cache_path value. + // The location where cache data for this request context will be stored on + // disk. If non-empty this must be either equal to or a child directory of + // CefSettings.root_cache_path. If empty then browsers will be created in + // "incognito mode" where in-memory caches are used for storage and no data is + // persisted to disk. HTML5 databases such as localStorage will only persist + // across sessions if a cache path is specified. To share the global browser + // cache and related configuration set this value to match the + // CefSettings.cache_path value. /// cef_string_t cache_path; diff --git a/libcef/browser/browser_context.cc b/libcef/browser/browser_context.cc index c2e84f67a..2fff3ce52 100644 --- a/libcef/browser/browser_context.cc +++ b/libcef/browser/browser_context.cc @@ -24,7 +24,6 @@ #include "base/lazy_instance.h" #include "base/logging.h" #include "base/strings/string_util.h" -#include "base/threading/thread_restrictions.h" #include "chrome/browser/font_family_cache.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h" @@ -260,16 +259,13 @@ CefBrowserContext::~CefBrowserContext() { } void CefBrowserContext::Initialize() { + CefContext* context = CefContext::Get(); + cache_path_ = base::FilePath(CefString(&settings_.cache_path)); - if (!cache_path_.empty()) { - base::ThreadRestrictions::ScopedAllowIO allow_io; - if (!base::DirectoryExists(cache_path_) && - !base::CreateDirectory(cache_path_)) { - LOG(ERROR) << "The cache_path directory could not be created: " - << cache_path_.value(); - cache_path_ = base::FilePath(); - CefString(&settings_.cache_path).clear(); - } + if (!context->ValidateCachePath(cache_path_)) { + // Reset to in-memory storage. + CefString(&settings_.cache_path).clear(); + cache_path_ = base::FilePath(); } if (!cache_path_.empty()) @@ -278,7 +274,7 @@ void CefBrowserContext::Initialize() { if (settings_.accept_language_list.length == 0) { // Use the global language list setting. CefString(&settings_.accept_language_list) = - CefString(&CefContext::Get()->settings().accept_language_list); + CefString(&context->settings().accept_language_list); } // Initialize the PrefService object. diff --git a/libcef/browser/chrome_browser_process_stub.cc b/libcef/browser/chrome_browser_process_stub.cc index fafaa7c1c..e292ba798 100644 --- a/libcef/browser/chrome_browser_process_stub.cc +++ b/libcef/browser/chrome_browser_process_stub.cc @@ -7,6 +7,7 @@ #include "libcef/browser/browser_context.h" #include "libcef/browser/chrome_profile_manager_stub.h" +#include "libcef/browser/context.h" #include "libcef/browser/prefs/browser_prefs.h" #include "libcef/browser/thread_util.h" #include "libcef/common/cef_switches.h" @@ -39,11 +40,13 @@ void ChromeBrowserProcessStub::Initialize() { DCHECK(!context_initialized_); DCHECK(!shutdown_); + const CefSettings& settings = CefContext::Get()->settings(); + const base::FilePath& cache_path = + base::FilePath(CefString(&settings.cache_path)); + // Used for very early NetworkService initialization. - // TODO(cef): These preferences could be persisted in the DIR_USER_DATA - // directory. - local_state_ = - browser_prefs::CreatePrefService(nullptr, base::FilePath(), false); + local_state_ = browser_prefs::CreatePrefService( + nullptr, cache_path, !!settings.persist_user_preferences); initialized_ = true; } diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index fb23da1e1..0b8be4689 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -49,6 +49,7 @@ #include "base/json/json_reader.h" #include "base/path_service.h" #include "base/stl_util.h" +#include "base/threading/thread_restrictions.h" #include "cef/grit/cef_resources.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_service.h" @@ -57,7 +58,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_paths_internal.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/constants.mojom.h" #include "chrome/grit/browser_resources.h" @@ -1200,6 +1200,11 @@ void CefContentBrowserClient::OnNetworkServiceCreated( DCHECK(local_state); if (!SystemNetworkContextManager::GetInstance()) { + // TODO(network): This triggers creation of ChromeBrowserPolicyConnector via + // ChromeBrowserProcessStub::policy_service() which loads some system DLLs + // on Windows. Determine the correct initialization timing to avoid the need + // for ScopedAllowIO here. + base::ThreadRestrictions::ScopedAllowIO allow_io; SystemNetworkContextManager::CreateInstance(local_state); } // Need to set up global NetworkService state before anything else uses it. @@ -1215,24 +1220,26 @@ network::mojom::NetworkContextPtr CefContentBrowserClient::CreateNetworkContext( return profile->CreateNetworkContext(in_memory, relative_partition_path); } +// The sandbox may block read/write access from the NetworkService to +// directories that are not returned by this method. std::vector CefContentBrowserClient::GetNetworkContextsParentDirectory() { - base::FilePath user_data_dir; - base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); - DCHECK(!user_data_dir.empty()); + base::FilePath user_data_path; + base::PathService::Get(chrome::DIR_USER_DATA, &user_data_path); + DCHECK(!user_data_path.empty()); - // TODO(cef): Do we really want to create a cache directory underneath - // DIR_USER_DATA? - base::FilePath cache_dir; - chrome::GetUserCacheDirectory(user_data_dir, &cache_dir); - DCHECK(!cache_dir.empty()); + // The CefContext::ValidateCachePath method enforces the requirement that all + // cache_path values be either equal to or a child of root_cache_path. + const base::FilePath& root_cache_path = + base::FilePath(CefString(&CefContext::Get()->settings().root_cache_path)); - // On some platforms, the cache is a child of the user_data_dir so only - // return the one path. - if (user_data_dir.IsParent(cache_dir)) - return {user_data_dir}; + // root_cache_path may sometimes be empty or a child of user_data_path, so + // only return the one path in that case. + if (root_cache_path.empty() || user_data_path.IsParent(root_cache_path)) { + return {user_data_path}; + } - return {user_data_dir, cache_dir}; + return {user_data_path, root_cache_path}; } bool CefContentBrowserClient::HandleExternalProtocol( diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 4441ff67d..56aa7ab9c 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -22,6 +22,7 @@ #include "base/files/file_util.h" #include "base/run_loop.h" #include "base/synchronization/waitable_event.h" +#include "base/threading/thread_restrictions.h" #include "components/network_session_configurator/common/network_switches.h" #include "content/app/content_service_manager_main_delegate.h" #include "content/browser/startup_helper.h" @@ -370,6 +371,18 @@ bool CefContext::Initialize(const CefMainArgs& args, SignalChromeElf(); #endif + base::FilePath cache_path = base::FilePath(CefString(&settings_.cache_path)); + if (!ValidateCachePath(cache_path)) { + // Reset to in-memory storage. + CefString(&settings_.cache_path).clear(); + cache_path = base::FilePath(); + } + const base::FilePath& root_cache_path = + base::FilePath(CefString(&settings_.root_cache_path)); + if (root_cache_path.empty() && !cache_path.empty()) { + CefString(&settings_.root_cache_path) = CefString(&settings_.cache_path); + } + main_delegate_.reset(new CefMainDelegate(application)); browser_info_manager_.reset(new CefBrowserInfoManager); @@ -533,6 +546,31 @@ void CefContext::PopulateRequestContextSettings( CefString(&settings_.accept_language_list); } +bool CefContext::ValidateCachePath(const base::FilePath& cache_path) { + if (cache_path.empty()) + return true; + + const base::FilePath& root_cache_path = + base::FilePath(CefString(&settings_.root_cache_path)); + if (!root_cache_path.empty() && root_cache_path != cache_path && + !root_cache_path.IsParent(cache_path)) { + LOG(ERROR) << "The cache_path directory (" << cache_path.value() + << ") is not a child of the root_cache_path directory (" + << root_cache_path.value() << ")"; + return false; + } + + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (!base::DirectoryExists(cache_path) && + !base::CreateDirectory(cache_path)) { + LOG(ERROR) << "The cache_path directory (" << cache_path.value() + << ") could not be created."; + return false; + } + + return true; +} + void CefContext::OnContextInitialized() { CEF_REQUIRE_UIT(); diff --git a/libcef/browser/context.h b/libcef/browser/context.h index d83f79122..21a656896 100644 --- a/libcef/browser/context.h +++ b/libcef/browser/context.h @@ -73,10 +73,13 @@ class CefContext { CefTraceSubscriber* GetTraceSubscriber(); - // Populate the request context settings based on CefSettings and command- - // line flags. + // Populate request context settings for the global system context based on + // CefSettings and command-line flags. void PopulateRequestContextSettings(CefRequestContextSettings* settings); + // Verify that |cache_path| is valid and create it if necessary. + bool ValidateCachePath(const base::FilePath& cache_path); + private: void OnContextInitialized(); diff --git a/libcef/browser/prefs/browser_prefs.cc b/libcef/browser/prefs/browser_prefs.cc index 0217137f5..63e81d590 100644 --- a/libcef/browser/prefs/browser_prefs.cc +++ b/libcef/browser/prefs/browser_prefs.cc @@ -193,6 +193,12 @@ std::unique_ptr CreatePrefService(Profile* profile, // Based on ProfileImpl::RegisterProfilePrefs. registry->RegisterBooleanPref(prefs::kPrintingEnabled, true); + // Cache preferences. + // Based on ProfileImpl::RegisterProfilePrefs. + registry->RegisterFilePathPref(prefs::kDiskCacheDir, cache_path); + registry->RegisterIntegerPref(prefs::kDiskCacheSize, 0); + registry->RegisterIntegerPref(prefs::kMediaCacheSize, 0); + // Spell checking preferences. // Modify defaults from SpellcheckServiceFactory::RegisterProfilePrefs. std::string spellcheck_lang = diff --git a/tests/cefclient/browser/dialog_test.cc b/tests/cefclient/browser/dialog_test.cc index 5860d4421..e911c957b 100644 --- a/tests/cefclient/browser/dialog_test.cc +++ b/tests/cefclient/browser/dialog_test.cc @@ -9,6 +9,7 @@ #include "include/cef_browser.h" #include "include/wrapper/cef_helpers.h" #include "tests/cefclient/browser/test_runner.h" +#include "tests/shared/browser/file_util.h" namespace client { namespace dialog_test { @@ -21,12 +22,6 @@ const char kFileOpenMultipleMessageName[] = "DialogTest.FileOpenMultiple"; const char kFileOpenFolderMessageName[] = "DialogTest.FileOpenFolder"; const char kFileSaveMessageName[] = "DialogTest.FileSave"; -#if defined(OS_WIN) -#define PATH_SEP '\\' -#else -#define PATH_SEP '/' -#endif - // Store persistent dialog state information. class DialogState : public base::RefCountedThreadSafe { public: @@ -62,10 +57,10 @@ class DialogCallback : public CefRunFileDialogCallback { dialog_state_->last_file_ = file_paths[0]; if (dialog_state_->mode_ == FILE_DIALOG_OPEN_FOLDER) { std::string last_file = dialog_state_->last_file_; - if (last_file[last_file.length() - 1] != PATH_SEP) { + if (last_file[last_file.length() - 1] != file_util::kPathSep) { // Add a trailing slash so we know it's a directory. Otherwise, file // dialogs will think the last path component is a file name. - last_file += PATH_SEP; + last_file += file_util::kPathSep; dialog_state_->last_file_ = last_file; } } diff --git a/tests/cefclient/browser/root_window_manager.cc b/tests/cefclient/browser/root_window_manager.cc index 9b1033453..cf03ab44e 100644 --- a/tests/cefclient/browser/root_window_manager.cc +++ b/tests/cefclient/browser/root_window_manager.cc @@ -12,6 +12,7 @@ #include "tests/cefclient/browser/main_context.h" #include "tests/cefclient/browser/test_runner.h" #include "tests/shared/browser/extension_util.h" +#include "tests/shared/browser/file_util.h" #include "tests/shared/browser/resource_util.h" #include "tests/shared/common/client_switches.h" @@ -335,7 +336,7 @@ CefRefPtr RootWindowManager::GetRequestContext( // isolated context objects. std::stringstream ss; ss << command_line->GetSwitchValue(switches::kCachePath).ToString() - << time(NULL); + << file_util::kPathSep << time(NULL); CefString(&settings.cache_path) = ss.str(); } }