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#ifndef EXTENSIONS_RENDERER_SCRIPT_INJECTION_H_ 6#define EXTENSIONS_RENDERER_SCRIPT_INJECTION_H_ 7 8#include <map> 9#include <set> 10#include <string> 11 12#include "base/basictypes.h" 13#include "base/macros.h" 14#include "base/memory/scoped_ptr.h" 15#include "base/memory/scoped_vector.h" 16#include "base/timer/elapsed_timer.h" 17#include "extensions/common/user_script.h" 18 19class GURL; 20 21namespace blink { 22class WebFrame; 23} 24 25namespace content { 26class RenderView; 27} 28 29namespace extensions { 30class UserScriptSlave; 31 32// This class is a wrapper around a UserScript that knows how to inject itself 33// into a frame. 34class ScriptInjection { 35 public: 36 // Map of extensions IDs to the executing script paths. 37 typedef std::map<std::string, std::set<std::string> > ExecutingScriptsMap; 38 39 // A struct containing information about a script run. 40 struct ScriptsRunInfo { 41 ScriptsRunInfo(); 42 ~ScriptsRunInfo(); 43 44 // The number of CSS scripts injected. 45 size_t num_css; 46 // The number of JS scripts injected. 47 size_t num_js; 48 // A map of extension ids to executing script paths. 49 ExecutingScriptsMap executing_scripts; 50 // The elapsed time since the ScriptsRunInfo was constructed. 51 base::ElapsedTimer timer; 52 53 private: 54 DISALLOW_COPY_AND_ASSIGN(ScriptsRunInfo); 55 }; 56 57 // Return the URL to use as the document url when checking permissions for 58 // script injection. 59 static GURL GetDocumentUrlForFrame(blink::WebFrame* frame); 60 61 ScriptInjection(scoped_ptr<UserScript> script, 62 UserScriptSlave* user_script_slave); 63 ~ScriptInjection(); 64 65 // Inject the script into the given |frame| if the script should run on the 66 // frame and has permission to do so. If the script requires user consent, 67 // this will register a pending request to inject at a later time. 68 // If the script is run immediately, |scripts_run_info| is updated with 69 // information about the run. 70 void InjectIfAllowed(blink::WebFrame* frame, 71 UserScript::RunLocation location, 72 const GURL& document_url, 73 ScriptsRunInfo* scripts_run_info); 74 75 // If a request with the given |request_id| exists, runs that request and 76 // modifies |scripts_run_info| with information about the run. Otherwise, does 77 // nothing. 78 // If |frame_out| is non-NULL and a script was run, |frame_out| will be 79 // populated with the frame in which the script was run. 80 // Returns true if the request was found *and* the script was run. 81 bool NotifyScriptPermitted(int64 request_id, 82 content::RenderView* render_view, 83 ScriptsRunInfo* scripts_run_info, 84 blink::WebFrame** frame_out); 85 86 // Notififies the Injection that the frame has been detached (i.e. is about 87 // to be destroyed). 88 void FrameDetached(blink::WebFrame* frame); 89 90 void SetScript(scoped_ptr<UserScript> script); 91 92 const std::string& extension_id() { return extension_id_; } 93 const UserScript* script() { return script_.get(); } 94 95 private: 96 struct PendingInjection; 97 98 // Returns true if this ScriptInjection wants to run on the given |frame| at 99 // the given |run_location| (i.e., if this script would inject either JS or 100 // CSS). 101 bool WantsToRun(blink::WebFrame* frame, 102 UserScript::RunLocation run_location, 103 const GURL& document_url) const; 104 105 // Returns true if the script will inject [css|js] at the given 106 // |run_location|. 107 bool ShouldInjectJS(UserScript::RunLocation run_location) const; 108 bool ShouldInjectCSS(UserScript::RunLocation run_location) const; 109 110 // Injects the script into the given |frame|, and updates |scripts_run_info| 111 // information about the run. 112 void Inject(blink::WebFrame* frame, 113 UserScript::RunLocation run_location, 114 ScriptsRunInfo* scripts_run_info) const; 115 116 // Injects the [css|js] scripts into the frame, and stores the results of 117 // the run in |scripts_run_info|. 118 void InjectJS(blink::WebFrame* frame, ScriptsRunInfo* scripts_run_info) const; 119 void InjectCSS(blink::WebFrame* frame, ScriptsRunInfo* scripts_run_info) 120 const; 121 122 // The UserScript this is injecting. 123 scoped_ptr<UserScript> script_; 124 125 // The associated extension's id. 126 std::string extension_id_; 127 128 // The associated UserScriptSlave. 129 // It's unfortunate that this is needed, but we use it to get the isolated 130 // world ids and the associated extensions. 131 // TODO(rdevlin.cronin): It would be nice to clean this up more. 132 UserScriptSlave* user_script_slave_; 133 134 // True if the script is a standalone script or emulates greasemonkey. 135 bool is_standalone_or_emulate_greasemonkey_; 136 137 ScopedVector<PendingInjection> pending_injections_; 138 139 DISALLOW_COPY_AND_ASSIGN(ScriptInjection); 140}; 141 142} // namespace extensions 143 144#endif // EXTENSIONS_RENDERER_SCRIPT_INJECTION_H_ 145