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