summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 19:23:09 +0000
committerkinuko@chromium.org <kinuko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-27 19:23:09 +0000
commitd34c5f86806cc82c667ac09339c25f5f64fdc1db (patch)
treee60c9bc8346d9fd9742a649a37d0c604a3c0b672
parent01ce7c91bc987c620be3620836f2151ecdb8acff (diff)
downloadchromium_src-d34c5f86806cc82c667ac09339c25f5f64fdc1db.zip
chromium_src-d34c5f86806cc82c667ac09339c25f5f64fdc1db.tar.gz
chromium_src-d34c5f86806cc82c667ac09339c25f5f64fdc1db.tar.bz2
Add a helper class that keeps per-profile information for FileSystem API
BUG=32277 TEST=FileSystemHostContextTest Review URL: http://codereview.chromium.org/3028033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57715 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/file_system/file_system_dispatcher_host.cc40
-rw-r--r--chrome/browser/file_system/file_system_dispatcher_host.h4
-rw-r--r--chrome/browser/file_system/file_system_host_context.cc65
-rw-r--r--chrome/browser/file_system/file_system_host_context.h51
-rw-r--r--chrome/browser/file_system/file_system_host_context_unittest.cc101
-rw-r--r--chrome/browser/profile.cc12
-rw-r--r--chrome/browser/profile.h4
-rw-r--r--chrome/browser/profile_impl.cc9
-rw-r--r--chrome/browser/profile_impl.h2
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc8
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/test/testing_profile.h1
13 files changed, 292 insertions, 8 deletions
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.cc b/chrome/browser/file_system/file_system_dispatcher_host.cc
index 3e23695..d876808 100644
--- a/chrome/browser/file_system/file_system_dispatcher_host.cc
+++ b/chrome/browser/file_system/file_system_dispatcher_host.cc
@@ -8,19 +8,23 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
#include "chrome/browser/host_content_settings_map.h"
#include "chrome/browser/renderer_host/browser_render_process_host.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/render_messages_params.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileError.h"
+#include "webkit/glue/webkit_glue.h"
FileSystemDispatcherHost::FileSystemDispatcherHost(
IPC::Message::Sender* sender,
+ FileSystemHostContext* file_system_host_context,
HostContentSettingsMap* host_content_settings_map)
: message_sender_(sender),
process_handle_(0),
shutdown_(false),
+ context_(file_system_host_context),
host_content_settings_map_(host_content_settings_map) {
DCHECK(message_sender_);
}
@@ -54,20 +58,46 @@ bool FileSystemDispatcherHost::OnMessageReceived(
void FileSystemDispatcherHost::OnOpenFileSystem(
const ViewHostMsg_OpenFileSystemRequest_Params& params) {
- string16 name;
- string16 root_path;
- // TODO(kinuko): not implemented yet.
+ // TODO(kinuko): hook up ContentSettings cookies type checks.
+
+ FilePath root_path;
+ std::string name;
+
+ if (!context_->GetFileSystemRootPath(params.origin_url,
+ params.type,
+ &root_path,
+ &name)) {
+ Send(new ViewMsg_OpenFileSystemRequest_Complete(
+ params.routing_id,
+ params.request_id,
+ false,
+ string16(),
+ string16()));
+ return;
+ }
+
+ // TODO(kinuko): creates the root directory and if it succeeds.
Send(new ViewMsg_OpenFileSystemRequest_Complete(
params.routing_id,
params.request_id,
- false,
- name, root_path));
+ true,
+ UTF8ToUTF16(name),
+ webkit_glue::FilePathToWebString(root_path)));
}
void FileSystemDispatcherHost::OnMove(
int request_id, const string16& src_path, const string16& dest_path) {
+ if (!context_->CheckValidFileSystemPath(
+ webkit_glue::WebStringToFilePath(src_path)) ||
+ !context_->CheckValidFileSystemPath(
+ webkit_glue::WebStringToFilePath(dest_path))) {
+ Send(new ViewMsg_FileSystem_Failed(
+ request_id, WebKit::WebFileErrorSecurity));
+ return;
+ }
+
// TODO(kinuko): not implemented yet.
Send(new ViewMsg_FileSystem_Failed(
diff --git a/chrome/browser/file_system/file_system_dispatcher_host.h b/chrome/browser/file_system/file_system_dispatcher_host.h
index f756ebe..0f8b63a 100644
--- a/chrome/browser/file_system/file_system_dispatcher_host.h
+++ b/chrome/browser/file_system/file_system_dispatcher_host.h
@@ -11,6 +11,7 @@
#include "base/ref_counted.h"
#include "chrome/common/render_messages.h"
+class FileSystemHostContext;
class HostContentSettingsMap;
class Receiver;
class ResourceMessageFilter;
@@ -19,6 +20,7 @@ class FileSystemDispatcherHost
: public base::RefCountedThreadSafe<FileSystemDispatcherHost> {
public:
FileSystemDispatcherHost(IPC::Message::Sender* sender,
+ FileSystemHostContext* file_system_host_context,
HostContentSettingsMap* host_content_settings_map);
void Init(base::ProcessHandle process_handle);
void Shutdown();
@@ -46,6 +48,8 @@ class FileSystemDispatcherHost
bool shutdown_;
+ scoped_refptr<FileSystemHostContext> context_;
+
// Used to look up permissions.
scoped_refptr<HostContentSettingsMap> host_content_settings_map_;
};
diff --git a/chrome/browser/file_system/file_system_host_context.cc b/chrome/browser/file_system/file_system_host_context.cc
new file mode 100644
index 0000000..c14dfe1
--- /dev/null
+++ b/chrome/browser/file_system/file_system_host_context.cc
@@ -0,0 +1,65 @@
+// Copyright (c) 2010 The Chromium 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 "chrome/browser/file_system/file_system_host_context.h"
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/profile.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
+
+const FilePath::CharType FileSystemHostContext::kFileSystemDirectory[] =
+ FILE_PATH_LITERAL("FileSystem");
+
+const char FileSystemHostContext::kPersistentName[] = "Persistent";
+const char FileSystemHostContext::kTemporaryName[] = "Temporary";
+
+FileSystemHostContext::FileSystemHostContext(
+ const FilePath& data_path, bool is_incognito)
+ : base_path_(data_path.Append(kFileSystemDirectory)),
+ is_incognito_(is_incognito) {
+}
+
+bool FileSystemHostContext::GetFileSystemRootPath(
+ const GURL& origin_url, WebKit::WebFileSystem::Type type,
+ FilePath* root_path, std::string* name) const {
+ // TODO(kinuko): should return an isolated temporary file system space.
+ if (is_incognito_)
+ return false;
+ std::string storage_identifier = GetStorageIdentifierFromURL(origin_url);
+ switch (type) {
+ case WebKit::WebFileSystem::TypeTemporary:
+ if (root_path)
+ *root_path = base_path_.AppendASCII(storage_identifier)
+ .AppendASCII(kTemporaryName);
+ if (name)
+ *name = storage_identifier + ":" + kTemporaryName;
+ return true;
+ case WebKit::WebFileSystem::TypePersistent:
+ if (root_path)
+ *root_path = base_path_.AppendASCII(storage_identifier)
+ .AppendASCII(kPersistentName);
+ if (name)
+ *name = storage_identifier + ":" + kPersistentName;
+ return true;
+ }
+ LOG(WARNING) << "Unknown filesystem type is requested:" << type;
+ return false;
+}
+
+bool FileSystemHostContext::CheckValidFileSystemPath(
+ const FilePath& path) const {
+ // Any paths that includes parent references are considered invalid.
+ return !path.ReferencesParent() && base_path_.IsParent(path);
+}
+
+std::string FileSystemHostContext::GetStorageIdentifierFromURL(
+ const GURL& url) {
+ WebKit::WebSecurityOrigin web_security_origin =
+ WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
+ return web_security_origin.databaseIdentifier().utf8();
+}
diff --git a/chrome/browser/file_system/file_system_host_context.h b/chrome/browser/file_system/file_system_host_context.h
new file mode 100644
index 0000000..592ccd6
--- /dev/null
+++ b/chrome/browser/file_system/file_system_host_context.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2010 The Chromium 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 CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_
+#define CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_
+
+#include "base/file_path.h"
+#include "base/ref_counted.h"
+#include "base/scoped_ptr.h"
+#include "googleurl/src/gurl.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
+
+// This is owned by profile and shared by all the FileSystemDispatcherHost
+// that shared by the same profile.
+class FileSystemHostContext
+ : public base::RefCountedThreadSafe<FileSystemHostContext> {
+ public:
+ FileSystemHostContext(const FilePath& data_path, bool is_incognito);
+ const FilePath& base_path() const { return base_path_; }
+ bool is_incognito() const { return is_incognito_; }
+
+ // Returns the root path and name for the file system specified by given
+ // |origin_url| and |type|. Returns true if the file system is available
+ // for the profile and |root_path| and |name| are filled successfully.
+ bool GetFileSystemRootPath(
+ const GURL& origin_url,
+ WebKit::WebFileSystem::Type type,
+ FilePath* root_path,
+ std::string* name) const;
+
+ // Check if the given |path| is in the FileSystem base directory.
+ bool CheckValidFileSystemPath(const FilePath& path) const;
+
+ // Returns the storage identifier string for the given |url|.
+ static std::string GetStorageIdentifierFromURL(const GURL& url);
+
+ // The FileSystem directory name.
+ static const FilePath::CharType kFileSystemDirectory[];
+
+ static const char kPersistentName[];
+ static const char kTemporaryName[];
+
+ private:
+ const FilePath base_path_;
+ const bool is_incognito_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FileSystemHostContext);
+};
+
+#endif // CHROME_BROWSER_FILE_SYSTEM_FILE_SYSTEM_HOST_CONTEXT_H_
diff --git a/chrome/browser/file_system/file_system_host_context_unittest.cc b/chrome/browser/file_system/file_system_host_context_unittest.cc
new file mode 100644
index 0000000..6bcda9d
--- /dev/null
+++ b/chrome/browser/file_system/file_system_host_context_unittest.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 The Chromium 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 "base/basictypes.h"
+#include "base/file_path.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
+
+namespace {
+
+// PS stands for path separator.
+#if defined(FILE_PATH_USES_WIN_SEPARATORS)
+#define PS "\\"
+#else
+#define PS "/"
+#endif
+
+const FilePath::CharType kTestDataPath[] = FILE_PATH_LITERAL(
+ "//tmp/TestingProfilePath");
+
+const struct RootPathTest {
+ WebKit::WebFileSystem::Type type;
+ bool off_the_record;
+ const char* origin_url;
+ bool expect_root_path;
+ const char* expected_path;
+} kRootPathTestCases[] = {
+ { WebKit::WebFileSystem::TypeTemporary, false, "http://host:1/",
+ true, "FileSystem" PS "http_host_1" PS "Temporary" },
+ { WebKit::WebFileSystem::TypePersistent, false, "http://host:2/",
+ true, "FileSystem" PS "http_host_2" PS "Persistent" },
+ { WebKit::WebFileSystem::TypeTemporary, true, "http://host:3/",
+ false, "" },
+ { WebKit::WebFileSystem::TypePersistent, true, "http://host:4/",
+ false, "" },
+};
+
+const struct CheckValidPathTest {
+ FilePath::StringType path;
+ bool expected_valid;
+} kCheckValidPathTestCases[] = {
+ { FILE_PATH_LITERAL("//tmp/foo.txt"), false, },
+ { FILE_PATH_LITERAL("//etc/hosts"), false, },
+ { FILE_PATH_LITERAL("foo.txt"), true, },
+ { FILE_PATH_LITERAL("a/b/c"), true, },
+ // Any paths that includes parent references are considered invalid.
+ { FILE_PATH_LITERAL(".."), false, },
+ { FILE_PATH_LITERAL("tmp/.."), false, },
+ { FILE_PATH_LITERAL("a/b/../c/.."), false, },
+};
+
+} // namespace
+
+TEST(FileSystemHostContextTest, GetRootPath) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kRootPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "RootPath #" << i << " "
+ << kRootPathTestCases[i].expected_path);
+
+ scoped_refptr<FileSystemHostContext> context(
+ new FileSystemHostContext(FilePath(kTestDataPath),
+ kRootPathTestCases[i].off_the_record));
+
+ FilePath root_path;
+ bool result = context->GetFileSystemRootPath(
+ GURL(kRootPathTestCases[i].origin_url),
+ kRootPathTestCases[i].type,
+ &root_path, NULL);
+ EXPECT_EQ(kRootPathTestCases[i].expect_root_path, result);
+ if (result) {
+ FilePath expected = FilePath(kTestDataPath).AppendASCII(
+ kRootPathTestCases[i].expected_path);
+ EXPECT_EQ(expected.value(), root_path.value());
+ }
+ }
+}
+
+TEST(FileSystemHostContextTest, CheckValidPath) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kCheckValidPathTestCases); ++i) {
+ SCOPED_TRACE(testing::Message() << "CheckValidPath #" << i << " "
+ << kCheckValidPathTestCases[i].path);
+
+ scoped_refptr<FileSystemHostContext> context(
+ new FileSystemHostContext(FilePath(kTestDataPath), false));
+
+ FilePath root_path;
+ EXPECT_TRUE(context->GetFileSystemRootPath(
+ GURL("http://foo.com/"), WebKit::WebFileSystem::TypePersistent,
+ &root_path, NULL));
+ FilePath path(kCheckValidPathTestCases[i].path);
+ if (!path.IsAbsolute())
+ path = root_path.Append(path);
+
+ EXPECT_EQ(kCheckValidPathTestCases[i].expected_valid,
+ context->CheckValidFileSystemPath(path));
+ }
+}
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 7b9e0fd..2f1641e 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/chrome_blob_storage_context.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/download/download_manager.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
#include "chrome/browser/find_bar_state.h"
#include "chrome/browser/in_process_webkit/webkit_context.h"
#include "chrome/browser/net/chrome_url_request_context.h"
@@ -314,6 +315,14 @@ class OffTheRecordProfileImpl : public Profile,
return NULL;
}
+ virtual FileSystemHostContext* GetFileSystemHostContext() {
+ if (!file_system_host_context_)
+ file_system_host_context_ = new FileSystemHostContext(
+ GetPath(), IsOffTheRecord());
+ DCHECK(file_system_host_context_.get());
+ return file_system_host_context_.get();
+ }
+
virtual void InitThemes() {
profile_->InitThemes();
}
@@ -581,6 +590,9 @@ class OffTheRecordProfileImpl : public Profile,
scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+ // The file_system context for this profile.
+ scoped_refptr<FileSystemHostContext> file_system_host_context_;
+
DISALLOW_COPY_AND_ASSIGN(OffTheRecordProfileImpl);
};
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index 4dc3f5b..d876d8c 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -51,6 +51,7 @@ class ExtensionMessageService;
class ExtensionsService;
class FaviconService;
class FilePath;
+class FileSystemHostContext;
class FindBarState;
class GeolocationContentSettingsMap;
class GeolocationPermissionContext;
@@ -277,6 +278,9 @@ class Profile {
// Returns the PersonalDataManager associated with this profile.
virtual PersonalDataManager* GetPersonalDataManager() = 0;
+ // Returns the HTML5 FileSystemHostContext assigned to this profile.
+ virtual FileSystemHostContext* GetFileSystemHostContext() = 0;
+
// Init our themes system.
virtual void InitThemes() = 0;
diff --git a/chrome/browser/profile_impl.cc b/chrome/browser/profile_impl.cc
index 650b956..0f8d997 100644
--- a/chrome/browser/profile_impl.cc
+++ b/chrome/browser/profile_impl.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/browser/favicon_service.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
#include "chrome/browser/find_bar_state.h"
#include "chrome/browser/geolocation/geolocation_content_settings_map.h"
#include "chrome/browser/geolocation/geolocation_permission_context.h"
@@ -979,6 +980,14 @@ PersonalDataManager* ProfileImpl::GetPersonalDataManager() {
return personal_data_manager_.get();
}
+FileSystemHostContext* ProfileImpl::GetFileSystemHostContext() {
+ if (!file_system_host_context_.get())
+ file_system_host_context_ = new FileSystemHostContext(
+ GetPath(), IsOffTheRecord());
+ DCHECK(file_system_host_context_.get());
+ return file_system_host_context_.get();
+}
+
void ProfileImpl::InitThemes() {
if (!created_theme_provider_) {
#if defined(TOOLKIT_USES_GTK)
diff --git a/chrome/browser/profile_impl.h b/chrome/browser/profile_impl.h
index 83815e6..d3831cb 100644
--- a/chrome/browser/profile_impl.h
+++ b/chrome/browser/profile_impl.h
@@ -59,6 +59,7 @@ class ProfileImpl : public Profile,
virtual TemplateURLFetcher* GetTemplateURLFetcher();
virtual DownloadManager* GetDownloadManager();
virtual PersonalDataManager* GetPersonalDataManager();
+ virtual FileSystemHostContext* GetFileSystemHostContext();
virtual void InitThemes();
virtual void SetTheme(Extension* extension);
virtual void SetNativeTheme();
@@ -196,6 +197,7 @@ class ProfileImpl : public Profile,
scoped_ptr<StatusTray> status_tray_;
scoped_refptr<PersonalDataManager> personal_data_manager_;
scoped_ptr<PinnedTabService> pinned_tab_service_;
+ scoped_refptr<FileSystemHostContext> file_system_host_context_;
bool history_service_created_;
bool favicon_service_created_;
bool created_web_data_service_;
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index db9e6e4..816d1fb 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/download/download_file.h"
#include "chrome/browser/extensions/extension_message_service.h"
#include "chrome/browser/file_system/file_system_dispatcher_host.h"
+#include "chrome/browser/file_system/file_system_host_context.h"
#include "chrome/browser/geolocation/geolocation_permission_context.h"
#include "chrome/browser/geolocation/geolocation_dispatcher_host.h"
#include "chrome/browser/gpu_process_host.h"
@@ -254,11 +255,12 @@ ResourceMessageFilter::ResourceMessageFilter(
new SearchProviderInstallStateDispatcherHost(this, profile))),
ALLOW_THIS_IN_INITIALIZER_LIST(device_orientation_dispatcher_host_(
new device_orientation::DispatcherHost(this->id()))),
+ ALLOW_THIS_IN_INITIALIZER_LIST(blob_dispatcher_host_(
+ new BlobDispatcherHost(profile->GetBlobStorageContext()))),
ALLOW_THIS_IN_INITIALIZER_LIST(file_system_dispatcher_host_(
new FileSystemDispatcherHost(this,
- profile->GetHostContentSettingsMap()))),
- ALLOW_THIS_IN_INITIALIZER_LIST(blob_dispatcher_host_(
- new BlobDispatcherHost(profile->GetBlobStorageContext()))) {
+ profile->GetFileSystemHostContext(),
+ profile->GetHostContentSettingsMap()))) {
request_context_ = profile_->GetRequestContext();
DCHECK(request_context_);
DCHECK(media_request_context_);
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 338f9d9..1a1bd2d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1497,6 +1497,8 @@
'browser/file_path_watcher_win.cc',
'browser/file_system/file_system_dispatcher_host.cc',
'browser/file_system/file_system_dispatcher_host.h',
+ 'browser/file_system/file_system_host_context.cc',
+ 'browser/file_system/file_system_host_context.h',
'browser/find_bar.h',
'browser/find_bar_controller.cc',
'browser/find_bar_controller.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 5fb20c2..cff0ea7 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1068,6 +1068,7 @@
'browser/extensions/user_script_listener_unittest.cc',
'browser/extensions/user_script_master_unittest.cc',
'browser/file_path_watcher_unittest.cc',
+ 'browser/file_system/file_system_host_context_unittest.cc',
'browser/find_backend_unittest.cc',
'browser/first_run/first_run_unittest.cc',
'browser/geolocation/fake_access_token_store.h',
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h
index a080bd5..6399692 100644
--- a/chrome/test/testing_profile.h
+++ b/chrome/test/testing_profile.h
@@ -156,6 +156,7 @@ class TestingProfile : public Profile {
virtual history::TopSites* GetTopSites();
virtual DownloadManager* GetDownloadManager() { return NULL; }
virtual PersonalDataManager* GetPersonalDataManager() { return NULL; }
+ virtual FileSystemHostContext* GetFileSystemHostContext() { return NULL; }
virtual bool HasCreatedDownloadManager() const { return false; }
virtual void InitThemes();
virtual void SetTheme(Extension* extension) {}