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/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 Loading... | |
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); | |
not at google - send to devlin
2015/06/29 18:28:11
I prefer the pattern of not having a variable whic
Devlin
2015/06/29 19:41:44
Not to be difficult, but why is an if-statement fo
not at google - send to devlin
2015/06/29 20:09:07
If nothing bad happens if it fails, and it should
Devlin
2015/06/29 20:43:13
Sanity-checking purposes. So that future Ben and
| |
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 error_ = error; |
116 url_ = on_url; | 123 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 (url_.is_empty()) { // We never finished the main frame injection. | |
133 error_ = kRendererDestroyed; | |
134 results_.Clear(); | |
135 } | |
136 | |
137 if (script_observers_.get() && error_.empty() && | |
124 host_id_.type() == HostID::EXTENSIONS) { | 138 host_id_.type() == HostID::EXTENSIONS) { |
125 ScriptExecutionObserver::ExecutingScriptsMap id_map; | 139 ScriptExecutionObserver::ExecutingScriptsMap id_map; |
126 id_map[host_id_.id()] = std::set<std::string>(); | 140 id_map[host_id_.id()] = std::set<std::string>(); |
not at google - send to devlin
2015/06/29 18:28:11
In tracking down this slightly odd-looking line of
Devlin
2015/06/29 19:41:44
Done.
| |
127 FOR_EACH_OBSERVER(ScriptExecutionObserver, | 141 FOR_EACH_OBSERVER(ScriptExecutionObserver, *script_observers_, |
128 *script_observers_, | 142 OnScriptsExecuted(web_contents(), id_map, url_)); |
129 OnScriptsExecuted(web_contents(), id_map, on_url)); | |
130 } | 143 } |
131 | 144 |
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()) | 145 if (!callback_.is_null()) |
139 callback_.Run(error, url, result); | 146 callback_.Run(error_, url_, results_); |
140 delete this; | 147 delete this; |
141 } | 148 } |
142 | 149 |
143 base::WeakPtr<base::ObserverList<ScriptExecutionObserver>> script_observers_; | 150 base::WeakPtr<base::ObserverList<ScriptExecutionObserver>> script_observers_; |
144 | 151 |
145 // The id of the host (the extension or the webui) doing the injection. | 152 // The id of the host (the extension or the webui) doing the injection. |
146 HostID host_id_; | 153 HostID host_id_; |
147 | 154 |
148 // The request id of the injection. | 155 // The request id of the injection. |
149 int request_id_; | 156 int request_id_; |
150 | 157 |
151 // The number of still-running injections. | 158 // The hosts of the still-running injections. |
152 int num_pending_; | 159 std::set<content::RenderFrameHost*> pending_render_frames_; |
153 | 160 |
154 // The results of the injection. | 161 // The results of the injection. |
155 base::ListValue results_; | 162 base::ListValue results_; |
156 | 163 |
157 // The error from injecting into the main frame. | 164 // The error from injecting into the main frame. |
158 std::string error_; | 165 std::string error_; |
159 | 166 |
160 // The url of the main frame. | 167 // The url of the main frame. |
161 GURL url_; | 168 GURL url_; |
not at google - send to devlin
2015/06/29 18:28:11
Could you rename to main_frame_url_ and main_frame
Devlin
2015/06/29 19:41:44
Good call; done.
| |
162 | 169 |
163 // The callback to run after all injections complete. | 170 // The callback to run after all injections complete. |
164 ScriptExecutor::ExecuteScriptCallback callback_; | 171 ScriptExecutor::ExecuteScriptCallback callback_; |
165 | 172 |
166 DISALLOW_COPY_AND_ASSIGN(Handler); | 173 DISALLOW_COPY_AND_ASSIGN(Handler); |
167 }; | 174 }; |
168 | 175 |
169 } // namespace | 176 } // namespace |
170 | 177 |
171 ScriptExecutionObserver::~ScriptExecutionObserver() { | 178 ScriptExecutionObserver::~ScriptExecutionObserver() { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 params.webview_src = webview_src; | 226 params.webview_src = webview_src; |
220 params.file_url = file_url; | 227 params.file_url = file_url; |
221 params.wants_result = (result_type == JSON_SERIALIZED_RESULT); | 228 params.wants_result = (result_type == JSON_SERIALIZED_RESULT); |
222 params.user_gesture = user_gesture; | 229 params.user_gesture = user_gesture; |
223 | 230 |
224 // Handler handles IPCs and deletes itself on completion. | 231 // Handler handles IPCs and deletes itself on completion. |
225 new Handler(script_observers_, web_contents_, params, frame_scope, callback); | 232 new Handler(script_observers_, web_contents_, params, frame_scope, callback); |
226 } | 233 } |
227 | 234 |
228 } // namespace extensions | 235 } // namespace extensions |
OLD | NEW |