| 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( |
| 128 *script_observers_, | 143 ScriptExecutionObserver, *script_observers_, |
| 129 OnScriptsExecuted(web_contents(), id_map, on_url)); | 144 OnScriptsExecuted(web_contents(), id_map, 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 |