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); |
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 Loading... |
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 |
OLD | NEW |