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