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) ¶ms.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) ¶ms.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(¶ms.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