Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Side by Side Diff: extensions/browser/script_executor.cc

Issue 1216453002: [Extensions] Handle some funny cases in script injection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Ben's Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/browser/script_executor.h" 5 #include "extensions/browser/script_executor.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/pickle.h" 10 #include "base/pickle.h"
(...skipping 24 matching lines...) Expand all
35 public: 35 public:
36 Handler(base::ObserverList<ScriptExecutionObserver>* script_observers, 36 Handler(base::ObserverList<ScriptExecutionObserver>* script_observers,
37 content::WebContents* web_contents, 37 content::WebContents* web_contents,
38 const ExtensionMsg_ExecuteCode_Params& params, 38 const ExtensionMsg_ExecuteCode_Params& params,
39 ScriptExecutor::FrameScope scope, 39 ScriptExecutor::FrameScope scope,
40 const ScriptExecutor::ExecuteScriptCallback& callback) 40 const ScriptExecutor::ExecuteScriptCallback& callback)
41 : content::WebContentsObserver(web_contents), 41 : content::WebContentsObserver(web_contents),
42 script_observers_(AsWeakPtr(script_observers)), 42 script_observers_(AsWeakPtr(script_observers)),
43 host_id_(params.host_id), 43 host_id_(params.host_id),
44 request_id_(params.request_id), 44 request_id_(params.request_id),
45 num_pending_(0),
46 callback_(callback) { 45 callback_(callback) {
47 if (scope == ScriptExecutor::ALL_FRAMES) { 46 if (scope == ScriptExecutor::ALL_FRAMES) {
48 web_contents->ForEachFrame(base::Bind(&Handler::SendExecuteCode, 47 web_contents->ForEachFrame(base::Bind(&Handler::SendExecuteCode,
49 base::Unretained(this), params)); 48 base::Unretained(this), params));
50 } else { 49 } else {
51 SendExecuteCode(params, web_contents->GetMainFrame()); 50 SendExecuteCode(params, web_contents->GetMainFrame());
52 } 51 }
53 } 52 }
54 53
55 private: 54 private:
56 // This class manages its own lifetime. 55 // This class manages its own lifetime.
57 ~Handler() override {} 56 ~Handler() override {}
58 57
59 // content::WebContentsObserver: 58 // content::WebContentsObserver:
60 void WebContentsDestroyed() override { 59 void WebContentsDestroyed() override { Finish(); }
61 Finish(kRendererDestroyed, GURL(), base::ListValue());
62 }
63 60
64 bool OnMessageReceived(const IPC::Message& message, 61 bool OnMessageReceived(const IPC::Message& message,
65 content::RenderFrameHost* render_frame_host) override { 62 content::RenderFrameHost* render_frame_host) override {
66 // Unpack by hand to check the request_id, since there may be multiple 63 // Unpack by hand to check the request_id, since there may be multiple
67 // requests in flight but only one is for this. 64 // requests in flight but only one is for this.
68 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID) 65 if (message.type() != ExtensionHostMsg_ExecuteCodeFinished::ID)
69 return false; 66 return false;
70 67
71 int message_request_id; 68 int message_request_id;
72 base::PickleIterator iter(message); 69 base::PickleIterator iter(message);
73 CHECK(iter.ReadInt(&message_request_id)); 70 CHECK(iter.ReadInt(&message_request_id));
74 71
75 if (message_request_id != request_id_) 72 if (message_request_id != request_id_)
76 return false; 73 return false;
77 74
78 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(Handler, message, render_frame_host) 75 IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(Handler, message, render_frame_host)
79 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ExecuteCodeFinished, 76 IPC_MESSAGE_HANDLER(ExtensionHostMsg_ExecuteCodeFinished,
80 OnExecuteCodeFinished) 77 OnExecuteCodeFinished)
81 IPC_END_MESSAGE_MAP() 78 IPC_END_MESSAGE_MAP()
82 return true; 79 return true;
83 } 80 }
84 81
82 void RenderFrameDeleted(
83 content::RenderFrameHost* render_frame_host) override {
84 if (pending_render_frames_.erase(render_frame_host) == 1 &&
85 pending_render_frames_.empty()) {
86 Finish();
87 }
88 }
89
85 // Sends an ExecuteCode message to the given frame host, and increments 90 // Sends an ExecuteCode message to the given frame host, and increments
86 // the number of pending messages. 91 // the number of pending messages.
87 void SendExecuteCode(const ExtensionMsg_ExecuteCode_Params& params, 92 void SendExecuteCode(const ExtensionMsg_ExecuteCode_Params& params,
88 content::RenderFrameHost* frame) { 93 content::RenderFrameHost* frame) {
89 ++num_pending_; 94 pending_render_frames_.insert(frame);
90 frame->Send(new ExtensionMsg_ExecuteCode(frame->GetRoutingID(), params)); 95 frame->Send(new ExtensionMsg_ExecuteCode(frame->GetRoutingID(), params));
91 } 96 }
92 97
93 // Handles the ExecuteCodeFinished message. 98 // Handles the ExecuteCodeFinished message.
94 void OnExecuteCodeFinished(content::RenderFrameHost* render_frame_host, 99 void OnExecuteCodeFinished(content::RenderFrameHost* render_frame_host,
95 int request_id, 100 int request_id,
96 const std::string& error, 101 const std::string& error,
97 const GURL& on_url, 102 const GURL& on_url,
98 const base::ListValue& result_list) { 103 const base::ListValue& result_list) {
99 DCHECK_EQ(request_id_, request_id); 104 DCHECK_EQ(request_id_, request_id);
100 DCHECK_GT(num_pending_, 0); 105 DCHECK(!pending_render_frames_.empty());
106 bool erased = pending_render_frames_.erase(render_frame_host) == 1;
107 DCHECK(erased);
101 bool is_main_frame = web_contents()->GetMainFrame() == render_frame_host; 108 bool is_main_frame = web_contents()->GetMainFrame() == render_frame_host;
102 109
103 // Set the result, if there is one. 110 // Set the result, if there is one.
104 const base::Value* script_value = nullptr; 111 const base::Value* script_value = nullptr;
105 if (result_list.Get(0u, &script_value)) { 112 if (result_list.Get(0u, &script_value)) {
106 // If this is the main result, we put it at index 0. Otherwise, we just 113 // If this is the main result, we put it at index 0. Otherwise, we just
107 // append it at the end. 114 // append it at the end.
108 if (is_main_frame && !results_.empty()) 115 if (is_main_frame && !results_.empty())
109 CHECK(results_.Insert(0u, script_value->DeepCopy())); 116 CHECK(results_.Insert(0u, script_value->DeepCopy()));
110 else 117 else
111 results_.Append(script_value->DeepCopy()); 118 results_.Append(script_value->DeepCopy());
112 } 119 }
113 120
114 if (is_main_frame) { // Only use the main frame's error and url. 121 if (is_main_frame) { // Only use the main frame's error and url.
115 error_ = error; 122 main_frame_error_ = error;
116 url_ = on_url; 123 main_frame_url_ = on_url;
117 } 124 }
118 125
119 // Wait until the final request finishes before reporting back. 126 // Wait until the final request finishes before reporting back.
120 if (--num_pending_ > 0) 127 if (pending_render_frames_.empty())
121 return; 128 Finish();
129 }
122 130
123 if (script_observers_.get() && error.empty() && 131 void Finish() {
132 if (main_frame_url_.is_empty()) {
133 // We never finished the main frame injection.
134 main_frame_error_ = kRendererDestroyed;
135 results_.Clear();
136 }
137
138 if (script_observers_.get() && main_frame_error_.empty() &&
124 host_id_.type() == HostID::EXTENSIONS) { 139 host_id_.type() == HostID::EXTENSIONS) {
125 ScriptExecutionObserver::ExecutingScriptsMap id_map; 140 ScriptExecutionObserver::ExecutingScriptsMap id_map;
126 id_map[host_id_.id()] = std::set<std::string>(); 141 id_map[host_id_.id()] = std::set<std::string>();
127 FOR_EACH_OBSERVER(ScriptExecutionObserver, 142 FOR_EACH_OBSERVER(ScriptExecutionObserver, *script_observers_,
128 *script_observers_, 143 OnScriptsExecuted(web_contents(), id_map,
129 OnScriptsExecuted(web_contents(), id_map, on_url)); 144 main_frame_url_));
130 } 145 }
131 146
132 Finish(error_, url_, results_);
133 }
134
135 void Finish(const std::string& error,
136 const GURL& url,
137 const base::ListValue& result) {
138 if (!callback_.is_null()) 147 if (!callback_.is_null())
139 callback_.Run(error, url, result); 148 callback_.Run(main_frame_error_, main_frame_url_, results_);
140 delete this; 149 delete this;
141 } 150 }
142 151
143 base::WeakPtr<base::ObserverList<ScriptExecutionObserver>> script_observers_; 152 base::WeakPtr<base::ObserverList<ScriptExecutionObserver>> script_observers_;
144 153
145 // The id of the host (the extension or the webui) doing the injection. 154 // The id of the host (the extension or the webui) doing the injection.
146 HostID host_id_; 155 HostID host_id_;
147 156
148 // The request id of the injection. 157 // The request id of the injection.
149 int request_id_; 158 int request_id_;
150 159
151 // The number of still-running injections. 160 // The hosts of the still-running injections.
152 int num_pending_; 161 std::set<content::RenderFrameHost*> pending_render_frames_;
153 162
154 // The results of the injection. 163 // The results of the injection.
155 base::ListValue results_; 164 base::ListValue results_;
156 165
157 // The error from injecting into the main frame. 166 // The error from injecting into the main frame.
158 std::string error_; 167 std::string main_frame_error_;
159 168
160 // The url of the main frame. 169 // The url of the main frame.
161 GURL url_; 170 GURL main_frame_url_;
162 171
163 // The callback to run after all injections complete. 172 // The callback to run after all injections complete.
164 ScriptExecutor::ExecuteScriptCallback callback_; 173 ScriptExecutor::ExecuteScriptCallback callback_;
165 174
166 DISALLOW_COPY_AND_ASSIGN(Handler); 175 DISALLOW_COPY_AND_ASSIGN(Handler);
167 }; 176 };
168 177
169 } // namespace 178 } // namespace
170 179
171 ScriptExecutionObserver::~ScriptExecutionObserver() { 180 ScriptExecutionObserver::~ScriptExecutionObserver() {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 params.webview_src = webview_src; 228 params.webview_src = webview_src;
220 params.file_url = file_url; 229 params.file_url = file_url;
221 params.wants_result = (result_type == JSON_SERIALIZED_RESULT); 230 params.wants_result = (result_type == JSON_SERIALIZED_RESULT);
222 params.user_gesture = user_gesture; 231 params.user_gesture = user_gesture;
223 232
224 // Handler handles IPCs and deletes itself on completion. 233 // Handler handles IPCs and deletes itself on completion.
225 new Handler(script_observers_, web_contents_, params, frame_scope, callback); 234 new Handler(script_observers_, web_contents_, params, frame_scope, callback);
226 } 235 }
227 236
228 } // namespace extensions 237 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698