blob: 919ccc22dde2f6992bff9fa878bd6ad04e7d89c7 [file] [log] [blame]
[email protected]31d8f5f22012-04-02 15:22:081// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_system.h"
6
7#include "base/bind.h"
8#include "base/command_line.h"
9#include "base/file_path.h"
10#include "base/string_tokenizer.h"
11#include "chrome/browser/browser_process.h"
[email protected]31d8f5f22012-04-02 15:22:0812#include "chrome/browser/content_settings/cookie_settings.h"
[email protected]ca6df682012-04-10 23:00:2013#include "chrome/browser/extensions/api/alarms/alarm_manager.h"
[email protected]b813ed72012-04-05 08:21:3614#include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
[email protected]931186e02012-07-20 01:22:0615#include "chrome/browser/extensions/component_loader.h"
[email protected]5a38dfd2012-07-23 23:22:1016#include "chrome/browser/extensions/event_router.h"
[email protected]31d8f5f22012-04-02 15:22:0817#include "chrome/browser/extensions/extension_devtools_manager.h"
18#include "chrome/browser/extensions/extension_error_reporter.h"
[email protected]31d8f5f22012-04-02 15:22:0819#include "chrome/browser/extensions/extension_info_map.h"
[email protected]31d8f5f22012-04-02 15:22:0820#include "chrome/browser/extensions/extension_pref_store.h"
21#include "chrome/browser/extensions/extension_pref_value_map.h"
[email protected]ef9bba12012-04-06 16:26:0922#include "chrome/browser/extensions/extension_pref_value_map_factory.h"
[email protected]31d8f5f22012-04-02 15:22:0823#include "chrome/browser/extensions/extension_process_manager.h"
24#include "chrome/browser/extensions/extension_service.h"
25#include "chrome/browser/extensions/extension_system_factory.h"
26#include "chrome/browser/extensions/lazy_background_task_queue.h"
[email protected]65187152012-06-02 13:14:1427#include "chrome/browser/extensions/management_policy.h"
[email protected]40404bc2012-07-25 17:40:4928#include "chrome/browser/extensions/message_service.h"
[email protected]d9ede582012-08-14 19:21:3829#include "chrome/browser/extensions/navigation_observer.h"
[email protected]90e800c2012-06-12 23:11:0030#include "chrome/browser/extensions/state_store.h"
[email protected]31d8f5f22012-04-02 15:22:0831#include "chrome/browser/extensions/unpacked_installer.h"
32#include "chrome/browser/extensions/user_script_master.h"
[email protected]8e7b2cf42012-04-18 14:26:5833#include "chrome/browser/prefs/pref_service.h"
[email protected]31d8f5f22012-04-02 15:22:0834#include "chrome/browser/profiles/profile.h"
35#include "chrome/browser/profiles/profile_manager.h"
36#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
37#include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
38#include "chrome/common/chrome_switches.h"
[email protected]d69d7b172012-08-09 04:17:2639#include "chrome/common/chrome_version_info.h"
[email protected]31d8f5f22012-04-02 15:22:0840#include "chrome/common/extensions/extension.h"
[email protected]5115ccc2012-06-11 19:47:0741#include "chrome/common/extensions/features/feature.h"
[email protected]31d8f5f22012-04-02 15:22:0842#include "chrome/common/pref_names.h"
43#include "content/public/browser/browser_thread.h"
44
45using content::BrowserThread;
46
[email protected]bd306722012-07-11 20:43:5947namespace extensions {
48
[email protected]31d8f5f22012-04-02 15:22:0849//
50// ExtensionSystem
51//
52
53ExtensionSystem::ExtensionSystem() {
[email protected]d69d7b172012-08-09 04:17:2654 Feature::SetCurrentChannel(chrome::VersionInfo::GetChannel());
[email protected]31d8f5f22012-04-02 15:22:0855}
56
57ExtensionSystem::~ExtensionSystem() {
58}
59
[email protected]749d59a2012-04-05 00:23:2460// static
61ExtensionSystem* ExtensionSystem::Get(Profile* profile) {
62 return ExtensionSystemFactory::GetForProfile(profile);
63}
64
[email protected]31d8f5f22012-04-02 15:22:0865//
66// ExtensionSystemImpl::Shared
67//
68
69ExtensionSystemImpl::Shared::Shared(Profile* profile)
70 : profile_(profile) {
71}
72
73ExtensionSystemImpl::Shared::~Shared() {
74}
75
76void ExtensionSystemImpl::Shared::InitPrefs() {
77 bool extensions_disabled =
78 profile_->GetPrefs()->GetBoolean(prefs::kDisableExtensions) ||
79 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableExtensions);
[email protected]bd306722012-07-11 20:43:5980 extension_prefs_.reset(new ExtensionPrefs(
[email protected]31d8f5f22012-04-02 15:22:0881 profile_->GetPrefs(),
82 profile_->GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
[email protected]ef9bba12012-04-06 16:26:0983 ExtensionPrefValueMapFactory::GetForProfile(profile_)));
[email protected]31d8f5f22012-04-02 15:22:0884 extension_prefs_->Init(extensions_disabled);
[email protected]90e800c2012-06-12 23:11:0085
[email protected]bd306722012-07-11 20:43:5986 state_store_.reset(new StateStore(
[email protected]90e800c2012-06-12 23:11:0087 profile_,
88 profile_->GetPath().AppendASCII(ExtensionService::kStateStoreName)));
[email protected]31d8f5f22012-04-02 15:22:0889}
90
[email protected]65187152012-06-02 13:14:1491void ExtensionSystemImpl::Shared::RegisterManagementPolicyProviders() {
92 DCHECK(extension_prefs_.get());
93 management_policy_->RegisterProvider(extension_prefs_.get());
94}
95
[email protected]31d8f5f22012-04-02 15:22:0896void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) {
97 const CommandLine* command_line = CommandLine::ForCurrentProcess();
98
[email protected]bd306722012-07-11 20:43:5999 lazy_background_task_queue_.reset(new LazyBackgroundTaskQueue(profile_));
[email protected]40404bc2012-07-25 17:40:49100 message_service_.reset(new MessageService(lazy_background_task_queue_.get()));
[email protected]5a38dfd2012-07-23 23:22:10101 extension_event_router_.reset(new EventRouter(profile_));
[email protected]d9ede582012-08-14 19:21:38102 navigation_observer_.reset(new NavigationObserver(profile_));
[email protected]31d8f5f22012-04-02 15:22:08103
104 ExtensionErrorReporter::Init(true); // allow noisy errors.
105
106 user_script_master_ = new UserScriptMaster(profile_);
107
108 bool autoupdate_enabled = true;
109#if defined(OS_CHROMEOS)
110 if (!extensions_enabled)
111 autoupdate_enabled = false;
112 else
113 autoupdate_enabled = !command_line->HasSwitch(switches::kGuestSession);
114#endif
115 extension_service_.reset(new ExtensionService(
116 profile_,
117 CommandLine::ForCurrentProcess(),
118 profile_->GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
119 extension_prefs_.get(),
120 autoupdate_enabled,
121 extensions_enabled));
122
[email protected]d7fbc092012-06-18 22:52:00123 // These services must be registered before the ExtensionService tries to
124 // load any extensions.
125 {
[email protected]bd306722012-07-11 20:43:59126 management_policy_.reset(new ManagementPolicy);
[email protected]d7fbc092012-06-18 22:52:00127 RegisterManagementPolicyProviders();
128 }
[email protected]65187152012-06-02 13:14:14129
[email protected]31d8f5f22012-04-02 15:22:08130 extension_service_->component_loader()->AddDefaultComponentExtensions();
131 if (command_line->HasSwitch(switches::kLoadComponentExtension)) {
132 CommandLine::StringType path_list = command_line->GetSwitchValueNative(
133 switches::kLoadComponentExtension);
134 StringTokenizerT<CommandLine::StringType,
135 CommandLine::StringType::const_iterator> t(path_list,
136 FILE_PATH_LITERAL(","));
137 while (t.GetNext()) {
138 // Load the component extension manifest synchronously.
139 // Blocking the UI thread is acceptable here since
140 // this flag designated for developers.
141 base::ThreadRestrictions::ScopedAllowIO allow_io;
142 extension_service_->component_loader()->AddOrReplace(
143 FilePath(t.token()));
144 }
145 }
146 extension_service_->Init();
147
148 if (extensions_enabled) {
149 // Load any extensions specified with --load-extension.
150 // TODO(yoz): Seems like this should move into ExtensionService::Init.
151 // But maybe it's no longer important.
152 if (command_line->HasSwitch(switches::kLoadExtension)) {
153 CommandLine::StringType path_list = command_line->GetSwitchValueNative(
154 switches::kLoadExtension);
155 StringTokenizerT<CommandLine::StringType,
156 CommandLine::StringType::const_iterator> t(path_list,
157 FILE_PATH_LITERAL(","));
[email protected]bd306722012-07-11 20:43:59158 scoped_refptr<UnpackedInstaller> installer =
159 UnpackedInstaller::Create(extension_service_.get());
[email protected]31d8f5f22012-04-02 15:22:08160 while (t.GetNext()) {
161 installer->LoadFromCommandLine(FilePath(t.token()));
162 }
163 }
164 }
165
166 // Make the chrome://extension-icon/ resource available.
[email protected]ef92e172012-04-25 19:40:41167 ChromeURLDataManager::AddDataSource(profile_,
[email protected]31d8f5f22012-04-02 15:22:08168 new ExtensionIconSource(profile_));
169
170 // Initialize extension event routers. Note that on Chrome OS, this will
171 // not succeed if the user has not logged in yet, in which case the
172 // event routers are initialized in LoginUtilsImpl::CompleteLogin instead.
173 // The InitEventRouters call used to be in BrowserMain, because when bookmark
174 // import happened on first run, the bookmark bar was not being correctly
175 // initialized (see issue 40144). Now that bookmarks aren't imported and
176 // the event routers need to be initialized for every profile individually,
177 // initialize them with the extension service.
178 // If this profile is being created as part of the import process, never
179 // initialize the event routers. If import is going to run in a separate
180 // process (the profile itself is on the main process), wait for import to
181 // finish before initializing the routers.
182 if (!command_line->HasSwitch(switches::kImport) &&
183 !command_line->HasSwitch(switches::kImportFromFile)) {
184 if (g_browser_process->profile_manager()->will_import()) {
185 extension_service_->InitEventRoutersAfterImport();
186 } else {
187 extension_service_->InitEventRouters();
188 }
189 }
190}
191
[email protected]bd306722012-07-11 20:43:59192StateStore* ExtensionSystemImpl::Shared::state_store() {
[email protected]90e800c2012-06-12 23:11:00193 return state_store_.get();
194}
195
[email protected]31d8f5f22012-04-02 15:22:08196ExtensionService* ExtensionSystemImpl::Shared::extension_service() {
197 return extension_service_.get();
198}
199
[email protected]bd306722012-07-11 20:43:59200ManagementPolicy* ExtensionSystemImpl::Shared::management_policy() {
[email protected]65187152012-06-02 13:14:14201 return management_policy_.get();
202}
203
[email protected]31d8f5f22012-04-02 15:22:08204UserScriptMaster* ExtensionSystemImpl::Shared::user_script_master() {
205 return user_script_master_.get();
206}
207
208ExtensionInfoMap* ExtensionSystemImpl::Shared::info_map() {
[email protected]9656bc52012-08-13 17:05:33209 if (!extension_info_map_)
210 extension_info_map_ = new ExtensionInfoMap();
[email protected]31d8f5f22012-04-02 15:22:08211 return extension_info_map_.get();
212}
213
[email protected]bd306722012-07-11 20:43:59214LazyBackgroundTaskQueue*
215 ExtensionSystemImpl::Shared::lazy_background_task_queue() {
[email protected]31d8f5f22012-04-02 15:22:08216 return lazy_background_task_queue_.get();
217}
218
[email protected]40404bc2012-07-25 17:40:49219MessageService* ExtensionSystemImpl::Shared::message_service() {
220 return message_service_.get();
[email protected]31d8f5f22012-04-02 15:22:08221}
222
[email protected]5a38dfd2012-07-23 23:22:10223EventRouter* ExtensionSystemImpl::Shared::event_router() {
[email protected]31d8f5f22012-04-02 15:22:08224 return extension_event_router_.get();
225}
226
227//
228// ExtensionSystemImpl
229//
230
231ExtensionSystemImpl::ExtensionSystemImpl(Profile* profile)
232 : profile_(profile),
233 extension_devtools_manager_(NULL) {
234 shared_ = ExtensionSystemSharedFactory::GetForProfile(profile);
235
236 if (profile->IsOffTheRecord()) {
237 extension_process_manager_.reset(ExtensionProcessManager::Create(profile));
238 } else {
239 shared_->InitPrefs();
240 }
241}
242
243ExtensionSystemImpl::~ExtensionSystemImpl() {
[email protected]3dfa4c02012-07-30 17:21:41244 if (rules_registry_service_.get())
245 rules_registry_service_->Shutdown();
[email protected]31d8f5f22012-04-02 15:22:08246}
247
248void ExtensionSystemImpl::Shutdown() {
249 extension_process_manager_.reset();
250}
251
[email protected]3dfa4c02012-07-30 17:21:41252void ExtensionSystemImpl::InitForRegularProfile(bool extensions_enabled) {
[email protected]31d8f5f22012-04-02 15:22:08253 DCHECK(!profile_->IsOffTheRecord());
254 if (user_script_master() || extension_service())
255 return; // Already initialized.
256
257 const CommandLine* command_line = CommandLine::ForCurrentProcess();
258 if (command_line->HasSwitch(
259 switches::kEnableExtensionTimelineApi)) {
260 extension_devtools_manager_ = new ExtensionDevToolsManager(profile_);
261 }
262
[email protected]9656bc52012-08-13 17:05:33263 // The ExtensionInfoMap needs to be created before the
264 // ExtensionProcessManager.
265 shared_->info_map();
[email protected]31d8f5f22012-04-02 15:22:08266
267 extension_process_manager_.reset(ExtensionProcessManager::Create(profile_));
[email protected]931186e02012-07-20 01:22:06268 alarm_manager_.reset(new AlarmManager(profile_, &base::Time::Now));
269
270 serial_connection_manager_.reset(new ApiResourceManager<SerialConnection>(
271 BrowserThread::FILE));
272 socket_manager_.reset(new ApiResourceManager<Socket>(BrowserThread::IO));
273 usb_device_resource_manager_.reset(
274 new ApiResourceManager<UsbDeviceResource>(BrowserThread::IO));
[email protected]31d8f5f22012-04-02 15:22:08275
[email protected]3dfa4c02012-07-30 17:21:41276 rules_registry_service_.reset(new RulesRegistryService(profile_));
277 rules_registry_service_->RegisterDefaultRulesRegistries();
278
[email protected]31d8f5f22012-04-02 15:22:08279 shared_->Init(extensions_enabled);
280}
281
[email protected]3dfa4c02012-07-30 17:21:41282void ExtensionSystemImpl::InitForOTRProfile() {
283 // Only initialize the RulesRegistryService of the OTR ExtensionSystem if the
284 // regular ExtensionSystem has been initialized properly, as we depend on it.
285 // Some ChromeOS browser tests don't initialize the regular ExtensionSystem
286 // in login-tests.
287 if (extension_service()) {
288 rules_registry_service_.reset(new RulesRegistryService(profile_));
289 rules_registry_service_->RegisterDefaultRulesRegistries();
290 }
291}
292
[email protected]31d8f5f22012-04-02 15:22:08293ExtensionService* ExtensionSystemImpl::extension_service() {
294 return shared_->extension_service();
295}
296
[email protected]bd306722012-07-11 20:43:59297ManagementPolicy* ExtensionSystemImpl::management_policy() {
[email protected]65187152012-06-02 13:14:14298 return shared_->management_policy();
299}
300
[email protected]31d8f5f22012-04-02 15:22:08301UserScriptMaster* ExtensionSystemImpl::user_script_master() {
302 return shared_->user_script_master();
303}
304
305ExtensionDevToolsManager* ExtensionSystemImpl::devtools_manager() {
306 // TODO(mpcomplete): in incognito, figure out whether we should
307 // return the original profile's version.
308 return extension_devtools_manager_.get();
309}
310
311ExtensionProcessManager* ExtensionSystemImpl::process_manager() {
312 return extension_process_manager_.get();
313}
314
[email protected]bd306722012-07-11 20:43:59315AlarmManager* ExtensionSystemImpl::alarm_manager() {
[email protected]ca6df682012-04-10 23:00:20316 return alarm_manager_.get();
317}
318
[email protected]bd306722012-07-11 20:43:59319StateStore* ExtensionSystemImpl::state_store() {
[email protected]90e800c2012-06-12 23:11:00320 return shared_->state_store();
321}
322
[email protected]31d8f5f22012-04-02 15:22:08323ExtensionInfoMap* ExtensionSystemImpl::info_map() {
324 return shared_->info_map();
325}
326
[email protected]bd306722012-07-11 20:43:59327LazyBackgroundTaskQueue* ExtensionSystemImpl::lazy_background_task_queue() {
[email protected]31d8f5f22012-04-02 15:22:08328 return shared_->lazy_background_task_queue();
329}
330
[email protected]40404bc2012-07-25 17:40:49331MessageService* ExtensionSystemImpl::message_service() {
[email protected]31d8f5f22012-04-02 15:22:08332 return shared_->message_service();
333}
334
[email protected]5a38dfd2012-07-23 23:22:10335EventRouter* ExtensionSystemImpl::event_router() {
[email protected]31d8f5f22012-04-02 15:22:08336 return shared_->event_router();
337}
338
[email protected]bd306722012-07-11 20:43:59339RulesRegistryService* ExtensionSystemImpl::rules_registry_service() {
[email protected]3dfa4c02012-07-30 17:21:41340 return rules_registry_service_.get();
[email protected]b813ed72012-04-05 08:21:36341}
342
[email protected]931186e02012-07-20 01:22:06343ApiResourceManager<SerialConnection>*
344ExtensionSystemImpl::serial_connection_manager() {
345 return serial_connection_manager_.get();
346}
347
[email protected]3dfa4c02012-07-30 17:21:41348ApiResourceManager<Socket>* ExtensionSystemImpl::socket_manager() {
[email protected]931186e02012-07-20 01:22:06349 return socket_manager_.get();
350}
351
352ApiResourceManager<UsbDeviceResource>*
353ExtensionSystemImpl::usb_device_resource_manager() {
354 return usb_device_resource_manager_.get();
355}
356
[email protected]31d8f5f22012-04-02 15:22:08357void ExtensionSystemImpl::RegisterExtensionWithRequestContexts(
[email protected]bd306722012-07-11 20:43:59358 const Extension* extension) {
[email protected]31d8f5f22012-04-02 15:22:08359 base::Time install_time;
[email protected]bd306722012-07-11 20:43:59360 if (extension->location() != Extension::COMPONENT) {
[email protected]31d8f5f22012-04-02 15:22:08361 install_time = extension_service()->extension_prefs()->
362 GetInstallTime(extension->id());
363 }
364 bool incognito_enabled =
365 extension_service()->IsIncognitoEnabled(extension->id());
366 BrowserThread::PostTask(
367 BrowserThread::IO, FROM_HERE,
368 base::Bind(&ExtensionInfoMap::AddExtension, info_map(),
369 make_scoped_refptr(extension), install_time,
370 incognito_enabled));
371}
372
373void ExtensionSystemImpl::UnregisterExtensionWithRequestContexts(
374 const std::string& extension_id,
375 const extension_misc::UnloadedExtensionReason reason) {
376 BrowserThread::PostTask(
377 BrowserThread::IO, FROM_HERE,
378 base::Bind(&ExtensionInfoMap::RemoveExtension, info_map(),
379 extension_id, reason));
380}
[email protected]bd306722012-07-11 20:43:59381
382} // namespace extensions