| 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/extension_function_dispatcher.h" | 5 #include "extensions/browser/extension_function_dispatcher.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/json/json_string_value_serializer.h" | 10 #include "base/json/json_string_value_serializer.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 16 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
| 17 #include "base/metrics/sparse_histogram.h" | 17 #include "base/metrics/sparse_histogram.h" |
| 18 #include "base/process/process.h" | 18 #include "base/process/process.h" |
| 19 #include "base/profiler/scoped_profile.h" | 19 #include "base/profiler/scoped_profile.h" |
| 20 #include "base/scoped_observer.h" | 20 #include "base/scoped_observer.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "content/public/browser/render_frame_host.h" | 24 #include "content/public/browser/render_frame_host.h" |
| 25 #include "content/public/browser/render_process_host.h" | 25 #include "content/public/browser/render_process_host.h" |
| 26 #include "content/public/browser/render_process_host_observer.h" | 26 #include "content/public/browser/render_process_host_observer.h" |
| 27 #include "content/public/browser/render_view_host.h" | 27 #include "content/public/browser/render_view_host.h" |
| 28 #include "content/public/browser/service_worker_context.h" | 28 #include "content/public/browser/service_worker_context.h" |
| 29 #include "content/public/browser/user_metrics.h" | |
| 30 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
| 31 #include "content/public/browser/web_contents_observer.h" | 30 #include "content/public/browser/web_contents_observer.h" |
| 32 #include "content/public/common/result_codes.h" | 31 #include "content/public/common/result_codes.h" |
| 33 #include "extensions/browser/api_activity_monitor.h" | 32 #include "extensions/browser/api_activity_monitor.h" |
| 34 #include "extensions/browser/bad_message.h" | |
| 35 #include "extensions/browser/extension_function_registry.h" | 33 #include "extensions/browser/extension_function_registry.h" |
| 36 #include "extensions/browser/extension_registry.h" | 34 #include "extensions/browser/extension_registry.h" |
| 37 #include "extensions/browser/extension_system.h" | 35 #include "extensions/browser/extension_system.h" |
| 38 #include "extensions/browser/extension_util.h" | 36 #include "extensions/browser/extension_util.h" |
| 39 #include "extensions/browser/extensions_browser_client.h" | 37 #include "extensions/browser/extensions_browser_client.h" |
| 40 #include "extensions/browser/io_thread_extension_message_filter.h" | 38 #include "extensions/browser/io_thread_extension_message_filter.h" |
| 41 #include "extensions/browser/process_manager.h" | 39 #include "extensions/browser/process_manager.h" |
| 42 #include "extensions/browser/process_map.h" | 40 #include "extensions/browser/process_map.h" |
| 43 #include "extensions/browser/quota_service.h" | 41 #include "extensions/browser/quota_service.h" |
| 44 #include "extensions/common/constants.h" | 42 #include "extensions/common/constants.h" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 73 | 71 |
| 74 // Separate copy of ExtensionAPI used for IO thread extension functions. We need | 72 // Separate copy of ExtensionAPI used for IO thread extension functions. We need |
| 75 // this because ExtensionAPI has mutable data. It should be possible to remove | 73 // this because ExtensionAPI has mutable data. It should be possible to remove |
| 76 // this once all the extension APIs are updated to the feature system. | 74 // this once all the extension APIs are updated to the feature system. |
| 77 struct Static { | 75 struct Static { |
| 78 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} | 76 Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {} |
| 79 std::unique_ptr<ExtensionAPI> api; | 77 std::unique_ptr<ExtensionAPI> api; |
| 80 }; | 78 }; |
| 81 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; | 79 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER; |
| 82 | 80 |
| 83 void LogBadMessage(functions::HistogramValue histogram_value) { | |
| 84 content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD")); | |
| 85 // Track the specific function's |histogram_value|, as this may indicate a | |
| 86 // bug in that API's implementation. | |
| 87 UMA_HISTOGRAM_ENUMERATION("Extensions.BadMessageFunctionName", | |
| 88 histogram_value, functions::ENUM_BOUNDARY); | |
| 89 } | |
| 90 | |
| 91 template <class T> | |
| 92 void ReceivedBadMessage(T* bad_message_sender, | |
| 93 bad_message::BadMessageReason reason, | |
| 94 functions::HistogramValue histogram_value) { | |
| 95 LogBadMessage(histogram_value); | |
| 96 // The renderer has done validation before sending extension api requests. | |
| 97 // Therefore, we should never receive a request that is invalid in a way | |
| 98 // that JSON validation in the renderer should have caught. It could be an | |
| 99 // attacker trying to exploit the browser, so we crash the renderer instead. | |
| 100 bad_message::ReceivedBadMessage(bad_message_sender, reason); | |
| 101 } | |
| 102 | |
| 103 template <class T> | |
| 104 void CommonResponseCallback(IPC::Sender* ipc_sender, | 81 void CommonResponseCallback(IPC::Sender* ipc_sender, |
| 105 int routing_id, | 82 int routing_id, |
| 106 T* bad_message_sender, | |
| 107 int request_id, | 83 int request_id, |
| 108 ExtensionFunction::ResponseType type, | 84 ExtensionFunction::ResponseType type, |
| 109 const base::ListValue& results, | 85 const base::ListValue& results, |
| 110 const std::string& error, | 86 const std::string& error) { |
| 111 functions::HistogramValue histogram_value) { | |
| 112 DCHECK(ipc_sender); | 87 DCHECK(ipc_sender); |
| 113 | 88 |
| 114 if (type == ExtensionFunction::BAD_MESSAGE) { | 89 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 115 ReceivedBadMessage(bad_message_sender, bad_message::EFD_BAD_MESSAGE, | 90 // The renderer will be shut down from ExtensionFunction::SetBadMessage(). |
| 116 histogram_value); | |
| 117 return; | 91 return; |
| 118 } | 92 } |
| 119 | 93 |
| 120 ipc_sender->Send(new ExtensionMsg_Response( | 94 ipc_sender->Send(new ExtensionMsg_Response( |
| 121 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, | 95 routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results, |
| 122 error)); | 96 error)); |
| 123 } | 97 } |
| 124 | 98 |
| 125 void IOThreadResponseCallback( | 99 void IOThreadResponseCallback( |
| 126 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, | 100 const base::WeakPtr<IOThreadExtensionMessageFilter>& ipc_sender, |
| 127 int routing_id, | 101 int routing_id, |
| 128 int request_id, | 102 int request_id, |
| 129 ExtensionFunction::ResponseType type, | 103 ExtensionFunction::ResponseType type, |
| 130 const base::ListValue& results, | 104 const base::ListValue& results, |
| 131 const std::string& error, | 105 const std::string& error, |
| 132 functions::HistogramValue histogram_value) { | 106 functions::HistogramValue histogram_value) { |
| 133 if (!ipc_sender.get()) | 107 if (!ipc_sender.get()) |
| 134 return; | 108 return; |
| 135 | 109 |
| 136 CommonResponseCallback(ipc_sender.get(), routing_id, ipc_sender.get(), | 110 CommonResponseCallback(ipc_sender.get(), routing_id, request_id, type, |
| 137 request_id, type, results, error, histogram_value); | 111 results, error); |
| 138 } | 112 } |
| 139 | 113 |
| 140 } // namespace | 114 } // namespace |
| 141 | 115 |
| 142 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper | 116 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper |
| 143 : public content::WebContentsObserver { | 117 : public content::WebContentsObserver { |
| 144 public: | 118 public: |
| 145 UIThreadResponseCallbackWrapper( | 119 UIThreadResponseCallbackWrapper( |
| 146 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, | 120 const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher, |
| 147 content::RenderFrameHost* render_frame_host) | 121 content::RenderFrameHost* render_frame_host) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 176 request_id); | 150 request_id); |
| 177 } | 151 } |
| 178 | 152 |
| 179 private: | 153 private: |
| 180 void OnExtensionFunctionCompleted(int request_id, | 154 void OnExtensionFunctionCompleted(int request_id, |
| 181 ExtensionFunction::ResponseType type, | 155 ExtensionFunction::ResponseType type, |
| 182 const base::ListValue& results, | 156 const base::ListValue& results, |
| 183 const std::string& error, | 157 const std::string& error, |
| 184 functions::HistogramValue histogram_value) { | 158 functions::HistogramValue histogram_value) { |
| 185 CommonResponseCallback(render_frame_host_, | 159 CommonResponseCallback(render_frame_host_, |
| 186 render_frame_host_->GetRoutingID(), | 160 render_frame_host_->GetRoutingID(), request_id, type, |
| 187 render_frame_host_->GetProcess(), request_id, type, | 161 results, error); |
| 188 results, error, histogram_value); | |
| 189 } | 162 } |
| 190 | 163 |
| 191 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 164 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 192 content::RenderFrameHost* render_frame_host_; | 165 content::RenderFrameHost* render_frame_host_; |
| 193 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; | 166 base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_; |
| 194 | 167 |
| 195 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); | 168 DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper); |
| 196 }; | 169 }; |
| 197 | 170 |
| 198 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper | 171 class ExtensionFunctionDispatcher::UIThreadWorkerResponseCallbackWrapper |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 } | 214 } |
| 242 | 215 |
| 243 void OnExtensionFunctionCompleted(int request_id, | 216 void OnExtensionFunctionCompleted(int request_id, |
| 244 ExtensionFunction::ResponseType type, | 217 ExtensionFunction::ResponseType type, |
| 245 const base::ListValue& results, | 218 const base::ListValue& results, |
| 246 const std::string& error, | 219 const std::string& error, |
| 247 functions::HistogramValue histogram_value) { | 220 functions::HistogramValue histogram_value) { |
| 248 content::RenderProcessHost* sender = | 221 content::RenderProcessHost* sender = |
| 249 content::RenderProcessHost::FromID(render_process_id_); | 222 content::RenderProcessHost::FromID(render_process_id_); |
| 250 if (type == ExtensionFunction::BAD_MESSAGE) { | 223 if (type == ExtensionFunction::BAD_MESSAGE) { |
| 251 ReceivedBadMessage(sender, bad_message::EFD_BAD_MESSAGE_WORKER, | 224 // The renderer will be shut down from ExtensionFunction::SetBadMessage(). |
| 252 histogram_value); | |
| 253 return; | 225 return; |
| 254 } | 226 } |
| 255 DCHECK(sender); | 227 DCHECK(sender); |
| 256 sender->Send(new ExtensionMsg_ResponseWorker( | 228 sender->Send(new ExtensionMsg_ResponseWorker( |
| 257 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, | 229 worker_thread_id_, request_id, type == ExtensionFunction::SUCCEEDED, |
| 258 results, error)); | 230 results, error)); |
| 259 } | 231 } |
| 260 | 232 |
| 261 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; | 233 base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_; |
| 262 ScopedObserver<content::RenderProcessHost, | 234 ScopedObserver<content::RenderProcessHost, |
| (...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 633 // static | 605 // static |
| 634 void ExtensionFunctionDispatcher::SendAccessDenied( | 606 void ExtensionFunctionDispatcher::SendAccessDenied( |
| 635 const ExtensionFunction::ResponseCallback& callback, | 607 const ExtensionFunction::ResponseCallback& callback, |
| 636 functions::HistogramValue histogram_value) { | 608 functions::HistogramValue histogram_value) { |
| 637 base::ListValue empty_list; | 609 base::ListValue empty_list; |
| 638 callback.Run(ExtensionFunction::FAILED, empty_list, | 610 callback.Run(ExtensionFunction::FAILED, empty_list, |
| 639 "Access to extension API denied.", histogram_value); | 611 "Access to extension API denied.", histogram_value); |
| 640 } | 612 } |
| 641 | 613 |
| 642 } // namespace extensions | 614 } // namespace extensions |
| OLD | NEW |