Chromium Code Reviews| Index: chrome/browser/extensions/shared_user_script_master.cc |
| diff --git a/chrome/browser/extensions/shared_user_script_master.cc b/chrome/browser/extensions/shared_user_script_master.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d6419d7dfbdf75bbc7a42c61029dd4c5150a6534 |
| --- /dev/null |
| +++ b/chrome/browser/extensions/shared_user_script_master.cc |
| @@ -0,0 +1,156 @@ |
| +// Copyright (c) 2014 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/shared_user_script_master.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/memory/shared_memory.h" |
| +#include "chrome/browser/chrome_notification_types.h" |
| +#include "chrome/browser/extensions/extension_util.h" |
| +#include "chrome/browser/profiles/profile.h" |
| +#include "chrome/common/extensions/api/i18n/default_locale_handler.h" |
| +#include "chrome/common/extensions/manifest_handlers/content_scripts_handler.h" |
| +#include "content/public/browser/notification_service.h" |
| +#include "content/public/browser/render_process_host.h" |
| +#include "extensions/browser/content_verifier.h" |
| +#include "extensions/browser/extension_system.h" |
| + |
| +namespace extensions { |
| + |
| +SharedUserScriptMaster::SharedUserScriptMaster(Profile* profile) |
| + : UserScriptMaster(profile), extension_registry_observer_(this) { |
| + extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
| + registrar_.Add(this, |
| + chrome::NOTIFICATION_EXTENSIONS_READY, |
| + content::Source<Profile>(profile_)); |
| + registrar_.Add(this, |
| + content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| + content::NotificationService::AllBrowserContextsAndSources()); |
| +} |
| + |
| +SharedUserScriptMaster::~SharedUserScriptMaster() { |
| +} |
| + |
| +void SharedUserScriptMaster::OnExtensionLoaded( |
| + content::BrowserContext* browser_context, |
| + const Extension* extension) { |
| + added_extensions_.insert(extension->id()); |
| + removed_extensions_.erase(extension->id()); |
| + extensions_info_[extension->id()] = |
| + ExtensionSet::ExtensionPathAndDefaultLocale( |
| + extension->path(), LocaleInfo::GetDefaultLocale(extension)); |
| + if (extensions_service_ready_) { |
| + changed_extensions_.insert(extension->id()); |
| + if (is_loading()) |
| + pending_load_ = true; |
| + else |
| + StartLoad(); |
| + } |
| +} |
| + |
| +void SharedUserScriptMaster::OnExtensionUnloaded( |
| + content::BrowserContext* browser_context, |
| + const Extension* extension, |
| + UnloadedExtensionInfo::Reason reason) { |
| + removed_extensions_.insert(extension->id()); |
| + added_extensions_.erase(extension->id()); |
| + // Remove any content scripts. |
| + extensions_info_.erase(extension->id()); |
| + changed_extensions_.insert(extension->id()); |
| + if (is_loading()) |
| + pending_load_ = true; |
| + else |
| + StartLoad(); |
| +} |
| + |
| +void SharedUserScriptMaster::Observe( |
| + int type, |
| + const content::NotificationSource& source, |
| + const content::NotificationDetails& details) { |
| + bool should_start_load = false; |
| + switch (type) { |
| + case chrome::NOTIFICATION_EXTENSIONS_READY: |
| + extensions_service_ready_ = true; |
| + should_start_load = true; |
| + break; |
| + case content::NOTIFICATION_RENDERER_PROCESS_CREATED: { |
| + content::RenderProcessHost* process = |
| + content::Source<content::RenderProcessHost>(source).ptr(); |
| + Profile* profile = |
| + Profile::FromBrowserContext(process->GetBrowserContext()); |
| + if (!profile_->IsSameProfile(profile)) |
| + return; |
| + if (ScriptsReady()) { |
| + SendUpdate(process, |
|
Devlin
2014/07/30 21:20:38
(This comment is in a random spot)
To me, this wh
|
| + GetSharedMemory(), |
| + std::set<std::string>()); // Include all extensions. |
| + } |
| + break; |
| + } |
| + default: |
| + DCHECK(false); |
| + } |
| + |
| + if (should_start_load) { |
| + if (is_loading()) |
| + pending_load_ = true; |
| + else |
| + StartLoad(); |
| + } |
| +} |
| + |
| +void SharedUserScriptMaster::StartLoad() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + DCHECK(!is_loading()); |
| + |
| + // Remove any user scripts belonging to any extension that was updated or |
| + // removed. |
| + for (UserScriptList::iterator iter = user_scripts_->begin(); |
| + iter != user_scripts_->end();) { |
| + if (removed_extensions_.count(iter->extension_id()) > 0 || |
| + added_extensions_.count(iter->extension_id()) > 0) { |
| + iter = user_scripts_->erase(iter); |
| + } else { |
| + ++iter; |
| + } |
| + } |
| + |
| + // Add any content scripts for extensions that were recently loaded. |
| + const ExtensionSet& enabled_extensions = |
| + ExtensionRegistry::Get(profile_)->enabled_extensions(); |
| + for (std::set<std::string>::const_iterator iter = added_extensions_.begin(); |
| + iter != added_extensions_.end(); |
| + ++iter) { |
| + const Extension* extension = enabled_extensions.GetByID(*iter); |
| + if (!extension) |
| + continue; |
| + bool incognito_enabled = |
| + util::IsIncognitoEnabled(extension->id(), profile_); |
| + const UserScriptList& scripts = |
| + ContentScriptsInfo::GetContentScripts(extension); |
| + for (UserScriptList::const_iterator script = scripts.begin(); |
| + script != scripts.end(); |
| + ++script) { |
| + user_scripts_->push_back(*script); |
| + user_scripts_->back().set_incognito_enabled(incognito_enabled); |
| + } |
| + } |
| + |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::FILE, |
| + FROM_HERE, |
| + base::Bind(&UserScriptMaster::LoadScriptsOnFileThread, |
| + base::Passed(&user_scripts_), |
| + extensions_info_, |
| + added_extensions_, |
| + make_scoped_refptr( |
| + ExtensionSystem::Get(profile_)->content_verifier()), |
| + base::Bind(&UserScriptMaster::OnScriptsLoaded, |
| + weak_factory_.GetWeakPtr()))); |
| + added_extensions_.clear(); |
| + removed_extensions_.clear(); |
| + user_scripts_.reset(NULL); |
| +} |
| + |
| +} // namespace extensions |