OLD | NEW |
(Empty) | |
| 1 // 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" |
| 12 #include "chrome/browser/extensions/component_loader.h" |
| 13 #include "chrome/browser/content_settings/cookie_settings.h" |
| 14 #include "chrome/browser/extensions/extension_devtools_manager.h" |
| 15 #include "chrome/browser/extensions/extension_error_reporter.h" |
| 16 #include "chrome/browser/extensions/extension_event_router.h" |
| 17 #include "chrome/browser/extensions/extension_info_map.h" |
| 18 #include "chrome/browser/extensions/extension_message_service.h" |
| 19 #include "chrome/browser/extensions/extension_navigation_observer.h" |
| 20 #include "chrome/browser/extensions/extension_pref_store.h" |
| 21 #include "chrome/browser/extensions/extension_pref_value_map.h" |
| 22 #include "chrome/browser/extensions/extension_process_manager.h" |
| 23 #include "chrome/browser/extensions/extension_service.h" |
| 24 #include "chrome/browser/extensions/extension_system_factory.h" |
| 25 #include "chrome/browser/extensions/unpacked_installer.h" |
| 26 #include "chrome/browser/extensions/user_script_master.h" |
| 27 #include "chrome/browser/profiles/profile.h" |
| 28 #include "chrome/browser/profiles/profile_manager.h" |
| 29 #include "chrome/browser/ui/webui/chrome_url_data_manager.h" |
| 30 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" |
| 31 #include "chrome/common/chrome_switches.h" |
| 32 #include "chrome/common/extensions/extension.h" |
| 33 #include "chrome/common/pref_names.h" |
| 34 #include "content/public/browser/browser_thread.h" |
| 35 |
| 36 using content::BrowserThread; |
| 37 |
| 38 // |
| 39 // ExtensionSystem |
| 40 // |
| 41 |
| 42 ExtensionSystem::ExtensionSystem() { |
| 43 } |
| 44 |
| 45 ExtensionSystem::~ExtensionSystem() { |
| 46 } |
| 47 |
| 48 // |
| 49 // ExtensionSystemImpl::Shared |
| 50 // |
| 51 |
| 52 ExtensionSystemImpl::Shared::Shared(Profile* profile) |
| 53 : profile_(profile) { |
| 54 } |
| 55 |
| 56 ExtensionSystemImpl::Shared::~Shared() { |
| 57 } |
| 58 |
| 59 void ExtensionSystemImpl::Shared::Shutdown() { |
| 60 if (message_service()) |
| 61 message_service()->DestroyingProfile(); |
| 62 } |
| 63 |
| 64 void ExtensionSystemImpl::Shared::InitPrefs() { |
| 65 bool extensions_disabled = |
| 66 profile_->GetPrefs()->GetBoolean(prefs::kDisableExtensions) || |
| 67 CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableExtensions); |
| 68 extension_prefs_.reset(new ExtensionPrefs( |
| 69 profile_->GetPrefs(), |
| 70 profile_->GetPath().AppendASCII(ExtensionService::kInstallDirectoryName), |
| 71 profile_->GetExtensionPrefValueMap())); |
| 72 extension_prefs_->Init(extensions_disabled); |
| 73 } |
| 74 |
| 75 void ExtensionSystemImpl::Shared::InitInfoMap() { |
| 76 // The ExtensionInfoMap needs to be created before the |
| 77 // ExtensionProcessManager. |
| 78 extension_info_map_ = new ExtensionInfoMap(); |
| 79 } |
| 80 |
| 81 void ExtensionSystemImpl::Shared::Init(bool extensions_enabled) { |
| 82 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 83 |
| 84 extension_event_router_.reset(new ExtensionEventRouter(profile_)); |
| 85 extension_message_service_ = new ExtensionMessageService(profile_); |
| 86 extension_navigation_observer_.reset( |
| 87 new ExtensionNavigationObserver(profile_)); |
| 88 |
| 89 ExtensionErrorReporter::Init(true); // allow noisy errors. |
| 90 |
| 91 user_script_master_ = new UserScriptMaster(profile_); |
| 92 |
| 93 bool autoupdate_enabled = true; |
| 94 #if defined(OS_CHROMEOS) |
| 95 if (!extensions_enabled) |
| 96 autoupdate_enabled = false; |
| 97 else |
| 98 autoupdate_enabled = !command_line->HasSwitch(switches::kGuestSession); |
| 99 #endif |
| 100 extension_service_.reset(new ExtensionService( |
| 101 profile_, |
| 102 CommandLine::ForCurrentProcess(), |
| 103 profile_->GetPath().AppendASCII(ExtensionService::kInstallDirectoryName), |
| 104 extension_prefs_.get(), |
| 105 autoupdate_enabled, |
| 106 extensions_enabled)); |
| 107 |
| 108 extension_service_->component_loader()->AddDefaultComponentExtensions(); |
| 109 if (command_line->HasSwitch(switches::kLoadComponentExtension)) { |
| 110 CommandLine::StringType path_list = command_line->GetSwitchValueNative( |
| 111 switches::kLoadComponentExtension); |
| 112 StringTokenizerT<CommandLine::StringType, |
| 113 CommandLine::StringType::const_iterator> t(path_list, |
| 114 FILE_PATH_LITERAL(",")); |
| 115 while (t.GetNext()) { |
| 116 // Load the component extension manifest synchronously. |
| 117 // Blocking the UI thread is acceptable here since |
| 118 // this flag designated for developers. |
| 119 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 120 extension_service_->component_loader()->AddOrReplace( |
| 121 FilePath(t.token())); |
| 122 } |
| 123 } |
| 124 extension_service_->Init(); |
| 125 |
| 126 if (extensions_enabled) { |
| 127 // Load any extensions specified with --load-extension. |
| 128 // TODO(yoz): Seems like this should move into ExtensionService::Init. |
| 129 // But maybe it's no longer important. |
| 130 if (command_line->HasSwitch(switches::kLoadExtension)) { |
| 131 CommandLine::StringType path_list = command_line->GetSwitchValueNative( |
| 132 switches::kLoadExtension); |
| 133 StringTokenizerT<CommandLine::StringType, |
| 134 CommandLine::StringType::const_iterator> t(path_list, |
| 135 FILE_PATH_LITERAL(",")); |
| 136 scoped_refptr<extensions::UnpackedInstaller> installer = |
| 137 extensions::UnpackedInstaller::Create(extension_service_.get()); |
| 138 while (t.GetNext()) { |
| 139 installer->LoadFromCommandLine(FilePath(t.token())); |
| 140 } |
| 141 } |
| 142 } |
| 143 |
| 144 // Make the chrome://extension-icon/ resource available. |
| 145 profile_->GetChromeURLDataManager()->AddDataSource( |
| 146 new ExtensionIconSource(profile_)); |
| 147 |
| 148 // Initialize extension event routers. Note that on Chrome OS, this will |
| 149 // not succeed if the user has not logged in yet, in which case the |
| 150 // event routers are initialized in LoginUtilsImpl::CompleteLogin instead. |
| 151 // The InitEventRouters call used to be in BrowserMain, because when bookmark |
| 152 // import happened on first run, the bookmark bar was not being correctly |
| 153 // initialized (see issue 40144). Now that bookmarks aren't imported and |
| 154 // the event routers need to be initialized for every profile individually, |
| 155 // initialize them with the extension service. |
| 156 // If this profile is being created as part of the import process, never |
| 157 // initialize the event routers. If import is going to run in a separate |
| 158 // process (the profile itself is on the main process), wait for import to |
| 159 // finish before initializing the routers. |
| 160 if (!command_line->HasSwitch(switches::kImport) && |
| 161 !command_line->HasSwitch(switches::kImportFromFile)) { |
| 162 if (g_browser_process->profile_manager()->will_import()) { |
| 163 extension_service_->InitEventRoutersAfterImport(); |
| 164 } else { |
| 165 extension_service_->InitEventRouters(); |
| 166 } |
| 167 } |
| 168 } |
| 169 |
| 170 ExtensionService* ExtensionSystemImpl::Shared::extension_service() { |
| 171 return extension_service_.get(); |
| 172 } |
| 173 |
| 174 UserScriptMaster* ExtensionSystemImpl::Shared::user_script_master() { |
| 175 return user_script_master_.get(); |
| 176 } |
| 177 |
| 178 ExtensionInfoMap* ExtensionSystemImpl::Shared::info_map() { |
| 179 return extension_info_map_.get(); |
| 180 } |
| 181 |
| 182 ExtensionMessageService* ExtensionSystemImpl::Shared::message_service() { |
| 183 return extension_message_service_.get(); |
| 184 } |
| 185 |
| 186 ExtensionEventRouter* ExtensionSystemImpl::Shared::event_router() { |
| 187 return extension_event_router_.get(); |
| 188 } |
| 189 |
| 190 // |
| 191 // ExtensionSystemImpl |
| 192 // |
| 193 |
| 194 ExtensionSystemImpl::ExtensionSystemImpl(Profile* profile) |
| 195 : profile_(profile), |
| 196 extension_devtools_manager_(NULL) { |
| 197 shared_ = ExtensionSystemSharedFactory::GetForProfile(profile); |
| 198 |
| 199 if (profile->IsOffTheRecord()) { |
| 200 extension_process_manager_.reset(ExtensionProcessManager::Create(profile)); |
| 201 } else { |
| 202 shared_->InitPrefs(); |
| 203 } |
| 204 } |
| 205 |
| 206 ExtensionSystemImpl::~ExtensionSystemImpl() { |
| 207 } |
| 208 |
| 209 void ExtensionSystemImpl::Shutdown() { |
| 210 extension_process_manager_.reset(); |
| 211 } |
| 212 |
| 213 void ExtensionSystemImpl::Init(bool extensions_enabled) { |
| 214 DCHECK(!profile_->IsOffTheRecord()); |
| 215 if (user_script_master() || extension_service()) |
| 216 return; // Already initialized. |
| 217 |
| 218 const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 219 if (command_line->HasSwitch( |
| 220 switches::kEnableExtensionTimelineApi)) { |
| 221 extension_devtools_manager_ = new ExtensionDevToolsManager(profile_); |
| 222 } |
| 223 |
| 224 shared_->InitInfoMap(); |
| 225 |
| 226 extension_process_manager_.reset(ExtensionProcessManager::Create(profile_)); |
| 227 |
| 228 shared_->Init(extensions_enabled); |
| 229 } |
| 230 |
| 231 ExtensionService* ExtensionSystemImpl::extension_service() { |
| 232 return shared_->extension_service(); |
| 233 } |
| 234 |
| 235 UserScriptMaster* ExtensionSystemImpl::user_script_master() { |
| 236 return shared_->user_script_master(); |
| 237 } |
| 238 |
| 239 ExtensionDevToolsManager* ExtensionSystemImpl::devtools_manager() { |
| 240 // TODO(mpcomplete): in incognito, figure out whether we should |
| 241 // return the original profile's version. |
| 242 return extension_devtools_manager_.get(); |
| 243 } |
| 244 |
| 245 ExtensionProcessManager* ExtensionSystemImpl::process_manager() { |
| 246 return extension_process_manager_.get(); |
| 247 } |
| 248 |
| 249 ExtensionInfoMap* ExtensionSystemImpl::info_map() { |
| 250 return shared_->info_map(); |
| 251 } |
| 252 |
| 253 ExtensionMessageService* ExtensionSystemImpl::message_service() { |
| 254 return shared_->message_service(); |
| 255 } |
| 256 |
| 257 ExtensionEventRouter* ExtensionSystemImpl::event_router() { |
| 258 return shared_->event_router(); |
| 259 } |
| 260 |
| 261 void ExtensionSystemImpl::RegisterExtensionWithRequestContexts( |
| 262 const Extension* extension) { |
| 263 base::Time install_time; |
| 264 if (extension->location() != Extension::COMPONENT) { |
| 265 install_time = extension_service()->extension_prefs()-> |
| 266 GetInstallTime(extension->id()); |
| 267 } |
| 268 bool incognito_enabled = |
| 269 extension_service()->IsIncognitoEnabled(extension->id()); |
| 270 BrowserThread::PostTask( |
| 271 BrowserThread::IO, FROM_HERE, |
| 272 base::Bind(&ExtensionInfoMap::AddExtension, info_map(), |
| 273 make_scoped_refptr(extension), install_time, |
| 274 incognito_enabled)); |
| 275 } |
| 276 |
| 277 void ExtensionSystemImpl::UnregisterExtensionWithRequestContexts( |
| 278 const std::string& extension_id, |
| 279 const extension_misc::UnloadedExtensionReason reason) { |
| 280 BrowserThread::PostTask( |
| 281 BrowserThread::IO, FROM_HERE, |
| 282 base::Bind(&ExtensionInfoMap::RemoveExtension, info_map(), |
| 283 extension_id, reason)); |
| 284 } |
OLD | NEW |