1 // Copyright 2014 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 "extensions/renderer/user_script_set_manager.h" 6 7 #include "components/crx_file/id_util.h" 8 #include "content/public/renderer/render_thread.h" 9 #include "extensions/common/extension_messages.h" 10 #include "extensions/renderer/dispatcher.h" 11 #include "extensions/renderer/script_injection.h" 12 #include "extensions/renderer/user_script_set.h" 13 #include "ipc/ipc_message.h" 14 #include "ipc/ipc_message_macros.h" 15 #include "third_party/WebKit/public/web/WebFrame.h" 16 17 namespace extensions { 18 19 UserScriptSetManager::UserScriptSetManager(const ExtensionSet* extensions) 20 : static_scripts_(extensions), extensions_(extensions) { 21 content::RenderThread::Get()->AddObserver(this); 22 } 23 24 UserScriptSetManager::~UserScriptSetManager() { 25 } 26 27 void UserScriptSetManager::AddObserver(Observer* observer) { 28 observers_.AddObserver(observer); 29 } 30 31 void UserScriptSetManager::RemoveObserver(Observer* observer) { 32 observers_.RemoveObserver(observer); 33 } 34 35 scoped_ptr<ScriptInjection> 36 UserScriptSetManager::GetInjectionForDeclarativeScript( 37 int script_id, 38 blink::WebFrame* web_frame, 39 int tab_id, 40 const GURL& url, 41 const Extension* extension) { 42 UserScriptSet* user_script_set = 43 GetProgrammaticScriptsByExtension(extension->id()); 44 if (!user_script_set) 45 return scoped_ptr<ScriptInjection>(); 46 47 return user_script_set->GetDeclarativeScriptInjection( 48 script_id, 49 web_frame, 50 tab_id, 51 UserScript::BROWSER_DRIVEN, 52 url, 53 extension); 54 } 55 56 bool UserScriptSetManager::OnControlMessageReceived( 57 const IPC::Message& message) { 58 bool handled = true; 59 IPC_BEGIN_MESSAGE_MAP(UserScriptSetManager, message) 60 IPC_MESSAGE_HANDLER(ExtensionMsg_UpdateUserScripts, OnUpdateUserScripts) 61 IPC_MESSAGE_UNHANDLED(handled = false) 62 IPC_END_MESSAGE_MAP() 63 return handled; 64 } 65 66 void UserScriptSetManager::GetAllInjections( 67 ScopedVector<ScriptInjection>* injections, 68 blink::WebFrame* web_frame, 69 int tab_id, 70 UserScript::RunLocation run_location) { 71 static_scripts_.GetInjections(injections, web_frame, tab_id, run_location); 72 for (UserScriptSetMap::iterator it = programmatic_scripts_.begin(); 73 it != programmatic_scripts_.end(); 74 ++it) { 75 it->second->GetInjections(injections, web_frame, tab_id, run_location); 76 } 77 } 78 79 void UserScriptSetManager::GetAllActiveExtensionIds( 80 std::set<std::string>* ids) const { 81 DCHECK(ids); 82 static_scripts_.GetActiveExtensionIds(ids); 83 for (UserScriptSetMap::const_iterator it = programmatic_scripts_.begin(); 84 it != programmatic_scripts_.end(); 85 ++it) { 86 it->second->GetActiveExtensionIds(ids); 87 } 88 } 89 90 UserScriptSet* UserScriptSetManager::GetProgrammaticScriptsByExtension( 91 const ExtensionId& extension_id) { 92 UserScriptSetMap::const_iterator it = 93 programmatic_scripts_.find(extension_id); 94 return it != programmatic_scripts_.end() ? it->second.get() : NULL; 95 } 96 97 void UserScriptSetManager::OnUpdateUserScripts( 98 base::SharedMemoryHandle shared_memory, 99 const ExtensionId& extension_id, 100 const std::set<std::string>& changed_extensions) { 101 if (!base::SharedMemory::IsHandleValid(shared_memory)) { 102 NOTREACHED() << "Bad scripts handle"; 103 return; 104 } 105 106 for (std::set<std::string>::const_iterator iter = changed_extensions.begin(); 107 iter != changed_extensions.end(); 108 ++iter) { 109 if (!crx_file::id_util::IdIsValid(*iter)) { 110 NOTREACHED() << "Invalid extension id: " << *iter; 111 return; 112 } 113 } 114 115 UserScriptSet* scripts = NULL; 116 if (!extension_id.empty()) { 117 // The expectation when there is an extension that "owns" this shared 118 // memory region is that the |changed_extensions| is either the empty list 119 // or just the owner. 120 CHECK(changed_extensions.size() <= 1); 121 if (programmatic_scripts_.find(extension_id) == 122 programmatic_scripts_.end()) { 123 scripts = new UserScriptSet(extensions_); 124 programmatic_scripts_[extension_id] = make_linked_ptr(scripts); 125 } else { 126 scripts = programmatic_scripts_[extension_id].get(); 127 } 128 } else { 129 scripts = &static_scripts_; 130 } 131 DCHECK(scripts); 132 133 // If no extensions are included in the set, that indicates that all 134 // extensions were updated. Add them all to the set so that observers and 135 // individual UserScriptSets don't need to know this detail. 136 const std::set<std::string>* effective_extensions = &changed_extensions; 137 std::set<std::string> all_extensions; 138 if (changed_extensions.empty()) { 139 // The meaning of "all extensions" varies, depending on whether some 140 // extension "owns" this shared memory region. 141 // No owner => all known extensions. 142 // Owner => just the owner extension. 143 if (extension_id.empty()) 144 all_extensions = extensions_->GetIDs(); 145 else 146 all_extensions.insert(extension_id); 147 effective_extensions = &all_extensions; 148 } 149 150 if (scripts->UpdateUserScripts(shared_memory, *effective_extensions)) { 151 FOR_EACH_OBSERVER( 152 Observer, 153 observers_, 154 OnUserScriptsUpdated(*effective_extensions, scripts->scripts())); 155 } 156 } 157 158 } // namespace extensions 159