summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authoraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-25 05:08:54 +0000
committeraa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-25 05:08:54 +0000
commitbdbc87ca87fda52c3262240705d974030e9ed4b4 (patch)
tree6ca34f4c2ba9fe4b340075206846c115a5400d27 /chrome/browser
parent1692ea885338dd799ae9f47151d2a7fd4d1b10c4 (diff)
downloadchromium_src-bdbc87ca87fda52c3262240705d974030e9ed4b4.zip
chromium_src-bdbc87ca87fda52c3262240705d974030e9ed4b4.tar.gz
chromium_src-bdbc87ca87fda52c3262240705d974030e9ed4b4.tar.bz2
Add user script support to extensions.
This is implemented mostly by relying on the existing user script code. But since extension user scripts are declared, not discovered in a directory, I had to add support for adding 'lone' user scripts to UserScriptMaster. This led to a bit of refactoring. Note that this CL relies on: http://codereview.chromium.org/18352 Review URL: http://codereview.chromium.org/18198 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8614 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_init.cc4
-rw-r--r--chrome/browser/extensions/extensions_service.cc25
-rw-r--r--chrome/browser/extensions/extensions_service.h7
-rw-r--r--chrome/browser/extensions/user_script_master.cc120
-rw-r--r--chrome/browser/extensions/user_script_master.h52
-rw-r--r--chrome/browser/extensions/user_script_master_unittest.cc2
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc15
-rw-r--r--chrome/browser/profile.cc40
-rw-r--r--chrome/browser/profile.h4
9 files changed, 185 insertions, 84 deletions
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc
index b65d88c..4b061e6 100644
--- a/chrome/browser/browser_init.cc
+++ b/chrome/browser/browser_init.cc
@@ -494,9 +494,7 @@ bool BrowserInit::LaunchWithProfile::Launch(Profile* profile,
}
}
- // Start up the extensions service
- if (parsed_command_line.HasSwitch(switches::kEnableExtensions))
- profile->GetExtensionsService()->Init();
+ profile->InitExtensions();
return true;
}
diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc
index 85d4fe8..e103821 100644
--- a/chrome/browser/extensions/extensions_service.cc
+++ b/chrome/browser/extensions/extensions_service.cc
@@ -9,6 +9,7 @@
#include "base/string_util.h"
#include "base/thread.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/user_script_master.h"
#include "chrome/common/json_value_serializer.h"
#include "chrome/common/notification_service.h"
@@ -17,10 +18,12 @@
const FilePath::CharType* ExtensionsService::kInstallDirectoryName =
FILE_PATH_LITERAL("Extensions");
-ExtensionsService::ExtensionsService(const FilePath& profile_directory)
+ExtensionsService::ExtensionsService(const FilePath& profile_directory,
+ UserScriptMaster* user_script_master)
: message_loop_(MessageLoop::current()),
backend_(new ExtensionsServiceBackend),
- install_directory_(profile_directory.Append(kInstallDirectoryName)) {
+ install_directory_(profile_directory.Append(kInstallDirectoryName)),
+ user_script_master_(user_script_master) {
}
ExtensionsService::~ExtensionsService() {
@@ -53,6 +56,24 @@ void ExtensionsService::OnExtensionsLoadedFromDirectory(
extensions_.insert(extensions_.end(), new_extensions->begin(),
new_extensions->end());
+ // Tell UserScriptMaster about any scripts in the loaded extensions.
+ for (ExtensionList::iterator extension = extensions_.begin();
+ extension != extensions_.end(); ++extension) {
+ const UserScriptList& scripts = (*extension)->user_scripts();
+ for (UserScriptList::const_iterator script = scripts.begin();
+ script != scripts.end(); ++script) {
+ user_script_master_->AddLoneScript(*script);
+ }
+ }
+
+ // Tell UserScriptMaster to also watch the extensions directory for changes
+ // and then kick off the first scan.
+ // TODO(aa): This should go away when we implement the --extension flag, since
+ // developing scripts in the Extensions directory will no longer be a common
+ // use-case.
+ user_script_master_->AddWatchedPath(install_directory_);
+ user_script_master_->StartScan();
+
NotificationService::current()->Notify(NOTIFY_EXTENSIONS_LOADED,
NotificationService::AllSources(),
Details<ExtensionList>(new_extensions));
diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h
index ed5a81c..1a78d0a 100644
--- a/chrome/browser/extensions/extensions_service.h
+++ b/chrome/browser/extensions/extensions_service.h
@@ -15,6 +15,7 @@
typedef std::vector<Extension*> ExtensionList;
class ExtensionsServiceBackend;
+class UserScriptMaster;
// Interface for the frontend to implement. Typically, this will be
// ExtensionsService, but it can also be a test harness.
@@ -38,7 +39,8 @@ class ExtensionsServiceFrontendInterface
// Manages installed and running Chromium extensions.
class ExtensionsService : public ExtensionsServiceFrontendInterface {
public:
- ExtensionsService(const FilePath& profile_directory);
+ ExtensionsService(const FilePath& profile_directory,
+ UserScriptMaster* user_script_master);
~ExtensionsService();
// Gets the list of currently installed extensions.
@@ -71,6 +73,9 @@ class ExtensionsService : public ExtensionsServiceFrontendInterface {
// The full path to the directory where extensions are installed.
FilePath install_directory_;
+ // The user script master for this profile.
+ scoped_refptr<UserScriptMaster> user_script_master_;
+
DISALLOW_COPY_AND_ASSIGN(ExtensionsService);
};
diff --git a/chrome/browser/extensions/user_script_master.cc b/chrome/browser/extensions/user_script_master.cc
index 6efb577..66a8d70 100644
--- a/chrome/browser/extensions/user_script_master.cc
+++ b/chrome/browser/extensions/user_script_master.cc
@@ -13,7 +13,7 @@
#include "base/pickle.h"
#include "base/string_util.h"
#include "chrome/common/notification_service.h"
-#include "googleurl/src/gurl.h"
+#include "chrome/common/stl_util-inl.h"
#include "net/base/net_util.h"
// Defined in extension.h.
@@ -74,15 +74,15 @@ void UserScriptMaster::ScriptReloader::ParseMetadataHeader(
}
void UserScriptMaster::ScriptReloader::StartScan(
- MessageLoop* work_loop,
- const FilePath& script_dir) {
+ MessageLoop* work_loop, const FilePath& script_dir,
+ const UserScriptList& lone_scripts) {
// Add a reference to ourselves to keep ourselves alive while we're running.
// Balanced by NotifyMaster().
AddRef();
work_loop->PostTask(FROM_HERE,
NewRunnableMethod(this,
&UserScriptMaster::ScriptReloader::RunScan,
- script_dir));
+ script_dir, lone_scripts));
}
void UserScriptMaster::ScriptReloader::NotifyMaster(
@@ -99,8 +99,9 @@ void UserScriptMaster::ScriptReloader::NotifyMaster(
Release();
}
-void UserScriptMaster::ScriptReloader::RunScan(const FilePath script_dir) {
- base::SharedMemory* shared_memory = GetNewScripts(script_dir);
+void UserScriptMaster::ScriptReloader::RunScan(
+ const FilePath script_dir, const UserScriptList lone_scripts) {
+ base::SharedMemory* shared_memory = GetNewScripts(script_dir, lone_scripts);
// Post the new scripts back to the master's message loop.
master_message_loop_->PostTask(FROM_HERE,
@@ -110,45 +111,47 @@ void UserScriptMaster::ScriptReloader::RunScan(const FilePath script_dir) {
}
base::SharedMemory* UserScriptMaster::ScriptReloader::GetNewScripts(
- const FilePath& script_dir) {
- std::vector<std::wstring> scripts;
-
- file_util::FileEnumerator enumerator(script_dir, false,
- file_util::FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.user.js"));
- for (FilePath file = enumerator.Next(); !file.value().empty();
- file = enumerator.Next()) {
- scripts.push_back(file.ToWStringHack());
+ const FilePath& script_dir, const UserScriptList& lone_scripts) {
+ UserScriptList all_scripts;
+
+ // Find all the scripts in |script_dir|.
+ if (!script_dir.value().empty()) {
+ file_util::FileEnumerator enumerator(script_dir, false,
+ file_util::FileEnumerator::FILES,
+ FILE_PATH_LITERAL("*.user.js"));
+ for (FilePath file = enumerator.Next(); !file.value().empty();
+ file = enumerator.Next()) {
+ all_scripts.push_back(UserScriptInfo());
+ UserScriptInfo& info = all_scripts.back();
+ info.url = GURL(std::string(kUserScriptURLScheme) + ":/" +
+ net::FilePathToFileURL(file.ToWStringHack()).ExtractFileName());
+ info.path = file;
+ }
}
- if (scripts.empty())
+ if (all_scripts.empty() && lone_scripts.empty())
return NULL;
- // Pickle scripts data.
- Pickle pickle;
- pickle.WriteSize(scripts.size());
- for (std::vector<std::wstring>::iterator path = scripts.begin();
- path != scripts.end(); ++path) {
- std::string url(kUserScriptURLScheme);
- url += ":/";
- url += net::FilePathToFileURL(*path).ExtractFileName();
+ // Add all the lone scripts.
+ all_scripts.insert(all_scripts.end(), lone_scripts.begin(),
+ lone_scripts.end());
- std::string contents;
+ // Load and pickle each script. Look for a metadata header if there are no
+ // matches specified already.
+ Pickle pickle;
+ pickle.WriteSize(all_scripts.size());
+ for (UserScriptList::iterator iter = all_scripts.begin();
+ iter != all_scripts.end(); ++iter) {
// TODO(aa): Support unicode script files.
- file_util::ReadFileToString(*path, &contents);
-
- std::vector<std::string> includes;
- ParseMetadataHeader(contents, &includes);
-
- // Write scripts as 'data' so that we can read it out in the slave without
- // allocating a new string.
- pickle.WriteData(url.c_str(), url.length());
- pickle.WriteData(contents.c_str(), contents.length());
- pickle.WriteSize(includes.size());
- for (std::vector<std::string>::iterator iter = includes.begin();
- iter != includes.end(); ++iter) {
- pickle.WriteString(*iter);
+ std::string contents;
+ file_util::ReadFileToString(iter->path.ToWStringHack(), &contents);
+
+ if (iter->matches.empty()) {
+ // TODO(aa): Handle errors parsing header.
+ ParseMetadataHeader(contents, &iter->matches);
}
+
+ PickleScriptData(*iter, contents, &pickle);
}
// Create the shared memory object.
@@ -171,22 +174,45 @@ base::SharedMemory* UserScriptMaster::ScriptReloader::GetNewScripts(
return shared_memory.release();
}
+void UserScriptMaster::ScriptReloader::PickleScriptData(
+ const UserScriptInfo& script, const std::string& contents, Pickle* pickle) {
+ // Write scripts as 'data' so that we can read it out in the slave without
+ // allocating a new string.
+ pickle->WriteData(script.url.spec().c_str(), script.url.spec().length());
+ pickle->WriteData(contents.c_str(), contents.length());
+ pickle->WriteSize(script.matches.size());
+ for (std::vector<std::string>::const_iterator iter = script.matches.begin();
+ iter != script.matches.end(); ++iter) {
+ pickle->WriteString(*iter);
+ }
+}
+
UserScriptMaster::UserScriptMaster(MessageLoop* worker_loop,
- const FilePath& script_dir)
- : user_script_dir_(new FilePath(script_dir)),
- dir_watcher_(new DirectoryWatcher),
+ const FilePath& script_dir)
+ : user_script_dir_(script_dir),
worker_loop_(worker_loop),
pending_scan_(false) {
- // Watch our scripts directory for modifications.
- if (dir_watcher_->Watch(script_dir, this)) {
- // (Asynchronously) scan for our initial set of scripts.
- StartScan();
- }
+ if (!user_script_dir_.value().empty())
+ AddWatchedPath(script_dir);
}
UserScriptMaster::~UserScriptMaster() {
if (script_reloader_)
script_reloader_->DisownMaster();
+
+// TODO(aa): Enable this when DirectoryWatcher is implemented for linux and mac.
+#if defined(OS_WIN)
+ STLDeleteElements(&dir_watchers_);
+#endif
+}
+
+void UserScriptMaster::AddWatchedPath(const FilePath& path) {
+// TODO(aa): Enable this when DirectoryWatcher is implemented for linux and mac.
+#if defined(OS_WIN)
+ DirectoryWatcher* watcher = new DirectoryWatcher();
+ watcher->Watch(path, this);
+ dir_watchers_.push_back(watcher);
+#endif
}
void UserScriptMaster::NewScriptsAvailable(base::SharedMemory* handle) {
@@ -225,5 +251,5 @@ void UserScriptMaster::StartScan() {
if (!script_reloader_)
script_reloader_ = new ScriptReloader(this);
- script_reloader_->StartScan(worker_loop_, *user_script_dir_);
+ script_reloader_->StartScan(worker_loop_, user_script_dir_, lone_scripts_);
}
diff --git a/chrome/browser/extensions/user_script_master.h b/chrome/browser/extensions/user_script_master.h
index 5167a65..1c1b095 100644
--- a/chrome/browser/extensions/user_script_master.h
+++ b/chrome/browser/extensions/user_script_master.h
@@ -14,6 +14,8 @@
#include "base/string_piece.h"
#include "googleurl/src/gurl.h"
+class Pickle;
+
struct UserScriptInfo {
GURL url;
FilePath path;
@@ -32,6 +34,19 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
UserScriptMaster(MessageLoop* worker, const FilePath& script_dir);
~UserScriptMaster();
+ // Add a single user script that exists outside the script directory.
+ void AddLoneScript(const UserScriptInfo& script) {
+ lone_scripts_.push_back(script);
+ }
+
+ // Add a watched directory. All scripts will be reloaded when any file in
+ // this directory changes.
+ void AddWatchedPath(const FilePath& path);
+
+ // Kicks off a process on the file thread to reload scripts from disk
+ // into a new chunk of shared memory and notify renderers.
+ void StartScan();
+
// Gets the segment of shared memory for the scripts.
base::SharedMemory* GetSharedMemory() const {
return shared_memory_.get();
@@ -44,7 +59,7 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
bool ScriptsReady() const { return shared_memory_.get() != NULL; }
// Returns the path to the directory user scripts are stored in.
- FilePath user_script_dir() const { return *user_script_dir_; }
+ FilePath user_script_dir() const { return user_script_dir_; }
private:
FRIEND_TEST(UserScriptMasterTest, Parse1);
@@ -69,7 +84,8 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
// Start a scan for scripts.
// Will always send a message to the master upon completion.
- void StartScan(MessageLoop* work_loop, const FilePath& script_dir);
+ void StartScan(MessageLoop* work_loop, const FilePath& script_dir,
+ const UserScriptList &external_scripts);
// The master is going away; don't call it back.
void DisownMaster() {
@@ -89,15 +105,20 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
void NotifyMaster(base::SharedMemory* memory);
// Runs on the File thread.
- // Scan the script directory for scripts, calling NotifyMaster when done.
- // The path is intentionally passed by value so its lifetime isn't tied
- // to the caller.
- void RunScan(const FilePath script_dir);
+ // Scan the specified directory and lone scripts, calling NotifyMaster when
+ // done. The parameters are intentionally passed by value so their lifetimes
+ // aren't tied to the caller.
+ void RunScan(const FilePath script_dir, const UserScriptList lone_scripts);
// Runs on the File thread.
- // Scan the script directory for scripts, returning either a
- // new SharedMemory or NULL on error.
- base::SharedMemory* GetNewScripts(const FilePath& script_dir);
+ // Scan the script directory and lone scripts, returning either a new
+ // SharedMemory or NULL on error.
+ base::SharedMemory* GetNewScripts(const FilePath& script_dir,
+ const UserScriptList& lone_scripts);
+
+ // Serialize script metadata and contents into the specified pickle.
+ void PickleScriptData(const UserScriptInfo& script,
+ const std::string& contents, Pickle* pickle);
// A pointer back to our master.
// May be NULL if DisownMaster() is called.
@@ -113,15 +134,11 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
// DirectoryWatcher::Delegate implementation.
virtual void OnDirectoryChanged(const FilePath& path);
- // Kicks off a process on the file thread to reload scripts from disk
- // into a new chunk of shared memory and notify renderers.
- void StartScan();
-
- // The directory containing user scripts.
- scoped_ptr<FilePath> user_script_dir_;
+ // The directories containing user scripts.
+ FilePath user_script_dir_;
// The watcher watches the profile's user scripts directory for new scripts.
- scoped_ptr<DirectoryWatcher> dir_watcher_;
+ std::vector<DirectoryWatcher*> dir_watchers_;
// The MessageLoop that the scanner worker runs on.
// Typically the file thread; configurable for testing.
@@ -134,6 +151,9 @@ class UserScriptMaster : public base::RefCounted<UserScriptMaster>,
// Contains the scripts that were found the last time scripts were updated.
scoped_ptr<base::SharedMemory> shared_memory_;
+ // List of scripts outside of script directories we should also load.
+ UserScriptList lone_scripts_;
+
// If the script directory is modified while we're rescanning it, we note
// that we're currently mid-scan and then start over again once the scan
// finishes. This boolean tracks whether another scan is pending.
diff --git a/chrome/browser/extensions/user_script_master_unittest.cc b/chrome/browser/extensions/user_script_master_unittest.cc
index 0fa1932..f0f2dc2 100644
--- a/chrome/browser/extensions/user_script_master_unittest.cc
+++ b/chrome/browser/extensions/user_script_master_unittest.cc
@@ -74,6 +74,7 @@ TEST_F(UserScriptMasterTest, NoScripts) {
scoped_refptr<UserScriptMaster> master(
new UserScriptMaster(MessageLoop::current(), script_dir_));
+ master->StartScan();
message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask);
message_loop_.Run();
@@ -110,6 +111,7 @@ TEST_F(UserScriptMasterTest, ExistingScripts) {
scoped_refptr<UserScriptMaster> master(
new UserScriptMaster(MessageLoop::current(), script_dir_));
+ master->StartScan();
message_loop_.PostTask(FROM_HERE, new MessageLoop::QuitTask);
message_loop_.Run();
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc
index 4c877f5..f11b710 100644
--- a/chrome/browser/net/chrome_url_request_context.cc
+++ b/chrome/browser/net/chrome_url_request_context.cc
@@ -105,14 +105,17 @@ ChromeURLRequestContext::ChromeURLRequestContext(Profile* profile)
cookie_policy_.SetType(net::CookiePolicy::FromInt(
prefs_->GetInteger(prefs::kCookieBehavior)));
- const ExtensionList* extensions =
- profile->GetExtensionsService()->extensions();
- for (ExtensionList::const_iterator iter = extensions->begin();
- iter != extensions->end(); ++iter) {
- extension_paths_[(*iter)->id()] = (*iter)->path();
+ if (profile->GetExtensionsService()) {
+ const ExtensionList* extensions =
+ profile->GetExtensionsService()->extensions();
+ for (ExtensionList::const_iterator iter = extensions->begin();
+ iter != extensions->end(); ++iter) {
+ extension_paths_[(*iter)->id()] = (*iter)->path();
+ }
}
- user_script_dir_path_ = profile->GetUserScriptMaster()->user_script_dir();
+ if (profile->GetUserScriptMaster())
+ user_script_dir_path_ = profile->GetUserScriptMaster()->user_script_dir();
prefs_->AddPrefObserver(prefs::kAcceptLanguages, this);
prefs_->AddPrefObserver(prefs::kCookieBehavior, this);
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 089dd9c..5af89c9 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -257,6 +257,10 @@ class OffTheRecordProfileImpl : public Profile,
virtual void MarkAsCleanShutdown() {
}
+ virtual void InitExtensions() {
+ NOTREACHED();
+ }
+
virtual void ExitedOffTheRecordMode() {
// Drop our download manager so we forget about all the downloads made
// in off-the-record mode.
@@ -297,7 +301,6 @@ class OffTheRecordProfileImpl : public Profile,
ProfileImpl::ProfileImpl(const std::wstring& path)
: path_(path),
off_the_record_(false),
- extensions_service_(new ExtensionsService(FilePath(path))),
history_service_created_(false),
created_web_data_service_(false),
created_download_manager_(false),
@@ -313,11 +316,38 @@ ProfileImpl::ProfileImpl(const std::wstring& path)
create_session_service_timer_.Start(
TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
&ProfileImpl::EnsureSessionServiceCreated);
+
PrefService* prefs = GetPrefs();
prefs->AddPrefObserver(prefs::kSpellCheckDictionary, this);
prefs->AddPrefObserver(prefs::kEnableSpellCheck, this);
}
+void ProfileImpl::InitExtensions() {
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ bool user_scripts_enabled =
+ command_line->HasSwitch(switches::kEnableUserScripts);
+ bool extensions_enabled =
+ command_line->HasSwitch(switches::kEnableExtensions);
+
+ std::wstring script_dir;
+ if (user_scripts_enabled) {
+ script_dir = GetPath();
+ file_util::AppendToPath(&script_dir, chrome::kUserScriptsDirname);
+ }
+
+ user_script_master_ = new UserScriptMaster(
+ g_browser_process->file_thread()->message_loop(), FilePath(script_dir));
+ extensions_service_ = new ExtensionsService(
+ FilePath(GetPath()), user_script_master_.get());
+
+ // If we have extensions, the extension service will kick off the first scan
+ // after extensions are loaded. Otherwise, we need to do that now.
+ if (extensions_enabled)
+ extensions_service_->Init();
+ else if (user_scripts_enabled)
+ user_script_master_->StartScan();
+}
+
ProfileImpl::~ProfileImpl() {
tab_restore_service_ = NULL;
@@ -449,14 +479,6 @@ ExtensionsService* ProfileImpl::GetExtensionsService() {
}
UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
- if (!user_script_master_.get()) {
- std::wstring script_dir = GetPath();
- file_util::AppendToPath(&script_dir, chrome::kUserScriptsDirname);
- user_script_master_ =
- new UserScriptMaster(g_browser_process->file_thread()->message_loop(),
- FilePath(script_dir));
- }
-
return user_script_master_.get();
}
diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h
index f5e0866..2ef3eff 100644
--- a/chrome/browser/profile.h
+++ b/chrome/browser/profile.h
@@ -224,6 +224,9 @@ class Profile {
// NOTE: this is invoked internally on a normal shutdown, but is public so
// that it can be invoked when the user logs out/powers down (WM_ENDSESSION).
virtual void MarkAsCleanShutdown() = 0;
+
+ virtual void InitExtensions() = 0;
+
#ifdef UNIT_TEST
// Use with caution. GetDefaultRequestContext may be called on any thread!
static void set_default_request_context(URLRequestContext* c) {
@@ -286,6 +289,7 @@ class ProfileImpl : public Profile,
virtual void ReinitializeSpellChecker();
virtual SpellChecker* GetSpellChecker();
virtual void MarkAsCleanShutdown();
+ virtual void InitExtensions();
#ifdef CHROME_PERSONALIZATION
virtual ProfilePersonalization* GetProfilePersonalization();
#endif