Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / extensions / browser / extension_function_dispatcher.cc
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
3 // found in the LICENSE file.
4
5 #include "extensions/browser/extension_function_dispatcher.h"
6
7 #include "base/bind.h"
8 #include "base/json/json_string_value_serializer.h"
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/metrics/sparse_histogram.h"
13 #include "base/process/process.h"
14 #include "base/values.h"
15 #include "build/build_config.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/render_view_host.h"
20 #include "content/public/browser/user_metrics.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_observer.h"
23 #include "content/public/common/result_codes.h"
24 #include "extensions/browser/api_activity_monitor.h"
25 #include "extensions/browser/extension_function_registry.h"
26 #include "extensions/browser/extension_message_filter.h"
27 #include "extensions/browser/extension_registry.h"
28 #include "extensions/browser/extension_system.h"
29 #include "extensions/browser/extensions_browser_client.h"
30 #include "extensions/browser/process_manager.h"
31 #include "extensions/browser/process_map.h"
32 #include "extensions/browser/quota_service.h"
33 #include "extensions/common/extension_api.h"
34 #include "extensions/common/extension_messages.h"
35 #include "extensions/common/extension_set.h"
36 #include "ipc/ipc_message.h"
37 #include "ipc/ipc_message_macros.h"
38
39 using content::BrowserThread;
40 using content::RenderViewHost;
41
42 namespace extensions {
43 namespace {
44
45 // Notifies the ApiActivityMonitor that an extension API function has been
46 // called. May be called from any thread.
47 void NotifyApiFunctionCalled(const std::string& extension_id,
48                              const std::string& api_name,
49                              scoped_ptr<base::ListValue> args,
50                              content::BrowserContext* browser_context) {
51   // The ApiActivityMonitor can only be accessed from the main (UI) thread. If
52   // we're running on the wrong thread, re-dispatch from the main thread.
53   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
54     BrowserThread::PostTask(BrowserThread::UI,
55                             FROM_HERE,
56                             base::Bind(&NotifyApiFunctionCalled,
57                                        extension_id,
58                                        api_name,
59                                        base::Passed(&args),
60                                        browser_context));
61     return;
62   }
63   // The BrowserContext may become invalid after the task above is posted.
64   if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
65     return;
66
67   ApiActivityMonitor* monitor =
68       ExtensionsBrowserClient::Get()->GetApiActivityMonitor(browser_context);
69   if (monitor)
70     monitor->OnApiFunctionCalled(extension_id, api_name, args.Pass());
71 }
72
73 // Separate copy of ExtensionAPI used for IO thread extension functions. We need
74 // this because ExtensionAPI has mutable data. It should be possible to remove
75 // this once all the extension APIs are updated to the feature system.
76 struct Static {
77   Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {}
78   scoped_ptr<ExtensionAPI> api;
79 };
80 base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
81
82 // Kills the specified process because it sends us a malformed message.
83 void KillBadMessageSender(base::ProcessHandle process) {
84   NOTREACHED();
85   content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD"));
86   if (process)
87     base::KillProcess(process, content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
88 }
89
90 void CommonResponseCallback(IPC::Sender* ipc_sender,
91                             int routing_id,
92                             base::ProcessHandle peer_process,
93                             int request_id,
94                             ExtensionFunction::ResponseType type,
95                             const base::ListValue& results,
96                             const std::string& error) {
97   DCHECK(ipc_sender);
98
99   if (type == ExtensionFunction::BAD_MESSAGE) {
100     // The renderer has done validation before sending extension api requests.
101     // Therefore, we should never receive a request that is invalid in a way
102     // that JSON validation in the renderer should have caught. It could be an
103     // attacker trying to exploit the browser, so we crash the renderer instead.
104     LOG(ERROR) <<
105         "Terminating renderer because of malformed extension message.";
106     if (content::RenderProcessHost::run_renderer_in_process()) {
107       // In single process mode it is better if we don't suicide but just crash.
108       CHECK(false);
109     } else {
110       KillBadMessageSender(peer_process);
111     }
112
113     return;
114   }
115
116   ipc_sender->Send(new ExtensionMsg_Response(
117       routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results,
118       error));
119 }
120
121 void IOThreadResponseCallback(
122     const base::WeakPtr<ExtensionMessageFilter>& ipc_sender,
123     int routing_id,
124     int request_id,
125     ExtensionFunction::ResponseType type,
126     const base::ListValue& results,
127     const std::string& error) {
128   if (!ipc_sender.get())
129     return;
130
131   CommonResponseCallback(ipc_sender.get(),
132                          routing_id,
133                          ipc_sender->PeerHandle(),
134                          request_id,
135                          type,
136                          results,
137                          error);
138 }
139
140 }  // namespace
141
142 class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper
143     : public content::WebContentsObserver {
144  public:
145   UIThreadResponseCallbackWrapper(
146       const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher,
147       RenderViewHost* render_view_host)
148       : content::WebContentsObserver(
149             content::WebContents::FromRenderViewHost(render_view_host)),
150         dispatcher_(dispatcher),
151         render_view_host_(render_view_host),
152         weak_ptr_factory_(this) {
153   }
154
155   virtual ~UIThreadResponseCallbackWrapper() {
156   }
157
158   // content::WebContentsObserver overrides.
159   virtual void RenderViewDeleted(
160       RenderViewHost* render_view_host) OVERRIDE {
161     DCHECK_CURRENTLY_ON(BrowserThread::UI);
162     if (render_view_host != render_view_host_)
163       return;
164
165     if (dispatcher_.get()) {
166       dispatcher_->ui_thread_response_callback_wrappers_
167           .erase(render_view_host);
168     }
169
170     delete this;
171   }
172
173   ExtensionFunction::ResponseCallback CreateCallback(int request_id) {
174     return base::Bind(
175         &UIThreadResponseCallbackWrapper::OnExtensionFunctionCompleted,
176         weak_ptr_factory_.GetWeakPtr(),
177         request_id);
178   }
179
180  private:
181   void OnExtensionFunctionCompleted(int request_id,
182                                     ExtensionFunction::ResponseType type,
183                                     const base::ListValue& results,
184                                     const std::string& error) {
185     CommonResponseCallback(
186         render_view_host_, render_view_host_->GetRoutingID(),
187         render_view_host_->GetProcess()->GetHandle(), request_id, type,
188         results, error);
189   }
190
191   base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
192   content::RenderViewHost* render_view_host_;
193   base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_;
194
195   DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper);
196 };
197
198 WindowController*
199 ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const {
200   return NULL;
201 }
202
203 content::WebContents*
204 ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
205   return NULL;
206 }
207
208 content::WebContents*
209 ExtensionFunctionDispatcher::Delegate::GetVisibleWebContents() const {
210   return GetAssociatedWebContents();
211 }
212
213 void ExtensionFunctionDispatcher::GetAllFunctionNames(
214     std::vector<std::string>* names) {
215   ExtensionFunctionRegistry::GetInstance()->GetAllNames(names);
216 }
217
218 bool ExtensionFunctionDispatcher::OverrideFunction(
219     const std::string& name, ExtensionFunctionFactory factory) {
220   return ExtensionFunctionRegistry::GetInstance()->OverrideFunction(name,
221                                                                     factory);
222 }
223
224 // static
225 void ExtensionFunctionDispatcher::DispatchOnIOThread(
226     InfoMap* extension_info_map,
227     void* profile_id,
228     int render_process_id,
229     base::WeakPtr<ExtensionMessageFilter> ipc_sender,
230     int routing_id,
231     const ExtensionHostMsg_Request_Params& params) {
232   const Extension* extension =
233       extension_info_map->extensions().GetByID(params.extension_id);
234
235   ExtensionFunction::ResponseCallback callback(
236       base::Bind(&IOThreadResponseCallback, ipc_sender, routing_id,
237                  params.request_id));
238
239   scoped_refptr<ExtensionFunction> function(
240       CreateExtensionFunction(params,
241                               extension,
242                               render_process_id,
243                               extension_info_map->process_map(),
244                               g_global_io_data.Get().api.get(),
245                               profile_id,
246                               callback));
247   if (!function.get())
248     return;
249
250   IOThreadExtensionFunction* function_io =
251       function->AsIOThreadExtensionFunction();
252   if (!function_io) {
253     NOTREACHED();
254     return;
255   }
256   function_io->set_ipc_sender(ipc_sender, routing_id);
257   function_io->set_extension_info_map(extension_info_map);
258   function->set_include_incognito(
259       extension_info_map->IsIncognitoEnabled(extension->id()));
260
261   if (!CheckPermissions(function.get(), extension, params, callback))
262     return;
263
264   QuotaService* quota = extension_info_map->GetQuotaService();
265   std::string violation_error = quota->Assess(extension->id(),
266                                               function.get(),
267                                               &params.arguments,
268                                               base::TimeTicks::Now());
269   if (violation_error.empty()) {
270     scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
271     NotifyApiFunctionCalled(extension->id(),
272                             params.name,
273                             args.Pass(),
274                             static_cast<content::BrowserContext*>(profile_id));
275     UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls",
276                                 function->histogram_value());
277     function->Run()->Execute();
278   } else {
279     function->OnQuotaExceeded(violation_error);
280   }
281 }
282
283 ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
284     content::BrowserContext* browser_context,
285     Delegate* delegate)
286     : browser_context_(browser_context),
287       delegate_(delegate) {
288 }
289
290 ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
291 }
292
293 void ExtensionFunctionDispatcher::Dispatch(
294     const ExtensionHostMsg_Request_Params& params,
295     RenderViewHost* render_view_host) {
296   UIThreadResponseCallbackWrapperMap::const_iterator
297       iter = ui_thread_response_callback_wrappers_.find(render_view_host);
298   UIThreadResponseCallbackWrapper* callback_wrapper = NULL;
299   if (iter == ui_thread_response_callback_wrappers_.end()) {
300     callback_wrapper = new UIThreadResponseCallbackWrapper(AsWeakPtr(),
301                                                            render_view_host);
302     ui_thread_response_callback_wrappers_[render_view_host] = callback_wrapper;
303   } else {
304     callback_wrapper = iter->second;
305   }
306
307   DispatchWithCallbackInternal(
308       params, render_view_host, NULL,
309       callback_wrapper->CreateCallback(params.request_id));
310 }
311
312 void ExtensionFunctionDispatcher::DispatchWithCallback(
313     const ExtensionHostMsg_Request_Params& params,
314     content::RenderFrameHost* render_frame_host,
315     const ExtensionFunction::ResponseCallback& callback) {
316   DispatchWithCallbackInternal(params, NULL, render_frame_host, callback);
317 }
318
319 void ExtensionFunctionDispatcher::DispatchWithCallbackInternal(
320     const ExtensionHostMsg_Request_Params& params,
321     RenderViewHost* render_view_host,
322     content::RenderFrameHost* render_frame_host,
323     const ExtensionFunction::ResponseCallback& callback) {
324   DCHECK(render_view_host || render_frame_host);
325   // TODO(yzshen): There is some shared logic between this method and
326   // DispatchOnIOThread(). It is nice to deduplicate.
327   ProcessMap* process_map = ProcessMap::Get(browser_context_);
328   if (!process_map)
329     return;
330
331   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
332   const Extension* extension = registry->enabled_extensions().GetByID(
333       params.extension_id);
334   if (!extension) {
335     extension =
336         registry->enabled_extensions().GetHostedAppByURL(params.source_url);
337   }
338
339   int process_id = render_view_host ? render_view_host->GetProcess()->GetID() :
340                                       render_frame_host->GetProcess()->GetID();
341   scoped_refptr<ExtensionFunction> function(
342       CreateExtensionFunction(params,
343                               extension,
344                               process_id,
345                               *process_map,
346                               ExtensionAPI::GetSharedInstance(),
347                               browser_context_,
348                               callback));
349   if (!function.get())
350     return;
351
352   UIThreadExtensionFunction* function_ui =
353       function->AsUIThreadExtensionFunction();
354   if (!function_ui) {
355     NOTREACHED();
356     return;
357   }
358   if (render_view_host) {
359     function_ui->SetRenderViewHost(render_view_host);
360   } else {
361     function_ui->SetRenderFrameHost(render_frame_host);
362   }
363   function_ui->set_dispatcher(AsWeakPtr());
364   function_ui->set_browser_context(browser_context_);
365   function->set_include_incognito(
366       ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
367           extension, browser_context_));
368
369   if (!CheckPermissions(function.get(), extension, params, callback))
370     return;
371
372   ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
373   QuotaService* quota = extension_system->quota_service();
374   std::string violation_error = quota->Assess(extension->id(),
375                                               function.get(),
376                                               &params.arguments,
377                                               base::TimeTicks::Now());
378   if (violation_error.empty()) {
379     scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
380
381     NotifyApiFunctionCalled(
382         extension->id(), params.name, args.Pass(), browser_context_);
383     UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls",
384                                 function->histogram_value());
385     function->Run()->Execute();
386   } else {
387     function->OnQuotaExceeded(violation_error);
388   }
389
390   // Note: do not access |this| after this point. We may have been deleted
391   // if function->Run() ended up closing the tab that owns us.
392
393   // Check if extension was uninstalled by management.uninstall.
394   if (!registry->enabled_extensions().GetByID(params.extension_id))
395     return;
396
397   // We only adjust the keepalive count for UIThreadExtensionFunction for
398   // now, largely for simplicity's sake. This is OK because currently, only
399   // the webRequest API uses IOThreadExtensionFunction, and that API is not
400   // compatible with lazy background pages.
401   extension_system->process_manager()->IncrementLazyKeepaliveCount(extension);
402 }
403
404 void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted(
405     const Extension* extension) {
406   ExtensionSystem::Get(browser_context_)->process_manager()->
407       DecrementLazyKeepaliveCount(extension);
408 }
409
410 // static
411 bool ExtensionFunctionDispatcher::CheckPermissions(
412     ExtensionFunction* function,
413     const Extension* extension,
414     const ExtensionHostMsg_Request_Params& params,
415     const ExtensionFunction::ResponseCallback& callback) {
416   if (!function->HasPermission()) {
417     LOG(ERROR) << "Extension " << extension->id() << " does not have "
418                << "permission to function: " << params.name;
419     SendAccessDenied(callback);
420     return false;
421   }
422   return true;
423 }
424
425 namespace {
426
427 // Only COMPONENT hosted apps may call extension APIs, and they are limited
428 // to just the permissions they explicitly request. They should not have access
429 // to extension APIs like eg chrome.runtime, chrome.windows, etc. that normally
430 // are available without permission.
431 // TODO(mpcomplete): move this to ExtensionFunction::HasPermission (or remove
432 // it altogether).
433 bool AllowHostedAppAPICall(const Extension& extension,
434                            const GURL& source_url,
435                            const std::string& function_name) {
436   if (extension.location() != Manifest::COMPONENT)
437     return false;
438
439   if (!extension.web_extent().MatchesURL(source_url))
440     return false;
441
442   // Note: Not BLESSED_WEB_PAGE_CONTEXT here because these component hosted app
443   // entities have traditionally been treated as blessed extensions, for better
444   // or worse.
445   Feature::Availability availability =
446       ExtensionAPI::GetSharedInstance()->IsAvailable(
447           function_name, &extension, Feature::BLESSED_EXTENSION_CONTEXT,
448           source_url);
449   return availability.is_available();
450 }
451
452 }  // namespace
453
454
455 // static
456 ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
457     const ExtensionHostMsg_Request_Params& params,
458     const Extension* extension,
459     int requesting_process_id,
460     const ProcessMap& process_map,
461     ExtensionAPI* api,
462     void* profile_id,
463     const ExtensionFunction::ResponseCallback& callback) {
464   if (!extension) {
465     LOG(ERROR) << "Specified extension does not exist.";
466     SendAccessDenied(callback);
467     return NULL;
468   }
469
470   // Most hosted apps can't call APIs.
471   bool allowed = true;
472   if (extension->is_hosted_app())
473     allowed = AllowHostedAppAPICall(*extension, params.source_url, params.name);
474
475   // Privileged APIs can only be called from the process the extension
476   // is running in.
477   if (allowed && api->IsPrivileged(params.name))
478     allowed = process_map.Contains(extension->id(), requesting_process_id);
479
480   if (!allowed) {
481     LOG(ERROR) << "Extension API call disallowed - name:" << params.name
482                << " pid:" << requesting_process_id
483                << " from URL " << params.source_url.spec();
484     SendAccessDenied(callback);
485     return NULL;
486   }
487
488   ExtensionFunction* function =
489       ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name);
490   if (!function) {
491     LOG(ERROR) << "Unknown Extension API - " << params.name;
492     SendAccessDenied(callback);
493     return NULL;
494   }
495
496   function->SetArgs(&params.arguments);
497   function->set_source_url(params.source_url);
498   function->set_request_id(params.request_id);
499   function->set_has_callback(params.has_callback);
500   function->set_user_gesture(params.user_gesture);
501   function->set_extension(extension);
502   function->set_profile_id(profile_id);
503   function->set_response_callback(callback);
504   function->set_source_tab_id(params.source_tab_id);
505
506   return function;
507 }
508
509 // static
510 void ExtensionFunctionDispatcher::SendAccessDenied(
511     const ExtensionFunction::ResponseCallback& callback) {
512   base::ListValue empty_list;
513   callback.Run(ExtensionFunction::FAILED, empty_list,
514                "Access to extension API denied.");
515 }
516
517 }  // namespace extensions