diff options
author | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-05 00:38:25 +0000 |
---|---|---|
committer | aa@chromium.org <aa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-05 00:38:25 +0000 |
commit | 6014d67a9c2006e15cfa09babfe5eaf63d57a331 (patch) | |
tree | 9c0d36df02bd5b4a0e7fca1fa23045e3e6f26f27 /chrome | |
parent | fad84eab5e64996804824f2c7b8fce98da13b2cd (diff) | |
download | chromium_src-6014d67a9c2006e15cfa09babfe5eaf63d57a331.zip chromium_src-6014d67a9c2006e15cfa09babfe5eaf63d57a331.tar.gz chromium_src-6014d67a9c2006e15cfa09babfe5eaf63d57a331.tar.bz2 |
Introduce ExtensionsService. Load extensions on startup from a directory in
the profile if a command-line flag is present.
Please carefully scrutinize the threading/ref-counting schenanigans.
Review URL: http://codereview.chromium.org/12876
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6403 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser.scons | 1 | ||||
-rw-r--r-- | chrome/browser/browser.vcproj | 8 | ||||
-rw-r--r-- | chrome/browser/browser_init.cc | 6 | ||||
-rw-r--r-- | chrome/browser/extensions/extension.cc | 41 | ||||
-rw-r--r-- | chrome/browser/extensions/extension.h | 33 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.cc | 130 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service.h | 106 | ||||
-rw-r--r-- | chrome/browser/extensions/extensions_service_unittest.cc | 98 | ||||
-rw-r--r-- | chrome/browser/profile.cc | 10 | ||||
-rw-r--r-- | chrome/browser/profile.h | 7 | ||||
-rw-r--r-- | chrome/common/chrome_switches.cc | 3 | ||||
-rw-r--r-- | chrome/common/chrome_switches.h | 1 | ||||
-rwxr-xr-x | chrome/test/data/extensions/extension1/manifest | 10 | ||||
-rwxr-xr-x | chrome/test/data/extensions/extension2/manifest | 5 | ||||
-rw-r--r-- | chrome/test/testing_profile.h | 3 | ||||
-rw-r--r-- | chrome/test/unit/unit_tests.scons | 1 | ||||
-rw-r--r-- | chrome/test/unit/unittests.vcproj | 4 |
17 files changed, 435 insertions, 32 deletions
diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index c29cc02..d6c6334 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -59,6 +59,7 @@ if env['PLATFORM'] in ('posix', 'win32'): 'cross_site_request_manager.cc', 'download/save_file.cc', 'extensions/extension.cc', + 'extensions/extensions_service.cc', 'google_url_tracker.cc', 'google_util.cc', 'history/archived_database.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 51140bc..fdfcfc7 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -2173,6 +2173,14 @@ RelativePath=".\extensions\extension.h"
>
</File>
+ <File
+ RelativePath=".\extensions\extensions_service.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\extensions\extensions_service.h"
+ >
+ </File>
</Filter>
<File
RelativePath=".\browser_trial.cc"
diff --git a/chrome/browser/browser_init.cc b/chrome/browser/browser_init.cc index 0908689..b56c0b38 100644 --- a/chrome/browser/browser_init.cc +++ b/chrome/browser/browser_init.cc @@ -22,6 +22,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/dom_ui/new_tab_ui.h" +#include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/first_run.h" #include "chrome/browser/infobar_delegate.h" #include "chrome/browser/navigation_controller.h" @@ -480,6 +481,11 @@ bool BrowserInit::LaunchWithProfile::Launch(Profile* profile, base::EventRecorder::current()->StartPlayback(script_path); } } + + // Start up the extensions service + if (parsed_command_line.HasSwitch(switches::kEnableExtensions)) + profile->GetExtensionsService()->Init(); + return true; } diff --git a/chrome/browser/extensions/extension.cc b/chrome/browser/extensions/extension.cc index d4fbe9f..b2db579 100644 --- a/chrome/browser/extensions/extension.cc +++ b/chrome/browser/extensions/extension.cc @@ -7,30 +7,35 @@ #include "base/logging.h" #include "base/string_util.h" -const std::wstring Extension::kFormatVersionKey(L"format_version"); -const std::wstring Extension::kIdKey(L"id"); -const std::wstring Extension::kNameKey(L"name"); -const std::wstring Extension::kDescriptionKey(L"description"); -const std::wstring Extension::kContentScriptsKey(L"content_scripts"); - -const std::wstring Extension::kInvalidFormatVersionError( +const FilePath::CharType* Extension::kManifestFilename = + FILE_PATH_LITERAL("manifest"); + +const wchar_t* Extension::kFormatVersionKey = L"format_version"; +const wchar_t* Extension::kIdKey = L"id"; +const wchar_t* Extension::kNameKey = L"name"; +const wchar_t* Extension::kDescriptionKey = L"description"; +const wchar_t* Extension::kContentScriptsKey = L"content_scripts"; + +const wchar_t* Extension::kInvalidManifestError = + L"Manifest is missing or invalid."; +const wchar_t* Extension::kInvalidFormatVersionError = StringPrintf(L"Required key '%ls' is missing or invalid", - kFormatVersionKey.c_str())); -const std::wstring Extension::kInvalidIdError( + kFormatVersionKey).c_str(); +const wchar_t* Extension::kInvalidIdError = StringPrintf(L"Required key '%ls' is missing or invalid.", - kIdKey.c_str())); -const std::wstring Extension::kInvalidNameError( + kIdKey).c_str(); +const wchar_t* Extension::kInvalidNameError = StringPrintf(L"Required key '%ls' is missing or has invalid type.", - kNameKey.c_str())); -const std::wstring Extension::kInvalidDescriptionError( + kNameKey).c_str(); +const wchar_t* Extension::kInvalidDescriptionError = StringPrintf(L"Invalid type for '%ls' key.", - kDescriptionKey.c_str())); -const std::wstring Extension::kInvalidContentScriptsListError( + kDescriptionKey).c_str(); +const wchar_t* Extension::kInvalidContentScriptsListError = StringPrintf(L"Invalid type for '%ls' key.", - kContentScriptsKey.c_str())); -const std::wstring Extension::kInvalidContentScriptError( + kContentScriptsKey).c_str(); +const wchar_t* Extension::kInvalidContentScriptError = StringPrintf(L"Invalid type for %ls at index ", - kContentScriptsKey.c_str())); + kContentScriptsKey).c_str(); bool Extension::InitFromValue(const DictionaryValue& source, std::wstring* error) { diff --git a/chrome/browser/extensions/extension.h b/chrome/browser/extensions/extension.h index 16260e0..94127ac 100644 --- a/chrome/browser/extensions/extension.h +++ b/chrome/browser/extensions/extension.h @@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_H__ -#define CHROME_BROWSER_EXTENSIONS_EXTENSION_H__ +#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSION_H_ #include <string> #include <vector> +#include "base/file_path.h" #include "base/string16.h" #include "base/values.h" @@ -19,20 +20,24 @@ class Extension { // The format for extension manifests that this code understands. static const int kExpectedFormatVersion = 1; + // The name of the manifest inside an extension. + static const FilePath::CharType* kManifestFilename; + // Keys used in JSON representation of extensions. - static const std::wstring kFormatVersionKey; - static const std::wstring kIdKey; - static const std::wstring kNameKey; - static const std::wstring kDescriptionKey; - static const std::wstring kContentScriptsKey; + static const wchar_t* kFormatVersionKey; + static const wchar_t* kIdKey; + static const wchar_t* kNameKey; + static const wchar_t* kDescriptionKey; + static const wchar_t* kContentScriptsKey; // Error messages returned from InitFromValue(). - static const std::wstring kInvalidFormatVersionError; - static const std::wstring kInvalidIdError; - static const std::wstring kInvalidNameError; - static const std::wstring kInvalidDescriptionError; - static const std::wstring kInvalidContentScriptsListError; - static const std::wstring kInvalidContentScriptError; + static const wchar_t* kInvalidFormatVersionError; + static const wchar_t* kInvalidManifestError; + static const wchar_t* kInvalidIdError; + static const wchar_t* kInvalidNameError; + static const wchar_t* kInvalidDescriptionError; + static const wchar_t* kInvalidContentScriptsListError; + static const wchar_t* kInvalidContentScriptError; // A human-readable ID for the extension. The convention is to use something // like 'com.example.myextension', but this is not currently enforced. An @@ -68,4 +73,4 @@ class Extension { DISALLOW_COPY_AND_ASSIGN(Extension); }; -#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_H__ +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_H_ diff --git a/chrome/browser/extensions/extensions_service.cc b/chrome/browser/extensions/extensions_service.cc new file mode 100644 index 0000000..67d508e --- /dev/null +++ b/chrome/browser/extensions/extensions_service.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2006-2008 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/extensions/extensions_service.h" + +#include "base/file_util.h" +#include "base/values.h" +#include "base/string_util.h" +#include "base/thread.h" +#include "chrome/browser/browser_process.h" +#include "chrome/common/json_value_serializer.h" + +// ExtensionsService + +const FilePath::CharType* ExtensionsService::kInstallDirectoryName = + FILE_PATH_LITERAL("Extensions"); + +ExtensionsService::ExtensionsService(const FilePath& profile_directory) + : message_loop_(MessageLoop::current()), + backend_(new ExtensionsServiceBackend), + install_directory_(profile_directory.Append(kInstallDirectoryName)) { +} + +ExtensionsService::~ExtensionsService() { + for (ExtensionList::iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { + delete *iter; + } +} + +bool ExtensionsService::Init() { + // TODO(aa): This message loop should probably come from a backend + // interface, similar to how the message loop for the frontend comes + // from the frontend interface. + g_browser_process->file_thread()->message_loop()->PostTask(FROM_HERE, + NewRunnableMethod(backend_.get(), + &ExtensionsServiceBackend::LoadExtensionsFromDirectory, + install_directory_, + scoped_refptr<ExtensionsServiceFrontendInterface>(this))); + // TODO(aa): Load extensions from other registered directories. + + return true; +} + +MessageLoop* ExtensionsService::GetMessageLoop() { + return message_loop_; +} + +void ExtensionsService::OnExtensionsLoadedFromDirectory( + ExtensionList* extensions) { + extensions_.assign(extensions->begin(), extensions->end()); + delete extensions; + + // TODO(aa): Notify extensions are loaded. +} + +void ExtensionsService::OnExtensionLoadError(const std::wstring& error) { + // TODO(aa): Print the error message out somewhere better. Ideally we would + // use the JavaScript console I think, but that is complicated since these + // errors are not related to any particular page. + LOG(WARNING) << "Error loading extension: " << error; +} + + +// ExtensionsServicesBackend + +bool ExtensionsServiceBackend::LoadExtensionsFromDirectory( + const FilePath& path, + scoped_refptr<ExtensionsServiceFrontendInterface> frontend) { + // Find all child directories in the install directory and load their + // manifests. Post errors and results to the frontend. + scoped_ptr<ExtensionList> extensions(new ExtensionList); + file_util::FileEnumerator enumerator(path.ToWStringHack(), + false, // not recursive + file_util::FileEnumerator::DIRECTORIES); + for (std::wstring child_path = enumerator.Next(); !child_path.empty(); + child_path = enumerator.Next()) { + FilePath manifest_path = FilePath::FromWStringHack(child_path).Append( + Extension::kManifestFilename); + if (!file_util::PathExists(manifest_path)) { + ReportExtensionLoadError(frontend.get(), + Extension::kInvalidManifestError); + continue; + } + + JSONFileValueSerializer serializer(manifest_path.ToWStringHack()); + Value* root = NULL; + if (!serializer.Deserialize(&root)) { + ReportExtensionLoadError(frontend.get(), + Extension::kInvalidManifestError); + continue; + } + + if (!root->IsType(Value::TYPE_DICTIONARY)) { + ReportExtensionLoadError(frontend.get(), + Extension::kInvalidManifestError); + continue; + } + + scoped_ptr<Extension> extension(new Extension()); + std::wstring error; + if (!extension->InitFromValue(*static_cast<DictionaryValue*>(root), + &error)) { + ReportExtensionLoadError(frontend.get(), + Extension::kInvalidManifestError); + continue; + } + + extensions->push_back(extension.release()); + } + + ReportExtensionsLoaded(frontend.get(), extensions.release()); + return true; +} + +void ExtensionsServiceBackend::ReportExtensionLoadError( + ExtensionsServiceFrontendInterface *frontend, const std::wstring &error) { + frontend->GetMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod( + frontend, &ExtensionsServiceFrontendInterface::OnExtensionLoadError, + error)); +} + +void ExtensionsServiceBackend::ReportExtensionsLoaded( + ExtensionsServiceFrontendInterface *frontend, ExtensionList* extensions) { + frontend->GetMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod( + frontend, + &ExtensionsServiceFrontendInterface::OnExtensionsLoadedFromDirectory, + extensions)); +} diff --git a/chrome/browser/extensions/extensions_service.h b/chrome/browser/extensions/extensions_service.h new file mode 100644 index 0000000..17f25b7 --- /dev/null +++ b/chrome/browser/extensions/extensions_service.h @@ -0,0 +1,106 @@ +// Copyright (c) 2006-2008 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_EXTENSIONS_EXTENSIONS_SERVICE_H_ +#define CHROME_BROWSER_EXTENSIONS_EXTENSIONS_SERVICE_H_ + +#include <vector> + +#include "base/file_path.h" +#include "base/message_loop.h" +#include "base/ref_counted.h" +#include "base/task.h" +#include "chrome/browser/extensions/extension.h" + +typedef std::vector<Extension*> ExtensionList; +class ExtensionsServiceBackend; + +// Interface for the frontend to implement. Typically, this will be +// ExtensionsService, but it can also be a test harness. +class ExtensionsServiceFrontendInterface + : public base::RefCountedThreadSafe<ExtensionsServiceFrontendInterface> { + public: + virtual ~ExtensionsServiceFrontendInterface(){} + + // The message loop to invoke the frontend's methods on. + virtual MessageLoop* GetMessageLoop() = 0; + + // Called when loading an extension fails. + virtual void OnExtensionLoadError(const std::wstring& message) = 0; + + // Called with results from LoadExtensionsFromDirectory(). The frontend + // takes ownership of the list. + virtual void OnExtensionsLoadedFromDirectory(ExtensionList* extensions) = 0; +}; + + +// Manages installed and running Chromium extensions. +class ExtensionsService : public ExtensionsServiceFrontendInterface { + public: + ExtensionsService(const FilePath& profile_directory); + ~ExtensionsService(); + + // Gets the list of currently installed extensions. + const ExtensionList* extensions() const { + return &extensions_; + } + + // Initialize and start all installed extensions. + bool Init(); + + // ExtensionsServiceFrontendInterface + virtual MessageLoop* GetMessageLoop(); + virtual void OnExtensionLoadError(const std::wstring& message); + virtual void OnExtensionsLoadedFromDirectory(ExtensionList* extensions); + + private: + // The name of the directory inside the profile where extensions are + // installed to. + static const FilePath::CharType* kInstallDirectoryName; + + // The message loop for the thread the ExtensionsService is running on. + MessageLoop* message_loop_; + + // The backend that will do IO on behalf of this instance. + scoped_refptr<ExtensionsServiceBackend> backend_; + + // The current list of installed extensions. + ExtensionList extensions_; + + // The full path to the directory where extensions are installed. + FilePath install_directory_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionsService); +}; + +// Implements IO for the ExtensionsService. +// TODO(aa): Extract an interface out of this for testing the frontend, once the +// frontend has significant logic to test. +class ExtensionsServiceBackend + : public base::RefCountedThreadSafe<ExtensionsServiceBackend> { + public: + ExtensionsServiceBackend(){}; + + // Loads extensions from a directory. The extensions are assumed to be + // unpacked in directories that are direct children of the specified path. + // Errors are reported through OnExtensionLoadError(). On completion, + // OnExtensionsLoadedFromDirectory() is called with any successfully loaded + // extensions. + bool LoadExtensionsFromDirectory( + const FilePath &path, + scoped_refptr<ExtensionsServiceFrontendInterface> frontend); + + private: + // Notify a frontend that there was an error loading an extension. + void ReportExtensionLoadError(ExtensionsServiceFrontendInterface* frontend, + const std::wstring& error); + + // Notify a frontend that extensions were loaded. + void ReportExtensionsLoaded(ExtensionsServiceFrontendInterface* frontend, + ExtensionList* extensions); + + DISALLOW_COPY_AND_ASSIGN(ExtensionsServiceBackend); +}; + +#endif // CHROME_BROWSER_EXTENSIONS_EXTENSIONS_SERVICE_H_ diff --git a/chrome/browser/extensions/extensions_service_unittest.cc b/chrome/browser/extensions/extensions_service_unittest.cc new file mode 100644 index 0000000..22e891d --- /dev/null +++ b/chrome/browser/extensions/extensions_service_unittest.cc @@ -0,0 +1,98 @@ +// Copyright (c) 2006-2008 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 <vector> + +#include "base/file_path.h" +#include "base/file_util.h" +#include "base/message_loop.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "chrome/browser/extensions/extensions_service.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/common/json_value_serializer.h" +#include "testing/gtest/include/gtest/gtest.h" + +class ExtensionsServiceTest : public testing::Test { +}; + + +// A mock implementation of ExtensionsServiceFrontendInterface for testing the +// backend. +class ExtensionsServiceTestFrontend + : public ExtensionsServiceFrontendInterface { + public: + std::vector<std::wstring>* errors() { + return &errors_; + } + + ExtensionList* extensions() { + return extensions_.get(); + } + + // ExtensionsServiceFrontendInterface + virtual MessageLoop* GetMessageLoop() { + return &message_loop_; + } + + virtual void OnExtensionLoadError(const std::wstring& message) { + errors_.push_back(message); + } + + virtual void OnExtensionsLoadedFromDirectory(ExtensionList* extensions) { + extensions_.reset(extensions); + } + + private: + MessageLoop message_loop_; + scoped_ptr<ExtensionList> extensions_; + std::vector<std::wstring> errors_; +}; + + +// Test loading extensions from the profile directory. +TEST_F(ExtensionsServiceTest, LoadAllExtensionsFromDirectory) { +#if defined(OS_WIN) + std::wstring extensions_dir; + ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &extensions_dir)); + FilePath manifest_path = FilePath::FromWStringHack(extensions_dir).Append( + FILE_PATH_LITERAL("extensions")); + + scoped_refptr<ExtensionsServiceBackend> backend(new ExtensionsServiceBackend); + scoped_refptr<ExtensionsServiceTestFrontend> frontend( + new ExtensionsServiceTestFrontend); + + std::vector<Extension*> extensions; + EXPECT_TRUE(backend->LoadExtensionsFromDirectory(manifest_path, + scoped_refptr<ExtensionsServiceFrontendInterface>(frontend.get()))); + frontend->GetMessageLoop()->RunAllPending(); + + // Note: There can be more errors if there are extra directories, like .svn + // directories. + EXPECT_TRUE(frontend->errors()->size() >= 2u); + EXPECT_EQ(Extension::kInvalidManifestError, frontend->errors()->at(0)); + EXPECT_EQ(Extension::kInvalidManifestError, frontend->errors()->at(1)); + EXPECT_EQ(2u, frontend->extensions()->size()); + + EXPECT_EQ(std::wstring(L"com.google.myextension1"), + frontend->extensions()->at(0)->id()); + EXPECT_EQ(std::wstring(L"My extension 1"), + frontend->extensions()->at(0)->name()); + EXPECT_EQ(std::wstring(L"The first extension that I made."), + frontend->extensions()->at(0)->description()); + EXPECT_EQ(2u, frontend->extensions()->at(0)->content_scripts().size()); + EXPECT_EQ(std::wstring(L"script1.user.js"), + frontend->extensions()->at(0)->content_scripts().at(0)); + EXPECT_EQ(std::wstring(L"script2.user.js"), + frontend->extensions()->at(0)->content_scripts().at(1)); + + EXPECT_EQ(std::wstring(L"com.google.myextension2"), + frontend->extensions()->at(1)->id()); + EXPECT_EQ(std::wstring(L"My extension 2"), + frontend->extensions()->at(1)->name()); + EXPECT_EQ(std::wstring(L""), + frontend->extensions()->at(1)->description()); + EXPECT_EQ(0u, frontend->extensions()->at(1)->content_scripts().size()); +#endif +}; diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc index fb3508a..76f2f16 100644 --- a/chrome/browser/profile.cc +++ b/chrome/browser/profile.cc @@ -17,6 +17,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/greasemonkey_master.h" #include "chrome/browser/history/history.h" #include "chrome/browser/navigation_controller.h" @@ -384,6 +385,10 @@ class OffTheRecordProfileImpl : public Profile, return profile_->GetVisitedLinkMaster(); } + virtual ExtensionsService* GetExtensionsService() { + return profile_->GetExtensionsService(); + } + virtual GreasemonkeyMaster* GetGreasemonkeyMaster() { return profile_->GetGreasemonkeyMaster(); } @@ -547,6 +552,7 @@ 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), @@ -688,6 +694,10 @@ VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() { return visited_link_master_.get(); } +ExtensionsService* ProfileImpl::GetExtensionsService() { + return extensions_service_.get(); +} + GreasemonkeyMaster* ProfileImpl::GetGreasemonkeyMaster() { if (!greasemonkey_master_.get()) { std::wstring script_dir_str; diff --git a/chrome/browser/profile.h b/chrome/browser/profile.h index cb3c2ac..51a5c32 100644 --- a/chrome/browser/profile.h +++ b/chrome/browser/profile.h @@ -24,6 +24,7 @@ class BookmarkModel; class DownloadManager; +class ExtensionsService; class GreasemonkeyMaster; class HistoryService; class NavigationController; @@ -102,6 +103,10 @@ class Profile { // that this method is called. virtual VisitedLinkMaster* GetVisitedLinkMaster() = 0; + // Retrieves a pointer to the ExtensionsService associated with this + // profile. The ExtensionsService is created at startup. + virtual ExtensionsService* GetExtensionsService() = 0; + // Retrieves a pointer to the GreasemonkeyMaster associated with this // profile. The GreasemonkeyMaster is lazily created the first time // that this method is called. @@ -243,6 +248,7 @@ class ProfileImpl : public Profile, virtual Profile* GetOriginalProfile(); virtual VisitedLinkMaster* GetVisitedLinkMaster(); virtual GreasemonkeyMaster* GetGreasemonkeyMaster(); + virtual ExtensionsService* GetExtensionsService(); virtual HistoryService* GetHistoryService(ServiceAccessType sat); virtual WebDataService* GetWebDataService(ServiceAccessType sat); virtual PrefService* GetPrefs(); @@ -303,6 +309,7 @@ class ProfileImpl : public Profile, std::wstring path_; bool off_the_record_; scoped_ptr<VisitedLinkMaster> visited_link_master_; + scoped_refptr<ExtensionsService> extensions_service_; scoped_refptr<GreasemonkeyMaster> greasemonkey_master_; scoped_ptr<PrefService> prefs_; scoped_ptr<TemplateURLFetcher> template_url_fetcher_; diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 4d076f9..feccc82 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc @@ -336,6 +336,9 @@ const wchar_t kSdchFilter[] = L"enable-sdch"; // Enable Greasemonkey script support. const wchar_t kEnableGreasemonkey[] = L"enable-greasemonkey"; +// Enable extensions. +const wchar_t kEnableExtensions[] = L"enable-extensions"; + // Causes the browser to launch directly in incognito mode. const wchar_t kIncognito[] = L"incognito"; diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 7a75cb5..78e8212 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h @@ -130,6 +130,7 @@ extern const wchar_t kEnableP13n[]; extern const wchar_t kSdchFilter[]; extern const wchar_t kEnableGreasemonkey[]; +extern const wchar_t kEnableExtensions[]; extern const wchar_t kIncognito[]; extern const wchar_t kUseOldSafeBrowsing[]; diff --git a/chrome/test/data/extensions/extension1/manifest b/chrome/test/data/extensions/extension1/manifest new file mode 100755 index 0000000..b475913 --- /dev/null +++ b/chrome/test/data/extensions/extension1/manifest @@ -0,0 +1,10 @@ +{
+ "format_version": 1,
+ "id": "com.google.myextension1",
+ "name": "My extension 1",
+ "description": "The first extension that I made.",
+ "content_scripts": [
+ "script1.user.js",
+ "script2.user.js"
+ ]
+}
diff --git a/chrome/test/data/extensions/extension2/manifest b/chrome/test/data/extensions/extension2/manifest new file mode 100755 index 0000000..82b25d8d --- /dev/null +++ b/chrome/test/data/extensions/extension2/manifest @@ -0,0 +1,5 @@ +{
+ "format_version": 1,
+ "id": "com.google.myextension2",
+ "name": "My extension 2"
+}
diff --git a/chrome/test/testing_profile.h b/chrome/test/testing_profile.h index 10b6fbe..4973682 100644 --- a/chrome/test/testing_profile.h +++ b/chrome/test/testing_profile.h @@ -66,6 +66,9 @@ class TestingProfile : public Profile { virtual VisitedLinkMaster* GetVisitedLinkMaster() { return NULL; } + virtual ExtensionsService* GetExtensionsService() { + return NULL; + } virtual GreasemonkeyMaster* GetGreasemonkeyMaster() { return NULL; } diff --git a/chrome/test/unit/unit_tests.scons b/chrome/test/unit/unit_tests.scons index 320dc09..df884b1 100644 --- a/chrome/test/unit/unit_tests.scons +++ b/chrome/test/unit/unit_tests.scons @@ -116,6 +116,7 @@ if env['PLATFORM'] in ('posix', 'win32'): '$CHROME_DIR/browser/chrome_thread_unittest.cc', '$CHROME_DIR/browser/extensions/extension_unittest.cc', + '$CHROME_DIR/browser/extensions/extensions_service_unittest.cc', '$CHROME_DIR/browser/history/history_types_unittest.cc', '$CHROME_DIR/browser/history/snippet_unittest.cc', '$CHROME_DIR/browser/history/text_database_unittest.cc', diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj index 826959f..ab3eda5 100644 --- a/chrome/test/unit/unittests.vcproj +++ b/chrome/test/unit/unittests.vcproj @@ -1033,6 +1033,10 @@ RelativePath="..\..\browser\extensions\extension_unittest.cc"
>
</File>
+ <File
+ RelativePath="..\..\browser\extensions\extensions_service_unittest.cc"
+ >
+ </File>
</Filter>
</Files>
<Globals>
|