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/programmatic_script_injector.h"
6
7#include <vector>
8
9#include "base/values.h"
10#include "content/public/renderer/render_view.h"
11#include "extensions/common/error_utils.h"
12#include "extensions/common/extension.h"
13#include "extensions/common/extension_messages.h"
14#include "extensions/common/manifest_constants.h"
15#include "extensions/common/permissions/permissions_data.h"
16#include "extensions/renderer/script_context.h"
17#include "third_party/WebKit/public/platform/WebString.h"
18#include "third_party/WebKit/public/web/WebDocument.h"
19#include "third_party/WebKit/public/web/WebFrame.h"
20#include "third_party/WebKit/public/web/WebScriptSource.h"
21
22namespace extensions {
23
24ProgrammaticScriptInjector::ProgrammaticScriptInjector(
25    const ExtensionMsg_ExecuteCode_Params& params,
26    blink::WebFrame* web_frame)
27    : params_(new ExtensionMsg_ExecuteCode_Params(params)),
28      url_(ScriptContext::GetDataSourceURLForFrame(web_frame)),
29      render_view_(content::RenderView::FromWebView(web_frame->view())),
30      results_(new base::ListValue()),
31      finished_(false) {
32}
33
34ProgrammaticScriptInjector::~ProgrammaticScriptInjector() {
35}
36
37UserScript::InjectionType ProgrammaticScriptInjector::script_type()
38    const {
39  return UserScript::PROGRAMMATIC_SCRIPT;
40}
41
42bool ProgrammaticScriptInjector::ShouldExecuteInChildFrames() const {
43  return params_->all_frames;
44}
45
46bool ProgrammaticScriptInjector::ShouldExecuteInMainWorld() const {
47  return params_->in_main_world;
48}
49
50bool ProgrammaticScriptInjector::IsUserGesture() const {
51  return params_->user_gesture;
52}
53
54bool ProgrammaticScriptInjector::ExpectsResults() const {
55  return params_->wants_result;
56}
57
58bool ProgrammaticScriptInjector::ShouldInjectJs(
59    UserScript::RunLocation run_location) const {
60  return GetRunLocation() == run_location && params_->is_javascript;
61}
62
63bool ProgrammaticScriptInjector::ShouldInjectCss(
64    UserScript::RunLocation run_location) const {
65  return GetRunLocation() == run_location && !params_->is_javascript;
66}
67
68PermissionsData::AccessType ProgrammaticScriptInjector::CanExecuteOnFrame(
69    const Extension* extension,
70    blink::WebFrame* frame,
71    int tab_id,
72    const GURL& top_url) const {
73  GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL(
74      frame, frame->document().url(), params_->match_about_blank);
75  if (params_->is_web_view) {
76    return effective_document_url == params_->webview_src
77               ? PermissionsData::ACCESS_ALLOWED
78               : PermissionsData::ACCESS_DENIED;
79  }
80
81  return extension->permissions_data()->GetPageAccess(extension,
82                                                      effective_document_url,
83                                                      top_url,
84                                                      tab_id,
85                                                      -1,  // no process ID.
86                                                      NULL /* ignore error */);
87}
88
89std::vector<blink::WebScriptSource> ProgrammaticScriptInjector::GetJsSources(
90    UserScript::RunLocation run_location) const {
91  DCHECK_EQ(GetRunLocation(), run_location);
92  DCHECK(params_->is_javascript);
93
94  return std::vector<blink::WebScriptSource>(
95      1,
96      blink::WebScriptSource(
97          blink::WebString::fromUTF8(params_->code), params_->file_url));
98}
99
100std::vector<std::string> ProgrammaticScriptInjector::GetCssSources(
101    UserScript::RunLocation run_location) const {
102  DCHECK_EQ(GetRunLocation(), run_location);
103  DCHECK(!params_->is_javascript);
104
105  return std::vector<std::string>(1, params_->code);
106}
107
108void ProgrammaticScriptInjector::OnInjectionComplete(
109    scoped_ptr<base::ListValue> execution_results,
110    ScriptsRunInfo* scripts_run_info,
111    UserScript::RunLocation run_location) {
112  results_ = execution_results.Pass();
113  Finish(std::string());
114}
115
116void ProgrammaticScriptInjector::OnWillNotInject(InjectFailureReason reason) {
117  std::string error;
118  switch (reason) {
119    case NOT_ALLOWED:
120      error = ErrorUtils::FormatErrorMessage(manifest_errors::kCannotAccessPage,
121                                             url_.spec());
122      break;
123    case EXTENSION_REMOVED:  // no special error here.
124    case WONT_INJECT:
125      break;
126  }
127  Finish(error);
128}
129
130UserScript::RunLocation ProgrammaticScriptInjector::GetRunLocation() const {
131  return static_cast<UserScript::RunLocation>(params_->run_at);
132}
133
134void ProgrammaticScriptInjector::Finish(const std::string& error) {
135  DCHECK(!finished_);
136  finished_ = true;
137
138  render_view_->Send(new ExtensionHostMsg_ExecuteCodeFinished(
139      render_view_->GetRoutingID(),
140      params_->request_id,
141      error,
142      url_,
143      *results_));
144}
145
146}  // namespace extensions
147