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); 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 23590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ExtensionFunction::ResponseCallback callback( 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&IOThreadResponseCallback, ipc_sender, routing_id, 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) params.request_id)); 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ExtensionFunction> function( 240e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch CreateExtensionFunction(params, 241e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension, 242e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch render_process_id, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_info_map->process_map(), 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_global_io_data.Get().api.get(), 245e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch profile_id, 246e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch callback)); 2473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!function.get()) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOThreadExtensionFunction* function_io = 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->AsIOThreadExtensionFunction(); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!function_io) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) function_io->set_ipc_sender(ipc_sender, routing_id); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_io->set_extension_info_map(extension_info_map); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_include_incognito( 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_info_map->IsIncognitoEnabled(extension->id())); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!CheckPermissions(function.get(), extension, params, callback)) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 264e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch QuotaService* quota = extension_info_map->GetQuotaService(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string violation_error = quota->Assess(extension->id(), 266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) function.get(), 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¶ms.arguments, 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (violation_error.empty()) { 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(params.arguments.DeepCopy()); 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch NotifyApiFunctionCalled(extension->id(), 272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch params.name, 273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch args.Pass(), 274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch static_cast<content::BrowserContext*>(profile_id)); 275a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", 276a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch function->histogram_value()); 277010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) function->Run()->Execute(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->OnQuotaExceeded(violation_error); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ExtensionFunctionDispatcher::ExtensionFunctionDispatcher( 284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) content::BrowserContext* browser_context, 285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Delegate* delegate) 286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : browser_context_(browser_context), 287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) delegate_(delegate) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::Dispatch( 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExtensionHostMsg_Request_Params& params, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHost* render_view_host) { 29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UIThreadResponseCallbackWrapperMap::const_iterator 29790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) iter = ui_thread_response_callback_wrappers_.find(render_view_host); 29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) UIThreadResponseCallbackWrapper* callback_wrapper = NULL; 29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (iter == ui_thread_response_callback_wrappers_.end()) { 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback_wrapper = new UIThreadResponseCallbackWrapper(AsWeakPtr(), 30190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) render_view_host); 30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ui_thread_response_callback_wrappers_[render_view_host] = callback_wrapper; 30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback_wrapper = iter->second; 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DispatchWithCallbackInternal( 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params, render_view_host, NULL, 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) callback_wrapper->CreateCallback(params.request_id)); 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void ExtensionFunctionDispatcher::DispatchWithCallback( 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ExtensionHostMsg_Request_Params& params, 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RenderFrameHost* render_frame_host, 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ExtensionFunction::ResponseCallback& callback) { 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DispatchWithCallbackInternal(params, NULL, render_frame_host, callback); 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ExtensionFunctionDispatcher::DispatchWithCallbackInternal( 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ExtensionHostMsg_Request_Params& params, 32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RenderViewHost* render_view_host, 3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::RenderFrameHost* render_frame_host, 32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ExtensionFunction::ResponseCallback& callback) { 3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(render_view_host || render_frame_host); 32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // TODO(yzshen): There is some shared logic between this method and 32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // DispatchOnIOThread(). It is nice to deduplicate. 327e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ProcessMap* process_map = ProcessMap::Get(browser_context_); 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!process_map) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 331e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_); 3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = registry->enabled_extensions().GetByID( 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params.extension_id); 3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!extension) { 3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension = 3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) registry->enabled_extensions().GetHostedAppByURL(params.source_url); 3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int process_id = render_view_host ? render_view_host->GetProcess()->GetID() : 3405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_frame_host->GetProcess()->GetID(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ExtensionFunction> function( 342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CreateExtensionFunction(params, 343a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) extension, 3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) process_id, 345a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) *process_map, 346e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionAPI::GetSharedInstance(), 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) browser_context_, 348a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) callback)); 3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!function.get()) 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UIThreadExtensionFunction* function_ui = 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->AsUIThreadExtensionFunction(); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!function_ui) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (render_view_host) { 3595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function_ui->SetRenderViewHost(render_view_host); 3605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function_ui->SetRenderFrameHost(render_frame_host); 3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_ui->set_dispatcher(AsWeakPtr()); 364a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) function_ui->set_browser_context(browser_context_); 3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_include_incognito( 3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito( 3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension, browser_context_)); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!CheckPermissions(function.get(), extension, params, callback)) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_); 373e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch QuotaService* quota = extension_system->quota_service(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string violation_error = quota->Assess(extension->id(), 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) function.get(), 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ¶ms.arguments, 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks::Now()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (violation_error.empty()) { 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<base::ListValue> args(params.arguments.DeepCopy()); 3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3819a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu // See crbug.com/39178. 3829a3a4bc965704498ea9f22876627cda96ff9a77eBo Liu ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler(); 3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NotifyApiFunctionCalled( 3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extension->id(), params.name, args.Pass(), browser_context_); 385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.FunctionCalls", 386a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch function->histogram_value()); 387010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) function->Run()->Execute(); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->OnQuotaExceeded(violation_error); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: do not access |this| after this point. We may have been deleted 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if function->Run() ended up closing the tab that owns us. 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if extension was uninstalled by management.uninstall. 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!registry->enabled_extensions().GetByID(params.extension_id)) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only adjust the keepalive count for UIThreadExtensionFunction for 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // now, largely for simplicity's sake. This is OK because currently, only 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the webRequest API uses IOThreadExtensionFunction, and that API is not 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // compatible with lazy background pages. 403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) extension_system->process_manager()->IncrementLazyKeepaliveCount(extension); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted( 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExtensionSystem::Get(browser_context_)->process_manager()-> 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DecrementLazyKeepaliveCount(extension); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionFunctionDispatcher::CheckPermissions( 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionFunction* function, 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExtensionHostMsg_Request_Params& params, 41790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ExtensionFunction::ResponseCallback& callback) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!function->HasPermission()) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Extension " << extension->id() << " does not have " 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "permission to function: " << params.name; 42190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SendAccessDenied(callback); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Only COMPONENT hosted apps may call extension APIs, and they are limited 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to just the permissions they explicitly request. They should not have access 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to extension APIs like eg chrome.runtime, chrome.windows, etc. that normally 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// are available without permission. 433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// TODO(mpcomplete): move this to ExtensionFunction::HasPermission (or remove 434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// it altogether). 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AllowHostedAppAPICall(const Extension& extension, 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& source_url, 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& function_name) { 438e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (extension.location() != Manifest::COMPONENT) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!extension.web_extent().MatchesURL(source_url)) 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Note: Not BLESSED_WEB_PAGE_CONTEXT here because these component hosted app 4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // entities have traditionally been treated as blessed extensions, for better 4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // or worse. 447a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Feature::Availability availability = 448a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ExtensionAPI::GetSharedInstance()->IsAvailable( 449a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) function_name, &extension, Feature::BLESSED_EXTENSION_CONTEXT, 450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) source_url); 451a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return availability.is_available(); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionFunction* ExtensionFunctionDispatcher::CreateExtensionFunction( 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExtensionHostMsg_Request_Params& params, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int requesting_process_id, 462e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const ProcessMap& process_map, 463e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ExtensionAPI* api, 464e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void* profile_id, 46590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ExtensionFunction::ResponseCallback& callback) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension) { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Specified extension does not exist."; 46890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SendAccessDenied(callback); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Most hosted apps can't call APIs. 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool allowed = true; 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (extension->is_hosted_app()) 47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) allowed = AllowHostedAppAPICall(*extension, params.source_url, params.name); 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Privileged APIs can only be called from the process the extension 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is running in. 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (allowed && api->IsPrivileged(params.name)) 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) allowed = process_map.Contains(extension->id(), requesting_process_id); 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!allowed) { 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Extension API call disallowed - name:" << params.name 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " pid:" << requesting_process_id 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " from URL " << params.source_url.spec(); 48690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SendAccessDenied(callback); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionFunction* function = 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionFunctionRegistry::GetInstance()->NewFunction(params.name); 492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!function) { 493c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LOG(ERROR) << "Unknown Extension API - " << params.name; 49490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SendAccessDenied(callback); 495c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 496c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 497c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->SetArgs(¶ms.arguments); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_source_url(params.source_url); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_request_id(params.request_id); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_has_callback(params.has_callback); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_user_gesture(params.user_gesture); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function->set_extension(extension); 504e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch function->set_profile_id(profile_id); 50590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) function->set_response_callback(callback); 5065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function->set_source_tab_id(params.source_tab_id); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return function; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionFunctionDispatcher::SendAccessDenied( 51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ExtensionFunction::ResponseCallback& callback) { 5145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::ListValue empty_list; 51590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) callback.Run(ExtensionFunction::FAILED, empty_list, 51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) "Access to extension API denied."); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 518e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 519e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} // namespace extensions 520