Several things are done in this CL:
[chromium-blink-merge.git] / chrome / renderer / extensions / chrome_extensions_dispatcher_delegate.cc
blob4eab8ef5588b1fd43cda2635d82b726e42c5dc0a
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.h"
7 #include "base/command_line.h"
8 #include "base/sha1.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/common/chrome_switches.h"
11 #include "chrome/common/chrome_version_info.h"
12 #include "chrome/common/crash_keys.h"
13 #include "chrome/common/extensions/features/feature_channel.h"
14 #include "chrome/common/url_constants.h"
15 #include "chrome/grit/renderer_resources.h"
16 #include "chrome/renderer/extensions/app_bindings.h"
17 #include "chrome/renderer/extensions/automation_internal_custom_bindings.h"
18 #include "chrome/renderer/extensions/chrome_v8_context.h"
19 #include "chrome/renderer/extensions/enterprise_platform_keys_natives.h"
20 #include "chrome/renderer/extensions/file_browser_handler_custom_bindings.h"
21 #include "chrome/renderer/extensions/file_manager_private_custom_bindings.h"
22 #include "chrome/renderer/extensions/media_galleries_custom_bindings.h"
23 #include "chrome/renderer/extensions/notifications_native_handler.h"
24 #include "chrome/renderer/extensions/page_capture_custom_bindings.h"
25 #include "chrome/renderer/extensions/sync_file_system_custom_bindings.h"
26 #include "chrome/renderer/extensions/tab_finder.h"
27 #include "chrome/renderer/extensions/tabs_custom_bindings.h"
28 #include "chrome/renderer/extensions/webstore_bindings.h"
29 #include "content/public/renderer/render_thread.h"
30 #include "content/public/renderer/render_view.h"
31 #include "extensions/common/extension.h"
32 #include "extensions/common/feature_switch.h"
33 #include "extensions/common/permissions/api_permission_set.h"
34 #include "extensions/common/permissions/manifest_permission_set.h"
35 #include "extensions/common/permissions/permission_set.h"
36 #include "extensions/common/permissions/permissions_data.h"
37 #include "extensions/common/switches.h"
38 #include "extensions/common/url_pattern_set.h"
39 #include "extensions/renderer/dispatcher.h"
40 #include "extensions/renderer/native_handler.h"
41 #include "extensions/renderer/resource_bundle_source_map.h"
42 #include "extensions/renderer/script_context.h"
43 #include "third_party/WebKit/public/platform/WebString.h"
44 #include "third_party/WebKit/public/web/WebDocument.h"
45 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
46 #include "third_party/WebKit/public/web/WebView.h"
48 #if defined(ENABLE_WEBRTC)
49 #include "chrome/renderer/extensions/cast_streaming_native_handler.h"
50 #endif
52 using extensions::NativeHandler;
54 ChromeExtensionsDispatcherDelegate::ChromeExtensionsDispatcherDelegate() {
57 ChromeExtensionsDispatcherDelegate::~ChromeExtensionsDispatcherDelegate() {
60 scoped_ptr<extensions::ScriptContext>
61 ChromeExtensionsDispatcherDelegate::CreateScriptContext(
62 const v8::Handle<v8::Context>& v8_context,
63 blink::WebFrame* frame,
64 const extensions::Extension* extension,
65 extensions::Feature::Context context_type,
66 const extensions::Extension* effective_extension,
67 extensions::Feature::Context effective_context_type) {
68 return scoped_ptr<extensions::ScriptContext>(
69 new extensions::ChromeV8Context(v8_context,
70 frame,
71 extension,
72 context_type,
73 effective_extension,
74 effective_context_type));
77 void ChromeExtensionsDispatcherDelegate::InitOriginPermissions(
78 const extensions::Extension* extension,
79 bool is_extension_active) {
80 // TODO(jstritar): We should try to remove this special case. Also, these
81 // whitelist entries need to be updated when the kManagement permission
82 // changes.
83 if (is_extension_active &&
84 extension->permissions_data()->HasAPIPermission(
85 extensions::APIPermission::kManagement)) {
86 blink::WebSecurityPolicy::addOriginAccessWhitelistEntry(
87 extension->url(),
88 blink::WebString::fromUTF8(content::kChromeUIScheme),
89 blink::WebString::fromUTF8(chrome::kChromeUIExtensionIconHost),
90 false);
94 void ChromeExtensionsDispatcherDelegate::RegisterNativeHandlers(
95 extensions::Dispatcher* dispatcher,
96 extensions::ModuleSystem* module_system,
97 extensions::ScriptContext* context) {
98 #if !defined(ENABLE_EXTENSIONS)
99 return;
100 #endif
101 module_system->RegisterNativeHandler(
102 "app",
103 scoped_ptr<NativeHandler>(
104 new extensions::AppBindings(dispatcher, context)));
105 module_system->RegisterNativeHandler(
106 "sync_file_system",
107 scoped_ptr<NativeHandler>(
108 new extensions::SyncFileSystemCustomBindings(context)));
109 module_system->RegisterNativeHandler(
110 "enterprise_platform_keys_natives",
111 scoped_ptr<NativeHandler>(
112 new extensions::EnterprisePlatformKeysNatives(context)));
113 module_system->RegisterNativeHandler(
114 "file_browser_handler",
115 scoped_ptr<NativeHandler>(
116 new extensions::FileBrowserHandlerCustomBindings(context)));
117 module_system->RegisterNativeHandler(
118 "file_manager_private",
119 scoped_ptr<NativeHandler>(
120 new extensions::FileManagerPrivateCustomBindings(context)));
121 module_system->RegisterNativeHandler(
122 "notifications_private",
123 scoped_ptr<NativeHandler>(
124 new extensions::NotificationsNativeHandler(context)));
125 module_system->RegisterNativeHandler(
126 "mediaGalleries",
127 scoped_ptr<NativeHandler>(
128 new extensions::MediaGalleriesCustomBindings(context)));
129 module_system->RegisterNativeHandler(
130 "page_capture",
131 scoped_ptr<NativeHandler>(
132 new extensions::PageCaptureCustomBindings(context)));
133 module_system->RegisterNativeHandler(
134 "tabs",
135 scoped_ptr<NativeHandler>(new extensions::TabsCustomBindings(context)));
136 module_system->RegisterNativeHandler(
137 "webstore",
138 scoped_ptr<NativeHandler>(new extensions::WebstoreBindings(context)));
139 #if defined(ENABLE_WEBRTC)
140 module_system->RegisterNativeHandler(
141 "cast_streaming_natives",
142 scoped_ptr<NativeHandler>(
143 new extensions::CastStreamingNativeHandler(context)));
144 #endif
145 module_system->RegisterNativeHandler(
146 "automationInternal",
147 scoped_ptr<NativeHandler>(
148 new extensions::AutomationInternalCustomBindings(context)));
151 void ChromeExtensionsDispatcherDelegate::PopulateSourceMap(
152 extensions::ResourceBundleSourceMap* source_map) {
153 // Custom bindings.
154 source_map->RegisterSource("app", IDR_APP_CUSTOM_BINDINGS_JS);
155 source_map->RegisterSource("automation", IDR_AUTOMATION_CUSTOM_BINDINGS_JS);
156 source_map->RegisterSource("automationEvent", IDR_AUTOMATION_EVENT_JS);
157 source_map->RegisterSource("automationNode", IDR_AUTOMATION_NODE_JS);
158 source_map->RegisterSource("browserAction",
159 IDR_BROWSER_ACTION_CUSTOM_BINDINGS_JS);
160 source_map->RegisterSource("declarativeContent",
161 IDR_DECLARATIVE_CONTENT_CUSTOM_BINDINGS_JS);
162 source_map->RegisterSource("desktopCapture",
163 IDR_DESKTOP_CAPTURE_CUSTOM_BINDINGS_JS);
164 source_map->RegisterSource("developerPrivate",
165 IDR_DEVELOPER_PRIVATE_CUSTOM_BINDINGS_JS);
166 source_map->RegisterSource("downloads", IDR_DOWNLOADS_CUSTOM_BINDINGS_JS);
167 source_map->RegisterSource("enterprise.platformKeys",
168 IDR_ENTERPRISE_PLATFORM_KEYS_CUSTOM_BINDINGS_JS);
169 source_map->RegisterSource("enterprise.platformKeys.internalAPI",
170 IDR_ENTERPRISE_PLATFORM_KEYS_INTERNAL_API_JS);
171 source_map->RegisterSource("enterprise.platformKeys.Key",
172 IDR_ENTERPRISE_PLATFORM_KEYS_KEY_JS);
173 source_map->RegisterSource("enterprise.platformKeys.KeyPair",
174 IDR_ENTERPRISE_PLATFORM_KEYS_KEY_PAIR_JS);
175 source_map->RegisterSource("enterprise.platformKeys.SubtleCrypto",
176 IDR_ENTERPRISE_PLATFORM_KEYS_SUBTLE_CRYPTO_JS);
177 source_map->RegisterSource("enterprise.platformKeys.Token",
178 IDR_ENTERPRISE_PLATFORM_KEYS_TOKEN_JS);
179 source_map->RegisterSource("enterprise.platformKeys.utils",
180 IDR_ENTERPRISE_PLATFORM_KEYS_UTILS_JS);
181 source_map->RegisterSource("feedbackPrivate",
182 IDR_FEEDBACK_PRIVATE_CUSTOM_BINDINGS_JS);
183 source_map->RegisterSource("fileBrowserHandler",
184 IDR_FILE_BROWSER_HANDLER_CUSTOM_BINDINGS_JS);
185 source_map->RegisterSource("fileManagerPrivate",
186 IDR_FILE_MANAGER_PRIVATE_CUSTOM_BINDINGS_JS);
187 source_map->RegisterSource("fileSystem", IDR_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
188 source_map->RegisterSource("fileSystemProvider",
189 IDR_FILE_SYSTEM_PROVIDER_CUSTOM_BINDINGS_JS);
190 source_map->RegisterSource("gcm", IDR_GCM_CUSTOM_BINDINGS_JS);
191 source_map->RegisterSource("identity", IDR_IDENTITY_CUSTOM_BINDINGS_JS);
192 source_map->RegisterSource("imageWriterPrivate",
193 IDR_IMAGE_WRITER_PRIVATE_CUSTOM_BINDINGS_JS);
194 source_map->RegisterSource("input.ime", IDR_INPUT_IME_CUSTOM_BINDINGS_JS);
195 source_map->RegisterSource("logPrivate", IDR_LOG_PRIVATE_CUSTOM_BINDINGS_JS);
196 source_map->RegisterSource("mediaGalleries",
197 IDR_MEDIA_GALLERIES_CUSTOM_BINDINGS_JS);
198 source_map->RegisterSource("notifications",
199 IDR_NOTIFICATIONS_CUSTOM_BINDINGS_JS);
200 source_map->RegisterSource("omnibox", IDR_OMNIBOX_CUSTOM_BINDINGS_JS);
201 source_map->RegisterSource("pageAction", IDR_PAGE_ACTION_CUSTOM_BINDINGS_JS);
202 source_map->RegisterSource("pageCapture",
203 IDR_PAGE_CAPTURE_CUSTOM_BINDINGS_JS);
204 source_map->RegisterSource("syncFileSystem",
205 IDR_SYNC_FILE_SYSTEM_CUSTOM_BINDINGS_JS);
206 source_map->RegisterSource("systemIndicator",
207 IDR_SYSTEM_INDICATOR_CUSTOM_BINDINGS_JS);
208 source_map->RegisterSource("tabCapture", IDR_TAB_CAPTURE_CUSTOM_BINDINGS_JS);
209 source_map->RegisterSource("tabs", IDR_TABS_CUSTOM_BINDINGS_JS);
210 source_map->RegisterSource("tts", IDR_TTS_CUSTOM_BINDINGS_JS);
211 source_map->RegisterSource("ttsEngine", IDR_TTS_ENGINE_CUSTOM_BINDINGS_JS);
212 #if defined(ENABLE_WEBRTC)
213 source_map->RegisterSource("cast.streaming.rtpStream",
214 IDR_CAST_STREAMING_RTP_STREAM_CUSTOM_BINDINGS_JS);
215 source_map->RegisterSource("cast.streaming.session",
216 IDR_CAST_STREAMING_SESSION_CUSTOM_BINDINGS_JS);
217 source_map->RegisterSource(
218 "cast.streaming.udpTransport",
219 IDR_CAST_STREAMING_UDP_TRANSPORT_CUSTOM_BINDINGS_JS);
220 #endif
221 source_map->RegisterSource("webstore", IDR_WEBSTORE_CUSTOM_BINDINGS_JS);
223 // Custom types sources.
224 source_map->RegisterSource("ChromeSetting", IDR_CHROME_SETTING_JS);
225 source_map->RegisterSource("ContentSetting", IDR_CONTENT_SETTING_JS);
226 source_map->RegisterSource("ChromeDirectSetting",
227 IDR_CHROME_DIRECT_SETTING_JS);
229 // Platform app sources that are not API-specific..
230 source_map->RegisterSource("appView", IDR_APP_VIEW_JS);
231 source_map->RegisterSource("fileEntryBindingUtil",
232 IDR_FILE_ENTRY_BINDING_UTIL_JS);
233 source_map->RegisterSource("extensionOptions", IDR_EXTENSION_OPTIONS_JS);
234 source_map->RegisterSource("extensionOptionsEvents",
235 IDR_EXTENSION_OPTIONS_EVENTS_JS);
236 source_map->RegisterSource("tagWatcher", IDR_TAG_WATCHER_JS);
237 source_map->RegisterSource("chromeWebViewInternal",
238 IDR_CHROME_WEB_VIEW_INTERNAL_CUSTOM_BINDINGS_JS);
239 source_map->RegisterSource("chromeWebView", IDR_CHROME_WEB_VIEW_JS);
240 source_map->RegisterSource("chromeWebViewExperimental",
241 IDR_CHROME_WEB_VIEW_EXPERIMENTAL_JS);
242 source_map->RegisterSource("denyAppView", IDR_APP_VIEW_DENY_JS);
243 source_map->RegisterSource("injectAppTitlebar", IDR_INJECT_APP_TITLEBAR_JS);
246 void ChromeExtensionsDispatcherDelegate::RequireAdditionalModules(
247 extensions::ScriptContext* context,
248 bool is_within_platform_app) {
249 extensions::ModuleSystem* module_system = context->module_system();
250 extensions::Feature::Context context_type = context->context_type();
252 // TODO(kalman, fsamuel): Eagerly calling Require on context startup is
253 // expensive. It would be better if there were a light way of detecting when
254 // a webview or appview is created and only then set up the infrastructure.
255 if (context_type == extensions::Feature::BLESSED_EXTENSION_CONTEXT &&
256 is_within_platform_app &&
257 extensions::GetCurrentChannel() <= chrome::VersionInfo::CHANNEL_DEV &&
258 CommandLine::ForCurrentProcess()->HasSwitch(
259 extensions::switches::kEnableAppWindowControls)) {
260 module_system->Require("windowControls");
263 // Note: setting up the WebView class here, not the chrome.webview API.
264 // The API will be automatically set up when first used.
265 if (context->GetAvailability("webViewInternal").is_available()) {
266 module_system->Require("chromeWebView");
267 if (context->GetAvailability("webViewExperimentalInternal")
268 .is_available()) {
269 module_system->Require("chromeWebViewExperimental");
273 if (extensions::FeatureSwitch::app_view()->IsEnabled() &&
274 context->GetAvailability("appViewEmbedderInternal").is_available()) {
275 module_system->Require("appView");
276 } else if (context_type == extensions::Feature::BLESSED_EXTENSION_CONTEXT) {
277 module_system->Require("denyAppView");
280 if (extensions::FeatureSwitch::embedded_extension_options()->IsEnabled() &&
281 context->GetAvailability("extensionOptionsInternal").is_available()) {
282 module_system->Require("extensionOptions");
286 void ChromeExtensionsDispatcherDelegate::OnActiveExtensionsUpdated(
287 const std::set<std::string>& extension_ids) {
288 // In single-process mode, the browser process reports the active extensions.
289 if (CommandLine::ForCurrentProcess()->HasSwitch(::switches::kSingleProcess))
290 return;
291 crash_keys::SetActiveExtensions(extension_ids);
294 void ChromeExtensionsDispatcherDelegate::SetChannel(int channel) {
295 extensions::SetCurrentChannel(
296 static_cast<chrome::VersionInfo::Channel>(channel));
299 void ChromeExtensionsDispatcherDelegate::ClearTabSpecificPermissions(
300 const extensions::Dispatcher* dispatcher,
301 int tab_id,
302 const std::vector<std::string>& extension_ids) {
303 for (std::vector<std::string>::const_iterator it = extension_ids.begin();
304 it != extension_ids.end();
305 ++it) {
306 const extensions::Extension* extension =
307 dispatcher->extensions()->GetByID(*it);
308 if (extension)
309 extension->permissions_data()->ClearTabSpecificPermissions(tab_id);
313 void ChromeExtensionsDispatcherDelegate::UpdateTabSpecificPermissions(
314 const extensions::Dispatcher* dispatcher,
315 const GURL& url,
316 int tab_id,
317 const std::string& extension_id,
318 const extensions::URLPatternSet& origin_set) {
319 content::RenderView* view = extensions::TabFinder::Find(tab_id);
321 // For now, the message should only be sent to the render view that contains
322 // the target tab. This may change. Either way, if this is the target tab it
323 // gives us the chance to check against the URL to avoid races.
324 DCHECK(view);
325 GURL active_url(view->GetWebView()->mainFrame()->document().url());
326 if (active_url != url)
327 return;
329 const extensions::Extension* extension =
330 dispatcher->extensions()->GetByID(extension_id);
331 if (!extension)
332 return;
334 extension->permissions_data()->UpdateTabSpecificPermissions(
335 tab_id,
336 new extensions::PermissionSet(extensions::APIPermissionSet(),
337 extensions::ManifestPermissionSet(),
338 origin_set,
339 extensions::URLPatternSet()));