Enforce cache_path requirements for NetworkService (see issue #2622).
This change adds a new CefSettings.root_cache_path value that must be either equal to or a parent directory of all CefSettings.cache_path and CefRequestContextSettings.cache_path values. The sandbox may block read/write access from the NetworkService to directories that do not meet this requirement. To test: Run cefclient with a combination of the following flags: --cache-path=c:\temp\cache Cache data should be persisted to the specified directory. --request-context-per-browser A separate numbered cache directory should be created underneath the cache-path directory for each new browser instance. --enable-network-service --disable-extensions Same tests, but with NetworkService enabled. Known issues: - When NetworkService is enabled a C:\temp\cache\cache\Cache directory is created (should be C:\temp\cache\Cache).
This commit is contained in:
parent
9b43d265c3
commit
b65f336f81
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<base::FilePath>
|
||||
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(
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -193,6 +193,12 @@ std::unique_ptr<PrefService> 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 =
|
||||
|
|
|
@ -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<DialogState> {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<CefRequestContext> 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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue