| // Copyright 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 "extensions/renderer/user_script_set_manager.h" |
| |
| #include "components/crx_file/id_util.h" |
| #include "content/public/renderer/render_thread.h" |
| #include "extensions/common/extension_messages.h" |
| #include "extensions/renderer/dispatcher.h" |
| #include "extensions/renderer/script_injection.h" |
| #include "extensions/renderer/user_script_set.h" |
| #include "ipc/ipc_message.h" |
| #include "ipc/ipc_message_macros.h" |
| #include "third_party/WebKit/public/web/WebFrame.h" |
| |
| namespace extensions { |
| |
| UserScriptSetManager::UserScriptSetManager(const ExtensionSet* extensions) |
| : static_scripts_(extensions), extensions_(extensions) { |
| content::RenderThread::Get()->AddObserver(this); |
| } |
| |
| UserScriptSetManager::~UserScriptSetManager() { |
| } |
| |
| void UserScriptSetManager::AddObserver(Observer* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void UserScriptSetManager::RemoveObserver(Observer* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| scoped_ptr<ScriptInjection> |
| UserScriptSetManager::GetInjectionForDeclarativeScript( |
| int script_id, |
| blink::WebFrame* web_frame, |
| int tab_id, |
| const GURL& url, |
| const Extension* extension) { |
| UserScriptSet* user_script_set = |
| GetProgrammaticScriptsByExtension(extension->id()); |
| if (!user_script_set) |
| return scoped_ptr<ScriptInjection>(); |
| |
| return user_script_set->GetDeclarativeScriptInjection( |
| script_id, |
| web_frame, |
| tab_id, |
| UserScript::BROWSER_DRIVEN, |
| url, |
| extension); |
| } |
| |
| bool UserScriptSetManager::OnControlMessageReceived( |
| const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(UserScriptSetManager, message) |
| IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| } |
| |
| void UserScriptSetManager::GetAllInjections( |
| ScopedVector<ScriptInjection>* injections, |
| blink::WebFrame* web_frame, |
| int tab_id, |
| UserScript::RunLocation run_location) { |
| static_scripts_.GetInjections(injections, web_frame, tab_id, run_location); |
| for (UserScriptSetMap::iterator it = programmatic_scripts_.begin(); |
| it != programmatic_scripts_.end(); |
| ++it) { |
| it->second->GetInjections(injections, web_frame, tab_id, run_location); |
| } |
| } |
| |
| void UserScriptSetManager::GetAllActiveExtensionIds( |
| std::set<std::string>* ids) const { |
| DCHECK(ids); |
| static_scripts_.GetActiveExtensionIds(ids); |
| for (UserScriptSetMap::const_iterator it = programmatic_scripts_.begin(); |
| it != programmatic_scripts_.end(); |
| ++it) { |
| it->second->GetActiveExtensionIds(ids); |
| } |
| } |
| |
| UserScriptSet* UserScriptSetManager::GetProgrammaticScriptsByExtension( |
| const ExtensionId& extension_id) { |
| UserScriptSetMap::const_iterator it = |
| programmatic_scripts_.find(extension_id); |
| return it != programmatic_scripts_.end() ? it->second.get() : NULL; |
| } |
| |
| void UserScriptSetManager::OnUpdateUserScripts( |
| base::SharedMemoryHandle shared_memory, |
| const ExtensionId& extension_id, |
| const std::set<std::string>& changed_extensions) { |
| if (!base::SharedMemory::IsHandleValid(shared_memory)) { |
| NOTREACHED() << "Bad scripts handle"; |
| return; |
| } |
| |
| for (std::set<std::string>::const_iterator iter = changed_extensions.begin(); |
| iter != changed_extensions.end(); |
| ++iter) { |
| if (!crx_file::id_util::IdIsValid(*iter)) { |
| NOTREACHED() << "Invalid extension id: " << *iter; |
| return; |
| } |
| } |
| |
| UserScriptSet* scripts = NULL; |
| if (!extension_id.empty()) { |
| // The expectation when there is an extension that "owns" this shared |
| // memory region is that the |changed_extensions| is either the empty list |
| // or just the owner. |
| CHECK(changed_extensions.size() <= 1); |
| if (programmatic_scripts_.find(extension_id) == |
| programmatic_scripts_.end()) { |
| scripts = new UserScriptSet(extensions_); |
| programmatic_scripts_[extension_id] = make_linked_ptr(scripts); |
| } else { |
| scripts = programmatic_scripts_[extension_id].get(); |
| } |
| } else { |
| scripts = &static_scripts_; |
| } |
| DCHECK(scripts); |
| |
| // If no extensions are included in the set, that indicates that all |
| // extensions were updated. Add them all to the set so that observers and |
| // individual UserScriptSets don't need to know this detail. |
| const std::set<std::string>* effective_extensions = &changed_extensions; |
| std::set<std::string> all_extensions; |
| if (changed_extensions.empty()) { |
| // The meaning of "all extensions" varies, depending on whether some |
| // extension "owns" this shared memory region. |
| // No owner => all known extensions. |
| // Owner => just the owner extension. |
| if (extension_id.empty()) |
| all_extensions = extensions_->GetIDs(); |
| else |
| all_extensions.insert(extension_id); |
| effective_extensions = &all_extensions; |
| } |
| |
| if (scripts->UpdateUserScripts(shared_memory, *effective_extensions)) { |
| FOR_EACH_OBSERVER( |
| Observer, |
| observers_, |
| OnUserScriptsUpdated(*effective_extensions, scripts->scripts())); |
| } |
| } |
| |
| } // namespace extensions |