extension_function_dispatcher.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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"
12bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/renderer_host/chrome_render_message_filter.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"
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_registry.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h"
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extensions_browser_client.h"
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/process_manager.h"
30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/process_map.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/browser/quota_service.h"
320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h"
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h"
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/common/extension_set.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message_macros.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionAPI;
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using extensions::ExtensionsBrowserClient;
41a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)using extensions::ExtensionSystem;
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using extensions::Feature;
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using content::BrowserThread;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Notifies the ApiActivityMonitor that an extension API function has been
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// called. May be called from any thread.
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void NotifyApiFunctionCalled(const std::string& extension_id,
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             const std::string& api_name,
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             scoped_ptr<base::ListValue> args,
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             content::BrowserContext* browser_context) {
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The ApiActivityMonitor can only be accessed from the main (UI) thread. If
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // we're running on the wrong thread, re-dispatch from the main thread.
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            FROM_HERE,
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            base::Bind(&NotifyApiFunctionCalled,
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       extension_id,
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       api_name,
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       base::Passed(&args),
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                       browser_context));
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The BrowserContext may become invalid after the task above is posted.
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::ApiActivityMonitor* monitor =
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionsBrowserClient::Get()->GetApiActivityMonitor(browser_context);
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (monitor)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    monitor->OnApiFunctionCalled(extension_id, api_name, args.Pass());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Separate copy of ExtensionAPI used for IO thread extension functions. We need
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this because ExtensionAPI has mutable data. It should be possible to remove
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this once all the extension APIs are updated to the feature system.
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Static {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Static()
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : api(extensions::ExtensionAPI::CreateWithDefaultConfiguration()) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<extensions::ExtensionAPI> api;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<Static> g_global_io_data = LAZY_INSTANCE_INITIALIZER;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Kills the specified process because it sends us a malformed message.
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void KillBadMessageSender(base::ProcessHandle process) {
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  NOTREACHED();
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  content::RecordAction(base::UserMetricsAction("BadMessageTerminate_EFD"));
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (process)
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::KillProcess(process, content::RESULT_CODE_KILLED_BAD_MESSAGE, false);
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void CommonResponseCallback(IPC::Sender* ipc_sender,
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            int routing_id,
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            base::ProcessHandle peer_process,
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            int request_id,
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            ExtensionFunction::ResponseType type,
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const base::ListValue& results,
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                            const std::string& error) {
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(ipc_sender);
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (type == ExtensionFunction::BAD_MESSAGE) {
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // The renderer has done validation before sending extension api requests.
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Therefore, we should never receive a request that is invalid in a way
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // that JSON validation in the renderer should have caught. It could be an
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // attacker trying to exploit the browser, so we crash the renderer instead.
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(ERROR) <<
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        "Terminating renderer because of malformed extension message.";
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (content::RenderProcessHost::run_renderer_in_process()) {
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // In single process mode it is better if we don't suicide but just crash.
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      CHECK(false);
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
11590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      KillBadMessageSender(peer_process);
11690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
11990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ipc_sender->Send(new ExtensionMsg_Response(
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      routing_id, request_id, type == ExtensionFunction::SUCCEEDED, results,
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      error));
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void IOThreadResponseCallback(
12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::WeakPtr<ChromeRenderMessageFilter>& ipc_sender,
12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int routing_id,
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    int request_id,
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    ExtensionFunction::ResponseType type,
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::ListValue& results,
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& error) {
133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!ipc_sender.get())
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CommonResponseCallback(ipc_sender.get(),
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         routing_id,
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                         ipc_sender->PeerHandle(),
139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         request_id,
140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         type,
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         results,
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                         error);
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class ExtensionFunctionDispatcher::UIThreadResponseCallbackWrapper
1488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : public content::WebContentsObserver {
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  UIThreadResponseCallbackWrapper(
15190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const base::WeakPtr<ExtensionFunctionDispatcher>& dispatcher,
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RenderViewHost* render_view_host)
1538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : content::WebContentsObserver(
1548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            content::WebContents::FromRenderViewHost(render_view_host)),
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        dispatcher_(dispatcher),
1568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_(render_view_host),
15790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        weak_ptr_factory_(this) {
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  virtual ~UIThreadResponseCallbackWrapper() {
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // content::WebContentsObserver overrides.
1648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual void RenderViewDeleted(
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      RenderViewHost* render_view_host) OVERRIDE {
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
1678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (render_view_host != render_view_host_)
1688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return;
1698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (dispatcher_.get()) {
171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      dispatcher_->ui_thread_response_callback_wrappers_
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          .erase(render_view_host);
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete this;
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionFunction::ResponseCallback CreateCallback(int request_id) {
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return base::Bind(
18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        &UIThreadResponseCallbackWrapper::OnExtensionFunctionCompleted,
18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        weak_ptr_factory_.GetWeakPtr(),
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        request_id);
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void OnExtensionFunctionCompleted(int request_id,
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    ExtensionFunction::ResponseType type,
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    const base::ListValue& results,
18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                    const std::string& error) {
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    CommonResponseCallback(
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_, render_view_host_->GetRoutingID(),
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        render_view_host_->GetProcess()->GetHandle(), request_id, type,
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        results, error);
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtr<ExtensionFunctionDispatcher> dispatcher_;
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  content::RenderViewHost* render_view_host_;
19890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::WeakPtrFactory<UIThreadResponseCallbackWrapper> weak_ptr_factory_;
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(UIThreadResponseCallbackWrapper);
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::WindowController*
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController()
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::WebContents*
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochcontent::WebContents*
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochExtensionFunctionDispatcher::Delegate::GetVisibleWebContents() const {
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return GetAssociatedWebContents();
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::GetAllFunctionNames(
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::vector<std::string>* names) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionFunctionRegistry::GetInstance()->GetAllNames(names);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionFunctionDispatcher::OverrideFunction(
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name, ExtensionFunctionFactory factory) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ExtensionFunctionRegistry::GetInstance()->OverrideFunction(name,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                                    factory);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::DispatchOnIOThread(
232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    extensions::InfoMap* extension_info_map,
233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    void* browser_context,
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::WeakPtr<ChromeRenderMessageFilter> ipc_sender,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int routing_id,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Extension* extension =
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map->extensions().GetByID(params.extension_id);
24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ExtensionFunction::ResponseCallback callback(
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      base::Bind(&IOThreadResponseCallback, ipc_sender, routing_id,
24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 params.request_id));
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionFunction> function(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateExtensionFunction(params, extension, render_process_id,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extension_info_map->process_map(),
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              g_global_io_data.Get().api.get(),
249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              browser_context, callback));
2503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!function.get())
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IOThreadExtensionFunction* function_io =
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function->AsIOThreadExtensionFunction();
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function_io) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  function_io->set_ipc_sender(ipc_sender, routing_id);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function_io->set_extension_info_map(extension_info_map);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_include_incognito(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      extension_info_map->IsIncognitoEnabled(extension->id()));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!CheckPermissions(function.get(), extension, params, callback))
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  extensions::QuotaService* quota = extension_info_map->GetQuotaService();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string violation_error = quota->Assess(extension->id(),
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                              function.get(),
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              &params.arguments,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              base::TimeTicks::Now());
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (violation_error.empty()) {
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NotifyApiFunctionCalled(
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        extension->id(),
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        params.name,
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        args.Pass(),
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<content::BrowserContext*>(browser_context));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function->Run();
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)
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionFunctionDispatcher::DispatchWithCallback(
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host,
3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DispatchWithCallbackInternal(params, NULL, render_frame_host, callback);
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionFunctionDispatcher::DispatchWithCallbackInternal(
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RenderViewHost* render_view_host,
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderFrameHost* render_frame_host,
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(render_view_host || render_frame_host);
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // TODO(yzshen): There is some shared logic between this method and
32890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // DispatchOnIOThread(). It is nice to deduplicate.
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::ProcessMap* process_map =
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ProcessMap::Get(browser_context_);
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!process_map)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::ExtensionRegistry* registry =
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      extensions::ExtensionRegistry::Get(browser_context_);
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const Extension* extension = registry->enabled_extensions().GetByID(
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      params.extension_id);
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!extension) {
3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    extension =
3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        registry->enabled_extensions().GetHostedAppByURL(params.source_url);
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int process_id = render_view_host ? render_view_host->GetProcess()->GetID() :
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      render_frame_host->GetProcess()->GetID();
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ExtensionFunction> function(
346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      CreateExtensionFunction(params,
347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              extension,
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                              process_id,
349a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              *process_map,
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              extensions::ExtensionAPI::GetSharedInstance(),
351a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              browser_context_,
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              callback));
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!function.get())
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadExtensionFunction* function_ui =
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      function->AsUIThreadExtensionFunction();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function_ui) {
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (render_view_host) {
3635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function_ui->SetRenderViewHost(render_view_host);
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    function_ui->SetRenderFrameHost(render_frame_host);
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function_ui->set_dispatcher(AsWeakPtr());
368a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  function_ui->set_browser_context(browser_context_);
3695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function->set_include_incognito(
3705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          extension, browser_context_));
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!CheckPermissions(function.get(), extension, params, callback))
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  extensions::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());
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (violation_error.empty()) {
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    scoped_ptr<base::ListValue> args(params.arguments.DeepCopy());
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See crbug.com/39178.
386a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler();
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    NotifyApiFunctionCalled(
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        extension->id(), params.name, args.Pass(), browser_context_);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function->Run();
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    function->OnQuotaExceeded(violation_error);
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: do not access |this| after this point. We may have been deleted
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if function->Run() ended up closing the tab that owns us.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if extension was uninstalled by management.uninstall.
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!registry->enabled_extensions().GetByID(params.extension_id))
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only adjust the keepalive count for UIThreadExtensionFunction for
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // now, largely for simplicity's sake. This is OK because currently, only
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the webRequest API uses IOThreadExtensionFunction, and that API is not
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compatible with lazy background pages.
405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  extension_system->process_manager()->IncrementLazyKeepaliveCount(extension);
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted(
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension) {
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ExtensionSystem::Get(browser_context_)->process_manager()->
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DecrementLazyKeepaliveCount(extension);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionFunctionDispatcher::CheckPermissions(
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtensionFunction* function,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension,
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
41990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!function->HasPermission()) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Extension " << extension->id() << " does not have "
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << "permission to function: " << params.name;
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Only COMPONENT hosted apps may call extension APIs, and they are limited
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to just the permissions they explicitly request. They should not have access
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to extension APIs like eg chrome.runtime, chrome.windows, etc. that normally
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// are available without permission.
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// TODO(mpcomplete): move this to ExtensionFunction::HasPermission (or remove
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// it altogether).
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AllowHostedAppAPICall(const Extension& extension,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const GURL& source_url,
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const std::string& function_name) {
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension.location() != extensions::Manifest::COMPONENT)
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!extension.web_extent().MatchesURL(source_url))
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Note: Not BLESSED_WEB_PAGE_CONTEXT here because these component hosted app
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // entities have traditionally been treated as blessed extensions, for better
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // or worse.
449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  Feature::Availability availability =
450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      ExtensionAPI::GetSharedInstance()->IsAvailable(
451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          function_name, &extension, Feature::BLESSED_EXTENSION_CONTEXT,
452a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          source_url);
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return availability.is_available();
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction(
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ExtensionHostMsg_Request_Params& params,
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Extension* extension,
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int requesting_process_id,
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const extensions::ProcessMap& process_map,
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    extensions::ExtensionAPI* api,
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* profile,
46790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension) {
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Specified extension does not exist.";
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Most hosted apps can't call APIs.
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool allowed = true;
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (extension->is_hosted_app())
47790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    allowed = AllowHostedAppAPICall(*extension, params.source_url, params.name);
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Privileged APIs can only be called from the process the extension
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is running in.
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (allowed && api->IsPrivileged(params.name))
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    allowed = process_map.Contains(extension->id(), requesting_process_id);
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!allowed) {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LOG(ERROR) << "Extension API call disallowed - name:" << params.name
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               << " pid:" << requesting_process_id
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " from URL " << params.source_url.spec();
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExtensionFunction* function =
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name);
494c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!function) {
495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unknown Extension API - " << params.name;
49690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SendAccessDenied(callback);
497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->SetArgs(&params.arguments);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_source_url(params.source_url);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_request_id(params.request_id);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_has_callback(params.has_callback);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_user_gesture(params.user_gesture);
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_extension(extension);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  function->set_profile_id(profile);
50790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  function->set_response_callback(callback);
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  function->set_source_tab_id(params.source_tab_id);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::SendAccessDenied(
51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const ExtensionFunction::ResponseCallback& callback) {
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::ListValue empty_list;
51790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  callback.Run(ExtensionFunction::FAILED, empty_list,
51890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)               "Access to extension API denied.");
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
520