1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file. 4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/user_script_set.h" 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/common/url_constants.h" 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "content/public/renderer/render_thread.h" 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension.h" 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/extension_set.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/permissions/permissions_data.h" 12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/extensions_renderer_client.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/script_context.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/script_injection.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/renderer/user_script_injector.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/web/WebDocument.h" 17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/WebKit/public/web/WebFrame.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "url/gurl.h" 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace extensions { 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace { 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 24116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGURL GetDocumentUrlForFrame(blink::WebFrame* frame) { 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL data_source_url = ScriptContext::GetDataSourceURLForFrame(frame); 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!data_source_url.is_empty() && frame->isViewSourceModeEnabled()) { 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch data_source_url = GURL(content::kViewSourceScheme + std::string(":") + 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch data_source_url.spec()); 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return data_source_url; 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 36116680a4aac90f2aa7413d9095a592090648e557Ben MurdochUserScriptSet::UserScriptSet(const ExtensionSet* extensions) 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch : extensions_(extensions) { 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 40116680a4aac90f2aa7413d9095a592090648e557Ben MurdochUserScriptSet::~UserScriptSet() { 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserScriptSet::AddObserver(Observer* observer) { 44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch observers_.AddObserver(observer); 45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserScriptSet::RemoveObserver(Observer* observer) { 48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch observers_.RemoveObserver(observer); 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserScriptSet::GetActiveExtensionIds( 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::set<std::string>* ids) const { 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != scripts_.end(); 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter) { 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!(*iter)->extension_id().empty()); 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ids->insert((*iter)->extension_id()); 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid UserScriptSet::GetInjections( 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ScopedVector<ScriptInjection>* injections, 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebFrame* web_frame, 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int tab_id, 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UserScript::RunLocation run_location) { 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL document_url = GetDocumentUrlForFrame(web_frame); 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (ScopedVector<UserScript>::const_iterator iter = scripts_.begin(); 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch iter != scripts_.end(); 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++iter) { 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Extension* extension = extensions_->GetByID((*iter)->extension_id()); 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!extension) 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch continue; 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjection> injection = GetInjectionForScript( 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci *iter, 751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame, 761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_id, 771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci run_location, 781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci document_url, 791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension, 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci false /* is_declarative */); 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (injection.get()) 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch injections->push_back(injection.release()); 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UserScriptSet::UpdateUserScripts( 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::SharedMemoryHandle shared_memory, 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::set<std::string>& changed_extensions) { 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool only_inject_incognito = 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ExtensionsRendererClient::Get()->IsIncognitoProcess(); 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Create the shared memory object (read only). 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch shared_memory_.reset(new base::SharedMemory(shared_memory, true)); 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!shared_memory_.get()) 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // First get the size of the memory block. 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!shared_memory_->Map(sizeof(Pickle::Header))) 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Pickle::Header* pickle_header = 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reinterpret_cast<Pickle::Header*>(shared_memory_->memory()); 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Now map in the rest of the block. 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int pickle_size = sizeof(Pickle::Header) + pickle_header->payload_size; 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch shared_memory_->Unmap(); 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!shared_memory_->Map(pickle_size)) 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return false; 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Unpickle scripts. 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint64 num_scripts = 0; 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Pickle pickle(reinterpret_cast<char*>(shared_memory_->memory()), pickle_size); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PickleIterator iter(pickle); 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(pickle.ReadUInt64(&iter, &num_scripts)); 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scripts_.clear(); 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scripts_.reserve(num_scripts); 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (uint64 i = 0; i < num_scripts; ++i) { 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<UserScript> script(new UserScript()); 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch script->Unpickle(pickle, &iter); 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Note that this is a pointer into shared memory. We don't own it. It gets 122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // cleared up when the last renderer or browser process drops their 123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // reference to the shared memory. 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t j = 0; j < script->js_scripts().size(); ++j) { 125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char* body = NULL; 126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int body_length = 0; 127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(pickle.ReadData(&iter, &body, &body_length)); 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch script->js_scripts()[j].set_external_content( 129116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringPiece(body, body_length)); 130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t j = 0; j < script->css_scripts().size(); ++j) { 132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const char* body = NULL; 133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int body_length = 0; 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(pickle.ReadData(&iter, &body, &body_length)); 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch script->css_scripts()[j].set_external_content( 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::StringPiece(body, body_length)); 137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (only_inject_incognito && !script->is_incognito_enabled()) 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch continue; // This script shouldn't run in an incognito tab. 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scripts_.push_back(script.release()); 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(Observer, 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnUserScriptsUpdated(changed_extensions, scripts_.get())); 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return true; 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciscoped_ptr<ScriptInjection> UserScriptSet::GetDeclarativeScriptInjection( 1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int script_id, 1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci blink::WebFrame* web_frame, 1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int tab_id, 1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UserScript::RunLocation run_location, 1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const GURL& document_url, 1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension) { 1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (ScopedVector<UserScript>::const_iterator it = scripts_.begin(); 1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci it != scripts_.end(); 1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++it) { 1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((*it)->id() == script_id) { 1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetInjectionForScript(*it, 1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame, 1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci tab_id, 1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci run_location, 1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci document_url, 1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extension, 1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci true /* is_declarative */); 1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return scoped_ptr<ScriptInjection>(); 1721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// TODO(dcheng): Scripts can't be injected on a remote frame, so this function 1751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// signature needs to be updated. 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdochscoped_ptr<ScriptInjection> UserScriptSet::GetInjectionForScript( 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UserScript* script, 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch blink::WebFrame* web_frame, 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int tab_id, 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch UserScript::RunLocation run_location, 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const GURL& document_url, 1821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension, 1831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool is_declarative) { 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<ScriptInjection> injection; 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (web_frame->parent() && !script->match_all_frames()) 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return injection.Pass(); // Only match subframes if the script declared it. 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch web_frame, document_url, script->match_about_blank()); 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!script->MatchesURL(effective_document_url)) 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return injection.Pass(); 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ScriptInjector> injector(new UserScriptInjector(script, 1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this, 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci is_declarative)); 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (injector->CanExecuteOnFrame( 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension, 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame, 200116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch -1, // Content scripts are not tab-specific. 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame->top()->document().url()) == 2021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PermissionsData::ACCESS_DENIED) { 203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return injection.Pass(); 204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool inject_css = !script->css_scripts().empty() && 207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch run_location == UserScript::DOCUMENT_START; 208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool inject_js = 209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch !script->js_scripts().empty() && script->run_location() == run_location; 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (inject_css || inject_js) { 211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch injection.reset(new ScriptInjection( 2121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci injector.Pass(), 2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci web_frame->toWebLocalFrame(), 214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension->id(), 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch run_location, 216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch tab_id)); 217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return injection.Pass(); 219116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 220116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 221116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} // namespace extensions 222