1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_dispatcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
12a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "base/metrics/sparse_histogram.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_frame_host.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_view_host.h"
200f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "content/public/browser/user_metrics.h"
218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/web_contents.h"
228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "content/public/browser/web_contents_observer.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/common/result_codes.h"
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/api_activity_monitor.h"
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/browser/extension_function_registry.h"
26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "extensions/browser/extension_message_filter.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/process_manager.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_map.h"
32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/quota_service.h"
330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h"
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h"
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace extensions {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Notifies the ApiActivityMonitor that an extension API function has been
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// called. May be called from any thread.
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotifyApiFunctionCalled(const std::string& extension_id,
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const std::string& api_name,
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             scoped_ptr<base::ListValue> args,
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             content::BrowserContext* browser_context) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The ApiActivityMonitor can only be accessed from the main (UI) thread. If
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we're running on the wrong thread, re-dispatch from the main thread.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI,
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            FROM_HERE,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            base::Bind(&NotifyApiFunctionCalled,
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       extension_id,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       api_name,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::Passed(&args),
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       browser_context));
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The BrowserContext may become invalid after the task above is posted.
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
67e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ApiActivityMonitor* monitor =
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionsBrowserClient::Get()->GetApiActivityMonitor(browser_context);
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (monitor)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    monitor->OnApiFunctionCalled(extension_id, api_name, args.Pass());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Separate copy of ExtensionAPI used for IO thread extension functions. We need
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this because ExtensionAPI has mutable data. It should be possible to remove
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this once all the extension APIs are updated to the feature system.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Static {
77e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  Static() : api(ExtensionAPI::CreateWithDefaultConfiguration()) {}
78e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  scoped_ptr<ExtensionAPI> api;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Kills the specified process because it sends us a malformed message.
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void KillBadMessageSender(base::ProcessHandle process) {
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NOTREACHED();
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD"));
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (process)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::KillProcess(process, content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CommonResponseCallback(IPC::Sender* ipc_sender,
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            int routing_id,
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            base::ProcessHandle peer_process,
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            int request_id,
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            ExtensionFunction::ResponseType type,
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const base::ListValue& results,
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const std::string& error) {
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(ipc_sender);
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (type == ExtensionFunction::BAD_MESSAGE) {
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // The renderer has done validation before sending extension api requests.
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Therefore, we should never receive a request that is invalid in a way
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // that JSON validation in the renderer should have caught. It could be an
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // attacker trying to exploit the browser, so we crash the renderer instead.
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) <<
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        "Terminating renderer because of malformed extension message.";
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (content::RenderProcessHost::run_renderer_in_process()) {
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // In single process mode it is better if we don't suicide but just crash.
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CHECK(false);
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      KillBadMessageSender(peer_process);
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ipc_sender->Send(new ExtensionMsg_Response(
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results,
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error));
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IOThreadResponseCallback(
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const base::WeakPtr<ExtensionMessageFilter>& ipc_sender,
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int routing_id,
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int request_id,
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ExtensionFunction::ResponseType type,
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::ListValue& results,
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& error) {
128868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ipc_sender.get())
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CommonResponseCallback(ipc_sender.get(),
132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         routing_id,
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                         ipc_sender->PeerHandle(),
134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         request_id,
135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         type,
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         results,
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         error);
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper
1438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : public content::WebContentsObserver {
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
14590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UIThreadResponseCallbackWrapper(
14690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher,
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RenderViewHost* render_view_host)
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : content::WebContentsObserver(
1498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            content::WebContents::FromRenderViewHost(render_view_host)),
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dispatcher_(dispatcher),
1518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_(render_view_host),
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        weak_ptr_factory_(this) {
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~UIThreadResponseCallbackWrapper() {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // content::WebContentsObserver overrides.
1598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void RenderViewDeleted(
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RenderViewHost* render_view_host) OVERRIDE {
161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    DCHECK_CURRENTLY_ON(BrowserThread::UI);
1628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (render_view_host != render_view_host_)
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (dispatcher_.get()) {
166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      dispatcher_->ui_thread_response_callback_wrappers_
167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          .erase(render_view_host);
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete this;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionFunction::ResponseCallback CreateCallback(int request_id) {
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return base::Bind(
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        &UIThreadResponseCallbackWrapper::OnExtensionFunctionCompleted,
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        request_id);
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OnExtensionFunctionCompleted(int request_id,
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    ExtensionFunction::ResponseType type,
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    const base::ListValue& results,
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    const std::string& error) {
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CommonResponseCallback(
1868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_, render_view_host_->GetRoutingID(),
1878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_->GetProcess()->GetHandle(), request_id, type,
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        results, error);
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  content::RenderViewHost* render_view_host_;
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_;
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper);
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochWindowController*
199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::WebContents*
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochcontent::WebContents*
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionFunctionDispatcher::Delegate::GetVisibleWebContents() const {
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return GetAssociatedWebContents();
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::GetAllFunctionNames(
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* names) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionFunctionRegistry::GetInstance()->GetAllNames(names);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionFunctionDispatcher::OverrideFunction(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name, ExtensionFunctionFactory factory) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExtensionFunctionRegistry::GetInstance()->OverrideFunction(name,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                    factory);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::DispatchOnIOThread(
226e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    InfoMap* extension_info_map,
227e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    void* profile_id,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
229e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    base::WeakPtr<ExtensionMessageFilter> ipc_sender,
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int routing_id,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map->extensions().GetByID(params.extension_id);
2341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!extension)
2351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionFunction::ResponseCallback callback(
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&IOThreadResponseCallback, ipc_sender, routing_id,
23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 params.request_id));
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionFunction> function(
242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      CreateExtensionFunction(params,
243e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              extension,
244e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              render_process_id,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extension_info_map->process_map(),
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              g_global_io_data.Get().api.get(),
247e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              profile_id,
248e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              callback));
2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!function.get())
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOThreadExtensionFunction* function_io =
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function->AsIOThreadExtensionFunction();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function_io) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  function_io->set_ipc_sender(ipc_sender, routing_id);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function_io->set_extension_info_map(extension_info_map);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_include_incognito(
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map->IsIncognitoEnabled(extension->id()));
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!CheckPermissions(function.get(), params, callback))
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  QuotaService* quota = extension_info_map->GetQuotaService();
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string violation_error = quota->Assess(extension->id(),
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              function.get(),
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              &params.arguments,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              base::TimeTicks::Now());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (violation_error.empty()) {
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    NotifyApiFunctionCalled(extension->id(),
274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            params.name,
275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            args.Pass(),
276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                            static_cast<content::BrowserContext*>(profile_id));
277a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls",
278a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                function->histogram_value());
279010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    function->Run()->Execute();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function->OnQuotaExceeded(violation_error);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    content::BrowserContext* browser_context,
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    Delegate* delegate)
288a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : browser_context_(browser_context),
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      delegate_(delegate) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::Dispatch(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RenderViewHost* render_view_host) {
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UIThreadResponseCallbackWrapperMap::const_iterator
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      iter = ui_thread_response_callback_wrappers_.find(render_view_host);
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UIThreadResponseCallbackWrapper* callback_wrapper = NULL;
30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (iter == ui_thread_response_callback_wrappers_.end()) {
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback_wrapper = new UIThreadResponseCallbackWrapper(AsWeakPtr(),
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                                           render_view_host);
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ui_thread_response_callback_wrappers_[render_view_host] = callback_wrapper;
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    callback_wrapper = iter->second;
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DispatchWithCallbackInternal(
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      params, render_view_host, NULL,
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      callback_wrapper->CreateCallback(params.request_id));
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionFunctionDispatcher::DispatchWithCallbackInternal(
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RenderViewHost* render_view_host,
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host,
31890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(render_view_host || render_frame_host);
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(yzshen): There is some shared logic between this method and
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // DispatchOnIOThread(). It is nice to deduplicate.
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ProcessMap* process_map = ProcessMap::Get(browser_context_);
323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!process_map)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const Extension* extension =
3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      registry->enabled_extensions().GetByID(params.extension_id);
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!extension) {
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    extension =
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        registry->enabled_extensions().GetHostedAppByURL(params.source_url);
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int process_id = render_view_host ? render_view_host->GetProcess()->GetID() :
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      render_frame_host->GetProcess()->GetID();
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionFunction> function(
337a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      CreateExtensionFunction(params,
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              extension,
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              process_id,
340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              *process_map,
341e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                              ExtensionAPI::GetSharedInstance(),
342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              browser_context_,
343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              callback));
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!function.get())
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadExtensionFunction* function_ui =
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function->AsUIThreadExtensionFunction();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function_ui) {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (render_view_host) {
3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function_ui->SetRenderViewHost(render_view_host);
3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function_ui->SetRenderFrameHost(render_frame_host);
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function_ui->set_dispatcher(AsWeakPtr());
359a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  function_ui->set_browser_context(browser_context_);
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension &&
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          extension, browser_context_)) {
3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    function->set_include_incognito(true);
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!CheckPermissions(function.get(), params, callback))
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!extension) {
3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // Skip all of the UMA, quota, event page, activity logging stuff if there
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // isn't an extension, e.g. if the function call was from WebUI.
3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    function->Run()->Execute();
3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return;
3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
377e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  QuotaService* quota = extension_system->quota_service();
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string violation_error = quota->Assess(extension->id(),
379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              function.get(),
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              &params.arguments,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              base::TimeTicks::Now());
3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (violation_error.empty()) {
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // See crbug.com/39178.
3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler();
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NotifyApiFunctionCalled(
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        extension->id(), params.name, args.Pass(), browser_context_);
390a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls",
391a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                function->histogram_value());
392010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    function->Run()->Execute();
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function->OnQuotaExceeded(violation_error);
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: do not access |this| after this point. We may have been deleted
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if function->Run() ended up closing the tab that owns us.
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if extension was uninstalled by management.uninstall.
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!registry->enabled_extensions().GetByID(params.extension_id))
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only adjust the keepalive count for UIThreadExtensionFunction for
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // now, largely for simplicity's sake. This is OK because currently, only
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the webRequest API uses IOThreadExtensionFunction, and that API is not
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compatible with lazy background pages.
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  extension_system->process_manager()->IncrementLazyKeepaliveCount(extension);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted(
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension) {
4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (extension) {
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ExtensionSystem::Get(browser_context_)
4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ->process_manager()
4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        ->DecrementLazyKeepaliveCount(extension);
4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionFunctionDispatcher::CheckPermissions(
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionFunction* function,
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function->HasPermission()) {
4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    LOG(ERROR) << "Permission denied for " << params.name;
42790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int requesting_process_id,
438e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const ProcessMap& process_map,
439e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ExtensionAPI* api,
440e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    void* profile_id,
44190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionFunction* function =
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name);
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!function) {
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unknown Extension API - " << params.name;
44690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->SetArgs(&params.arguments);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_source_url(params.source_url);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_request_id(params.request_id);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_has_callback(params.has_callback);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_user_gesture(params.user_gesture);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_extension(extension);
456e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  function->set_profile_id(profile_id);
45790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  function->set_response_callback(callback);
4585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function->set_source_tab_id(params.source_tab_id);
4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  function->set_source_context_type(
4606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      process_map.GetMostLikelyContextType(extension, requesting_process_id));
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::SendAccessDenied(
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue empty_list;
46990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  callback.Run(ExtensionFunction::FAILED, empty_list,
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               "Access to extension API denied.");
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
472e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
473e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace extensions
474