| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/renderer/user_script_injector.h" | 5 #include "extensions/renderer/user_script_injector.h" |
| 6 | 6 |
| 7 #include <tuple> | 7 #include <tuple> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 11 #include "content/public/common/url_constants.h" | 11 #include "content/public/common/url_constants.h" |
| 12 #include "content/public/renderer/render_thread.h" | 12 #include "content/public/renderer/render_thread.h" |
| 13 #include "content/public/renderer/render_frame.h" | 13 #include "content/public/renderer/render_frame.h" |
| 14 #include "content/public/renderer/render_view.h" | 14 #include "content/public/renderer/render_view.h" |
| 15 #include "extensions/common/extension.h" | 15 #include "extensions/common/extension.h" |
| 16 #include "extensions/common/guest_view/extensions_guest_view_messages.h" | 16 #include "extensions/common/guest_view/extensions_guest_view_messages.h" |
| 17 #include "extensions/common/permissions/permissions_data.h" | 17 #include "extensions/common/permissions/permissions_data.h" |
| 18 #include "extensions/renderer/injection_host.h" | 18 #include "extensions/renderer/injection_host.h" |
| 19 #include "extensions/renderer/script_context.h" | 19 #include "extensions/renderer/script_context.h" |
| 20 #include "extensions/renderer/scripts_run_info.h" | 20 #include "extensions/renderer/scripts_run_info.h" |
| 21 #include "grit/extensions_renderer_resources.h" | |
| 22 #include "third_party/WebKit/public/web/WebDocument.h" | 21 #include "third_party/WebKit/public/web/WebDocument.h" |
| 23 #include "third_party/WebKit/public/web/WebLocalFrame.h" | 22 #include "third_party/WebKit/public/web/WebLocalFrame.h" |
| 24 #include "third_party/WebKit/public/web/WebScriptSource.h" | 23 #include "third_party/WebKit/public/web/WebScriptSource.h" |
| 25 #include "ui/base/resource/resource_bundle.h" | |
| 26 #include "url/gurl.h" | 24 #include "url/gurl.h" |
| 27 | 25 |
| 28 namespace extensions { | 26 namespace extensions { |
| 29 | 27 |
| 30 namespace { | 28 namespace { |
| 31 | 29 |
| 32 struct RoutingInfoKey { | 30 struct RoutingInfoKey { |
| 33 int routing_id; | 31 int routing_id; |
| 34 int script_id; | 32 int script_id; |
| 35 | 33 |
| 36 RoutingInfoKey(int routing_id, int script_id) | 34 RoutingInfoKey(int routing_id, int script_id) |
| 37 : routing_id(routing_id), script_id(script_id) {} | 35 : routing_id(routing_id), script_id(script_id) {} |
| 38 | 36 |
| 39 bool operator<(const RoutingInfoKey& other) const { | 37 bool operator<(const RoutingInfoKey& other) const { |
| 40 return std::tie(routing_id, script_id) < | 38 return std::tie(routing_id, script_id) < |
| 41 std::tie(other.routing_id, other.script_id); | 39 std::tie(other.routing_id, other.script_id); |
| 42 } | 40 } |
| 43 }; | 41 }; |
| 44 | 42 |
| 45 using RoutingInfoMap = std::map<RoutingInfoKey, bool>; | 43 using RoutingInfoMap = std::map<RoutingInfoKey, bool>; |
| 46 | 44 |
| 47 // These two strings are injected before and after the Greasemonkey API and | |
| 48 // user script to wrap it in an anonymous scope. | |
| 49 const char kUserScriptHead[] = "(function (unsafeWindow) {\n"; | |
| 50 const char kUserScriptTail[] = "\n})(window);"; | |
| 51 | |
| 52 // A map records whether a given |script_id| from a webview-added user script | 45 // A map records whether a given |script_id| from a webview-added user script |
| 53 // is allowed to inject on the render of given |routing_id|. | 46 // is allowed to inject on the render of given |routing_id|. |
| 54 // Once a script is added, the decision of whether or not allowed to inject | 47 // Once a script is added, the decision of whether or not allowed to inject |
| 55 // won't be changed. | 48 // won't be changed. |
| 56 // After removed by the webview, the user scipt will also be removed | 49 // After removed by the webview, the user scipt will also be removed |
| 57 // from the render. Therefore, there won't be any query from the same | 50 // from the render. Therefore, there won't be any query from the same |
| 58 // |script_id| and |routing_id| pair. | 51 // |script_id| and |routing_id| pair. |
| 59 base::LazyInstance<RoutingInfoMap> g_routing_info_map = | 52 base::LazyInstance<RoutingInfoMap> g_routing_info_map = |
| 60 LAZY_INSTANCE_INITIALIZER; | 53 LAZY_INSTANCE_INITIALIZER; |
| 61 | 54 |
| 62 // Greasemonkey API source that is injected with the scripts. | |
| 63 struct GreasemonkeyApiJsString { | |
| 64 GreasemonkeyApiJsString(); | |
| 65 blink::WebScriptSource GetSource() const; | |
| 66 | |
| 67 private: | |
| 68 blink::WebString source_; | |
| 69 }; | |
| 70 | |
| 71 // The below constructor, monstrous as it is, just makes a WebScriptSource from | |
| 72 // the GreasemonkeyApiJs resource. | |
| 73 GreasemonkeyApiJsString::GreasemonkeyApiJsString() { | |
| 74 base::StringPiece source_piece = | |
| 75 ResourceBundle::GetSharedInstance().GetRawDataResource( | |
| 76 IDR_GREASEMONKEY_API_JS); | |
| 77 source_ = | |
| 78 blink::WebString::fromUTF8(source_piece.data(), source_piece.length()); | |
| 79 } | |
| 80 | |
| 81 blink::WebScriptSource GreasemonkeyApiJsString::GetSource() const { | |
| 82 return blink::WebScriptSource(source_); | |
| 83 } | |
| 84 | |
| 85 base::LazyInstance<GreasemonkeyApiJsString> g_greasemonkey_api = | |
| 86 LAZY_INSTANCE_INITIALIZER; | |
| 87 | |
| 88 } // namespace | 55 } // namespace |
| 89 | 56 |
| 90 UserScriptInjector::UserScriptInjector(const UserScript* script, | 57 UserScriptInjector::UserScriptInjector(const UserScript* script, |
| 91 UserScriptSet* script_list, | 58 UserScriptSet* script_list, |
| 92 bool is_declarative) | 59 bool is_declarative) |
| 93 : script_(script), | 60 : script_(script), |
| 61 user_script_set_(script_list), |
| 94 script_id_(script_->id()), | 62 script_id_(script_->id()), |
| 95 host_id_(script_->host_id()), | 63 host_id_(script_->host_id()), |
| 96 is_declarative_(is_declarative), | 64 is_declarative_(is_declarative), |
| 97 user_script_set_observer_(this) { | 65 user_script_set_observer_(this) { |
| 98 user_script_set_observer_.Add(script_list); | 66 user_script_set_observer_.Add(script_list); |
| 99 } | 67 } |
| 100 | 68 |
| 101 UserScriptInjector::~UserScriptInjector() { | 69 UserScriptInjector::~UserScriptInjector() { |
| 102 } | 70 } |
| 103 | 71 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 196 is_declarative_); | 164 is_declarative_); |
| 197 } | 165 } |
| 198 | 166 |
| 199 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( | 167 std::vector<blink::WebScriptSource> UserScriptInjector::GetJsSources( |
| 200 UserScript::RunLocation run_location) const { | 168 UserScript::RunLocation run_location) const { |
| 201 std::vector<blink::WebScriptSource> sources; | 169 std::vector<blink::WebScriptSource> sources; |
| 202 if (!script_) | 170 if (!script_) |
| 203 return sources; | 171 return sources; |
| 204 | 172 |
| 205 DCHECK_EQ(script_->run_location(), run_location); | 173 DCHECK_EQ(script_->run_location(), run_location); |
| 206 | 174 return user_script_set_->GetJsSources(script_->id()); |
| 207 const UserScript::FileList& js_scripts = script_->js_scripts(); | |
| 208 sources.reserve(js_scripts.size()); | |
| 209 for (const std::unique_ptr<UserScript::File>& file : js_scripts) { | |
| 210 base::StringPiece script_content = file->GetContent(); | |
| 211 blink::WebString source; | |
| 212 if (script_->emulate_greasemonkey()) { | |
| 213 // We add this dumb function wrapper for user scripts to emulate what | |
| 214 // Greasemonkey does. |script_content| becomes: | |
| 215 // concat(kUserScriptHead, script_content, kUserScriptTail). | |
| 216 std::string content; | |
| 217 content.reserve(strlen(kUserScriptHead) + script_content.length() + | |
| 218 strlen(kUserScriptTail)); | |
| 219 content.append(kUserScriptHead); | |
| 220 script_content.AppendToString(&content); | |
| 221 content.append(kUserScriptTail); | |
| 222 // TODO(lazyboy): |content| is copied to |source|, should be avoided. | |
| 223 // Investigate if we can leverage WebString's cheap copying mechanism | |
| 224 // somehow. | |
| 225 source = blink::WebString::fromUTF8(content); | |
| 226 } else { | |
| 227 source = blink::WebString::fromUTF8(script_content.data(), | |
| 228 script_content.length()); | |
| 229 } | |
| 230 sources.push_back(blink::WebScriptSource(source, file->url())); | |
| 231 } | |
| 232 | |
| 233 // Emulate Greasemonkey API for scripts that were converted to extension | |
| 234 // user scripts. | |
| 235 if (script_->emulate_greasemonkey()) | |
| 236 sources.insert(sources.begin(), g_greasemonkey_api.Get().GetSource()); | |
| 237 | |
| 238 return sources; | |
| 239 } | 175 } |
| 240 | 176 |
| 241 std::vector<blink::WebString> UserScriptInjector::GetCssSources( | 177 std::vector<blink::WebString> UserScriptInjector::GetCssSources( |
| 242 UserScript::RunLocation run_location) const { | 178 UserScript::RunLocation run_location) const { |
| 243 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); | 179 DCHECK_EQ(UserScript::DOCUMENT_START, run_location); |
| 244 | 180 |
| 245 std::vector<blink::WebString> sources; | |
| 246 if (!script_) | 181 if (!script_) |
| 247 return sources; | 182 return std::vector<blink::WebString>(); |
| 248 | 183 |
| 249 const UserScript::FileList& css_scripts = script_->css_scripts(); | 184 return user_script_set_->GetCssSources(script_->id()); |
| 250 sources.reserve(css_scripts.size()); | |
| 251 for (const std::unique_ptr<UserScript::File>& file : script_->css_scripts()) { | |
| 252 // TODO(lazyboy): |css_content| string is copied into blink::WebString for | |
| 253 // every frame in the current renderer process. Avoid the copy, possibly by | |
| 254 // only performing the copy once. | |
| 255 base::StringPiece css_content = file->GetContent(); | |
| 256 sources.push_back( | |
| 257 blink::WebString::fromUTF8(css_content.data(), css_content.length())); | |
| 258 } | |
| 259 return sources; | |
| 260 } | 185 } |
| 261 | 186 |
| 262 void UserScriptInjector::GetRunInfo( | 187 void UserScriptInjector::GetRunInfo( |
| 263 ScriptsRunInfo* scripts_run_info, | 188 ScriptsRunInfo* scripts_run_info, |
| 264 UserScript::RunLocation run_location) const { | 189 UserScript::RunLocation run_location) const { |
| 265 if (!script_) | 190 if (!script_) |
| 266 return; | 191 return; |
| 267 | 192 |
| 268 if (ShouldInjectJs(run_location)) { | 193 if (ShouldInjectJs(run_location)) { |
| 269 const UserScript::FileList& js_scripts = script_->js_scripts(); | 194 const UserScript::FileList& js_scripts = script_->js_scripts(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 281 void UserScriptInjector::OnInjectionComplete( | 206 void UserScriptInjector::OnInjectionComplete( |
| 282 std::unique_ptr<base::Value> execution_result, | 207 std::unique_ptr<base::Value> execution_result, |
| 283 UserScript::RunLocation run_location, | 208 UserScript::RunLocation run_location, |
| 284 content::RenderFrame* render_frame) {} | 209 content::RenderFrame* render_frame) {} |
| 285 | 210 |
| 286 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, | 211 void UserScriptInjector::OnWillNotInject(InjectFailureReason reason, |
| 287 content::RenderFrame* render_frame) { | 212 content::RenderFrame* render_frame) { |
| 288 } | 213 } |
| 289 | 214 |
| 290 } // namespace extensions | 215 } // namespace extensions |
| OLD | NEW |