| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "extensions/renderer/dispatcher.h" | 5 #include "extensions/renderer/dispatcher.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
| 11 #include "base/memory/scoped_ptr.h" | 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/metrics/user_metrics_action.h" | 13 #include "base/metrics/user_metrics_action.h" |
| 14 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
| 15 #include "base/strings/string_split.h" | 15 #include "base/strings/string_split.h" |
| 16 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "base/values.h" | 18 #include "base/values.h" |
| 19 #include "content/grit/content_resources.h" | 19 #include "content/grit/content_resources.h" |
| 20 #include "content/public/child/v8_value_converter.h" | 20 #include "content/public/child/v8_value_converter.h" |
| 21 #include "content/public/common/content_switches.h" | 21 #include "content/public/common/content_switches.h" |
| 22 #include "content/public/common/url_constants.h" | 22 #include "content/public/common/url_constants.h" |
| 23 #include "content/public/renderer/render_thread.h" | 23 #include "content/public/renderer/render_thread.h" |
| 24 #include "content/public/renderer/render_view.h" | 24 #include "content/public/renderer/render_view.h" |
| 25 #include "extensions/common/api/messaging/message.h" | 25 #include "extensions/common/api/messaging/message.h" |
| 26 #include "extensions/common/constants.h" | 26 #include "extensions/common/constants.h" |
| 27 #include "extensions/common/extension.h" | |
| 28 #include "extensions/common/extension_api.h" | 27 #include "extensions/common/extension_api.h" |
| 29 #include "extensions/common/extension_messages.h" | 28 #include "extensions/common/extension_messages.h" |
| 30 #include "extensions/common/extension_urls.h" | 29 #include "extensions/common/extension_urls.h" |
| 31 #include "extensions/common/feature_switch.h" | 30 #include "extensions/common/feature_switch.h" |
| 32 #include "extensions/common/features/feature.h" | 31 #include "extensions/common/features/feature.h" |
| 33 #include "extensions/common/features/feature_provider.h" | 32 #include "extensions/common/features/feature_provider.h" |
| 34 #include "extensions/common/manifest.h" | 33 #include "extensions/common/manifest.h" |
| 35 #include "extensions/common/manifest_constants.h" | 34 #include "extensions/common/manifest_constants.h" |
| 36 #include "extensions/common/manifest_handlers/background_info.h" | 35 #include "extensions/common/manifest_handlers/background_info.h" |
| 37 #include "extensions/common/manifest_handlers/content_capabilities_handler.h" | 36 #include "extensions/common/manifest_handlers/content_capabilities_handler.h" |
| 38 #include "extensions/common/manifest_handlers/externally_connectable.h" | 37 #include "extensions/common/manifest_handlers/externally_connectable.h" |
| 39 #include "extensions/common/manifest_handlers/options_page_info.h" | 38 #include "extensions/common/manifest_handlers/options_page_info.h" |
| 40 #include "extensions/common/manifest_handlers/sandboxed_page_info.h" | |
| 41 #include "extensions/common/message_bundle.h" | 39 #include "extensions/common/message_bundle.h" |
| 42 #include "extensions/common/permissions/permission_set.h" | 40 #include "extensions/common/permissions/permission_set.h" |
| 43 #include "extensions/common/permissions/permissions_data.h" | 41 #include "extensions/common/permissions/permissions_data.h" |
| 44 #include "extensions/common/switches.h" | 42 #include "extensions/common/switches.h" |
| 45 #include "extensions/common/view_type.h" | 43 #include "extensions/common/view_type.h" |
| 46 #include "extensions/renderer/api_activity_logger.h" | 44 #include "extensions/renderer/api_activity_logger.h" |
| 47 #include "extensions/renderer/api_definitions_natives.h" | 45 #include "extensions/renderer/api_definitions_natives.h" |
| 48 #include "extensions/renderer/app_runtime_custom_bindings.h" | 46 #include "extensions/renderer/app_runtime_custom_bindings.h" |
| 49 #include "extensions/renderer/app_window_custom_bindings.h" | 47 #include "extensions/renderer/app_window_custom_bindings.h" |
| 50 #include "extensions/renderer/binding_generating_native_handler.h" | 48 #include "extensions/renderer/binding_generating_native_handler.h" |
| 51 #include "extensions/renderer/blob_native_handler.h" | 49 #include "extensions/renderer/blob_native_handler.h" |
| 52 #include "extensions/renderer/content_watcher.h" | 50 #include "extensions/renderer/content_watcher.h" |
| 53 #include "extensions/renderer/context_menus_custom_bindings.h" | 51 #include "extensions/renderer/context_menus_custom_bindings.h" |
| 54 #include "extensions/renderer/css_native_handler.h" | 52 #include "extensions/renderer/css_native_handler.h" |
| 55 #include "extensions/renderer/dispatcher_delegate.h" | 53 #include "extensions/renderer/dispatcher_delegate.h" |
| 56 #include "extensions/renderer/document_custom_bindings.h" | 54 #include "extensions/renderer/document_custom_bindings.h" |
| 57 #include "extensions/renderer/dom_activity_logger.h" | 55 #include "extensions/renderer/dom_activity_logger.h" |
| 58 #include "extensions/renderer/event_bindings.h" | 56 #include "extensions/renderer/event_bindings.h" |
| 59 #include "extensions/renderer/extension_groups.h" | |
| 60 #include "extensions/renderer/extension_helper.h" | 57 #include "extensions/renderer/extension_helper.h" |
| 61 #include "extensions/renderer/extensions_renderer_client.h" | 58 #include "extensions/renderer/extensions_renderer_client.h" |
| 62 #include "extensions/renderer/file_system_natives.h" | 59 #include "extensions/renderer/file_system_natives.h" |
| 63 #include "extensions/renderer/guest_view/guest_view_internal_custom_bindings.h" | 60 #include "extensions/renderer/guest_view/guest_view_internal_custom_bindings.h" |
| 64 #include "extensions/renderer/i18n_custom_bindings.h" | 61 #include "extensions/renderer/i18n_custom_bindings.h" |
| 65 #include "extensions/renderer/id_generator_custom_bindings.h" | 62 #include "extensions/renderer/id_generator_custom_bindings.h" |
| 66 #include "extensions/renderer/lazy_background_page_native_handler.h" | 63 #include "extensions/renderer/lazy_background_page_native_handler.h" |
| 67 #include "extensions/renderer/logging_native_handler.h" | 64 #include "extensions/renderer/logging_native_handler.h" |
| 68 #include "extensions/renderer/messaging_bindings.h" | 65 #include "extensions/renderer/messaging_bindings.h" |
| 69 #include "extensions/renderer/module_system.h" | 66 #include "extensions/renderer/module_system.h" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 command_line.HasSwitch(switches::kExtensionProcess) || | 195 command_line.HasSwitch(switches::kExtensionProcess) || |
| 199 command_line.HasSwitch(::switches::kSingleProcess); | 196 command_line.HasSwitch(::switches::kSingleProcess); |
| 200 | 197 |
| 201 if (set_idle_notifications_) { | 198 if (set_idle_notifications_) { |
| 202 RenderThread::Get()->SetIdleNotificationDelayInMs( | 199 RenderThread::Get()->SetIdleNotificationDelayInMs( |
| 203 kInitialExtensionIdleHandlerDelayMs); | 200 kInitialExtensionIdleHandlerDelayMs); |
| 204 } | 201 } |
| 205 | 202 |
| 206 RenderThread::Get()->RegisterExtension(SafeBuiltins::CreateV8Extension()); | 203 RenderThread::Get()->RegisterExtension(SafeBuiltins::CreateV8Extension()); |
| 207 | 204 |
| 205 script_context_set_.reset( |
| 206 new ScriptContextSet(&extensions_, &active_extension_ids_)); |
| 208 user_script_set_manager_.reset(new UserScriptSetManager(&extensions_)); | 207 user_script_set_manager_.reset(new UserScriptSetManager(&extensions_)); |
| 209 script_injection_manager_.reset( | 208 script_injection_manager_.reset( |
| 210 new ScriptInjectionManager(&extensions_, user_script_set_manager_.get())); | 209 new ScriptInjectionManager(&extensions_, user_script_set_manager_.get())); |
| 211 user_script_set_manager_observer_.Add(user_script_set_manager_.get()); | 210 user_script_set_manager_observer_.Add(user_script_set_manager_.get()); |
| 212 request_sender_.reset(new RequestSender(this)); | 211 request_sender_.reset(new RequestSender(this)); |
| 213 PopulateSourceMap(); | 212 PopulateSourceMap(); |
| 214 } | 213 } |
| 215 | 214 |
| 216 Dispatcher::~Dispatcher() { | 215 Dispatcher::~Dispatcher() { |
| 217 } | 216 } |
| 218 | 217 |
| 219 void Dispatcher::OnRenderViewCreated(content::RenderView* render_view) { | 218 void Dispatcher::OnRenderViewCreated(content::RenderView* render_view) { |
| 220 script_injection_manager_->OnRenderViewCreated(render_view); | 219 script_injection_manager_->OnRenderViewCreated(render_view); |
| 221 } | 220 } |
| 222 | 221 |
| 223 bool Dispatcher::IsExtensionActive(const std::string& extension_id) const { | 222 bool Dispatcher::IsExtensionActive(const std::string& extension_id) const { |
| 224 bool is_active = | 223 bool is_active = |
| 225 active_extension_ids_.find(extension_id) != active_extension_ids_.end(); | 224 active_extension_ids_.find(extension_id) != active_extension_ids_.end(); |
| 226 if (is_active) | 225 if (is_active) |
| 227 CHECK(extensions_.Contains(extension_id)); | 226 CHECK(extensions_.Contains(extension_id)); |
| 228 return is_active; | 227 return is_active; |
| 229 } | 228 } |
| 230 | 229 |
| 231 const Extension* Dispatcher::GetExtensionFromFrameAndWorld( | |
| 232 const blink::WebFrame* frame, | |
| 233 int world_id, | |
| 234 bool use_effective_url) { | |
| 235 std::string extension_id; | |
| 236 if (world_id != 0) { | |
| 237 // Isolated worlds (content script). | |
| 238 extension_id = ScriptInjection::GetHostIdForIsolatedWorld(world_id); | |
| 239 } else if (!frame->document().securityOrigin().isUnique()) { | |
| 240 // TODO(kalman): Delete the above check. | |
| 241 | |
| 242 // Extension pages (chrome-extension:// URLs). | |
| 243 GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame); | |
| 244 frame_url = ScriptContext::GetEffectiveDocumentURL( | |
| 245 frame, frame_url, use_effective_url); | |
| 246 extension_id = extensions_.GetExtensionOrAppIDByURL(frame_url); | |
| 247 } | |
| 248 | |
| 249 const Extension* extension = extensions_.GetByID(extension_id); | |
| 250 if (!extension && !extension_id.empty()) { | |
| 251 // There are conditions where despite a context being associated with an | |
| 252 // extension, no extension actually gets found. Ignore "invalid" because | |
| 253 // CSP blocks extension page loading by switching the extension ID to | |
| 254 // "invalid". This isn't interesting. | |
| 255 if (extension_id != "invalid") { | |
| 256 LOG(ERROR) << "Extension \"" << extension_id << "\" not found"; | |
| 257 RenderThread::Get()->RecordAction( | |
| 258 UserMetricsAction("ExtensionNotFound_ED")); | |
| 259 } | |
| 260 } | |
| 261 return extension; | |
| 262 } | |
| 263 | |
| 264 void Dispatcher::DidCreateScriptContext( | 230 void Dispatcher::DidCreateScriptContext( |
| 265 blink::WebLocalFrame* frame, | 231 blink::WebLocalFrame* frame, |
| 266 const v8::Handle<v8::Context>& v8_context, | 232 const v8::Handle<v8::Context>& v8_context, |
| 267 int extension_group, | 233 int extension_group, |
| 268 int world_id) { | 234 int world_id) { |
| 269 const base::TimeTicks start_time = base::TimeTicks::Now(); | 235 const base::TimeTicks start_time = base::TimeTicks::Now(); |
| 270 | 236 |
| 271 const Extension* extension = | 237 ScriptContext* context = script_context_set_->Register( |
| 272 GetExtensionFromFrameAndWorld(frame, world_id, false); | 238 frame, v8_context, extension_group, world_id); |
| 273 const Extension* effective_extension = | |
| 274 GetExtensionFromFrameAndWorld(frame, world_id, true); | |
| 275 | |
| 276 GURL frame_url = ScriptContext::GetDataSourceURLForFrame(frame); | |
| 277 Feature::Context context_type = | |
| 278 ClassifyJavaScriptContext(extension, | |
| 279 extension_group, | |
| 280 frame_url, | |
| 281 frame->document().securityOrigin()); | |
| 282 Feature::Context effective_context_type = ClassifyJavaScriptContext( | |
| 283 effective_extension, | |
| 284 extension_group, | |
| 285 ScriptContext::GetEffectiveDocumentURL(frame, frame_url, true), | |
| 286 frame->document().securityOrigin()); | |
| 287 | |
| 288 ScriptContext* context = | |
| 289 new ScriptContext(v8_context, frame, extension, context_type, | |
| 290 effective_extension, effective_context_type); | |
| 291 script_context_set_.Add(context); | |
| 292 | 239 |
| 293 // Initialize origin permissions for content scripts, which can't be | 240 // Initialize origin permissions for content scripts, which can't be |
| 294 // initialized in |OnActivateExtension|. | 241 // initialized in |OnActivateExtension|. |
| 295 if (context_type == Feature::CONTENT_SCRIPT_CONTEXT) | 242 if (context->context_type() == Feature::CONTENT_SCRIPT_CONTEXT) |
| 296 InitOriginPermissions(extension); | 243 InitOriginPermissions(context->extension()); |
| 297 | 244 |
| 298 { | 245 { |
| 299 scoped_ptr<ModuleSystem> module_system( | 246 scoped_ptr<ModuleSystem> module_system( |
| 300 new ModuleSystem(context, &source_map_)); | 247 new ModuleSystem(context, &source_map_)); |
| 301 context->set_module_system(module_system.Pass()); | 248 context->set_module_system(module_system.Pass()); |
| 302 } | 249 } |
| 303 ModuleSystem* module_system = context->module_system(); | 250 ModuleSystem* module_system = context->module_system(); |
| 304 | 251 |
| 305 // Enable natives in startup. | 252 // Enable natives in startup. |
| 306 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system); | 253 ModuleSystem::NativesEnabledScope natives_enabled_scope(module_system); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 319 UpdateBindingsForContext(context); | 266 UpdateBindingsForContext(context); |
| 320 | 267 |
| 321 bool is_within_platform_app = IsWithinPlatformApp(); | 268 bool is_within_platform_app = IsWithinPlatformApp(); |
| 322 // Inject custom JS into the platform app context. | 269 // Inject custom JS into the platform app context. |
| 323 if (is_within_platform_app) { | 270 if (is_within_platform_app) { |
| 324 module_system->Require("platformApp"); | 271 module_system->Require("platformApp"); |
| 325 } | 272 } |
| 326 | 273 |
| 327 if (context->GetAvailability("appViewEmbedderInternal").is_available()) { | 274 if (context->GetAvailability("appViewEmbedderInternal").is_available()) { |
| 328 module_system->Require("appView"); | 275 module_system->Require("appView"); |
| 329 } else if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { | 276 } else if (context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT) { |
| 330 module_system->Require("appViewDeny"); | 277 module_system->Require("appViewDeny"); |
| 331 } | 278 } |
| 332 | 279 |
| 333 if (extensions::FeatureSwitch::surface_worker()->IsEnabled() && | 280 if (extensions::FeatureSwitch::surface_worker()->IsEnabled() && |
| 334 context->GetAvailability("surfaceWorkerInternal").is_available()) { | 281 context->GetAvailability("surfaceWorkerInternal").is_available()) { |
| 335 module_system->Require("surfaceWorker"); | 282 module_system->Require("surfaceWorker"); |
| 336 } | 283 } |
| 337 | 284 |
| 338 if (context->GetAvailability("extensionViewInternal").is_available()) { | 285 if (context->GetAvailability("extensionViewInternal").is_available()) { |
| 339 module_system->Require("extensionView"); | 286 module_system->Require("extensionView"); |
| 340 module_system->Require("extensionViewApiMethods"); | 287 module_system->Require("extensionViewApiMethods"); |
| 341 module_system->Require("extensionViewAttributes"); | 288 module_system->Require("extensionViewAttributes"); |
| 342 } | 289 } |
| 343 | 290 |
| 344 // Note: setting up the WebView class here, not the chrome.webview API. | 291 // Note: setting up the WebView class here, not the chrome.webview API. |
| 345 // The API will be automatically set up when first used. | 292 // The API will be automatically set up when first used. |
| 346 if (context->GetAvailability("webViewInternal").is_available()) { | 293 if (context->GetAvailability("webViewInternal").is_available()) { |
| 347 module_system->Require("webView"); | 294 module_system->Require("webView"); |
| 348 module_system->Require("webViewApiMethods"); | 295 module_system->Require("webViewApiMethods"); |
| 349 module_system->Require("webViewAttributes"); | 296 module_system->Require("webViewAttributes"); |
| 350 if (context->GetAvailability("webViewExperimentalInternal") | 297 if (context->GetAvailability("webViewExperimentalInternal") |
| 351 .is_available()) { | 298 .is_available()) { |
| 352 module_system->Require("webViewExperimental"); | 299 module_system->Require("webViewExperimental"); |
| 353 } | 300 } |
| 354 } else if (context_type == Feature::BLESSED_EXTENSION_CONTEXT) { | 301 } else if (context->context_type() == Feature::BLESSED_EXTENSION_CONTEXT) { |
| 355 module_system->Require("webViewDeny"); | 302 module_system->Require("webViewDeny"); |
| 356 } | 303 } |
| 357 | 304 |
| 358 delegate_->RequireAdditionalModules(context, is_within_platform_app); | 305 delegate_->RequireAdditionalModules(context, is_within_platform_app); |
| 359 | 306 |
| 360 const base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; | 307 const base::TimeDelta elapsed = base::TimeTicks::Now() - start_time; |
| 361 switch (context_type) { | 308 switch (context->context_type()) { |
| 362 case Feature::UNSPECIFIED_CONTEXT: | 309 case Feature::UNSPECIFIED_CONTEXT: |
| 363 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unspecified", | 310 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unspecified", |
| 364 elapsed); | 311 elapsed); |
| 365 break; | 312 break; |
| 366 case Feature::BLESSED_EXTENSION_CONTEXT: | 313 case Feature::BLESSED_EXTENSION_CONTEXT: |
| 367 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Blessed", elapsed); | 314 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Blessed", elapsed); |
| 368 break; | 315 break; |
| 369 case Feature::UNBLESSED_EXTENSION_CONTEXT: | 316 case Feature::UNBLESSED_EXTENSION_CONTEXT: |
| 370 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unblessed", | 317 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_Unblessed", |
| 371 elapsed); | 318 elapsed); |
| 372 break; | 319 break; |
| 373 case Feature::CONTENT_SCRIPT_CONTEXT: | 320 case Feature::CONTENT_SCRIPT_CONTEXT: |
| 374 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_ContentScript", | 321 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_ContentScript", |
| 375 elapsed); | 322 elapsed); |
| 376 break; | 323 break; |
| 377 case Feature::WEB_PAGE_CONTEXT: | 324 case Feature::WEB_PAGE_CONTEXT: |
| 378 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebPage", elapsed); | 325 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebPage", elapsed); |
| 379 break; | 326 break; |
| 380 case Feature::BLESSED_WEB_PAGE_CONTEXT: | 327 case Feature::BLESSED_WEB_PAGE_CONTEXT: |
| 381 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_BlessedWebPage", | 328 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_BlessedWebPage", |
| 382 elapsed); | 329 elapsed); |
| 383 break; | 330 break; |
| 384 case Feature::WEBUI_CONTEXT: | 331 case Feature::WEBUI_CONTEXT: |
| 385 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebUI", elapsed); | 332 UMA_HISTOGRAM_TIMES("Extensions.DidCreateScriptContext_WebUI", elapsed); |
| 386 break; | 333 break; |
| 387 } | 334 } |
| 388 | 335 |
| 389 VLOG(1) << "Num tracked contexts: " << script_context_set_.size(); | 336 VLOG(1) << "Num tracked contexts: " << script_context_set_->size(); |
| 390 } | 337 } |
| 391 | 338 |
| 392 void Dispatcher::WillReleaseScriptContext( | 339 void Dispatcher::WillReleaseScriptContext( |
| 393 blink::WebLocalFrame* frame, | 340 blink::WebLocalFrame* frame, |
| 394 const v8::Handle<v8::Context>& v8_context, | 341 const v8::Handle<v8::Context>& v8_context, |
| 395 int world_id) { | 342 int world_id) { |
| 396 ScriptContext* context = script_context_set_.GetByV8Context(v8_context); | 343 ScriptContext* context = script_context_set_->GetByV8Context(v8_context); |
| 397 if (!context) | 344 if (!context) |
| 398 return; | 345 return; |
| 399 | 346 |
| 400 context->DispatchOnUnloadEvent(); | 347 context->DispatchOnUnloadEvent(); |
| 401 // TODO(kalman): add an invalidation observer interface to ScriptContext. | 348 // TODO(kalman): add an invalidation observer interface to ScriptContext. |
| 402 request_sender_->InvalidateSource(context); | 349 request_sender_->InvalidateSource(context); |
| 403 | 350 |
| 404 script_context_set_.Remove(context); | 351 script_context_set_->Remove(context); |
| 405 VLOG(1) << "Num tracked contexts: " << script_context_set_.size(); | 352 VLOG(1) << "Num tracked contexts: " << script_context_set_->size(); |
| 406 } | 353 } |
| 407 | 354 |
| 408 void Dispatcher::DidCreateDocumentElement(blink::WebFrame* frame) { | 355 void Dispatcher::DidCreateDocumentElement(blink::WebFrame* frame) { |
| 409 // Note: use GetEffectiveDocumentURL not just frame->document()->url() | 356 // Note: use GetEffectiveDocumentURL not just frame->document()->url() |
| 410 // so that this also injects the stylesheet on about:blank frames that | 357 // so that this also injects the stylesheet on about:blank frames that |
| 411 // are hosted in the extension process. | 358 // are hosted in the extension process. |
| 412 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( | 359 GURL effective_document_url = ScriptContext::GetEffectiveDocumentURL( |
| 413 frame, frame->document().url(), true /* match_about_blank */); | 360 frame, frame->document().url(), true /* match_about_blank */); |
| 414 | 361 |
| 415 const Extension* extension = | 362 const Extension* extension = |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 466 const std::string& function_name, | 413 const std::string& function_name, |
| 467 ScriptContext* context) const { | 414 ScriptContext* context) const { |
| 468 if (!context) { | 415 if (!context) { |
| 469 DLOG(ERROR) << "Not in a v8::Context"; | 416 DLOG(ERROR) << "Not in a v8::Context"; |
| 470 return false; | 417 return false; |
| 471 } | 418 } |
| 472 | 419 |
| 473 // Theoretically we could end up with bindings being injected into sandboxed | 420 // Theoretically we could end up with bindings being injected into sandboxed |
| 474 // frames, for example content scripts. Don't let them execute API functions. | 421 // frames, for example content scripts. Don't let them execute API functions. |
| 475 blink::WebFrame* frame = context->web_frame(); | 422 blink::WebFrame* frame = context->web_frame(); |
| 476 if (IsSandboxedPage(ScriptContext::GetDataSourceURLForFrame(frame))) { | 423 if (ScriptContext::IsSandboxedPage( |
| 424 extensions_, ScriptContext::GetDataSourceURLForFrame(frame))) { |
| 477 static const char kMessage[] = | 425 static const char kMessage[] = |
| 478 "%s cannot be used within a sandboxed frame."; | 426 "%s cannot be used within a sandboxed frame."; |
| 479 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); | 427 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); |
| 480 context->isolate()->ThrowException(v8::Exception::Error( | 428 context->isolate()->ThrowException(v8::Exception::Error( |
| 481 v8::String::NewFromUtf8(context->isolate(), error_msg.c_str()))); | 429 v8::String::NewFromUtf8(context->isolate(), error_msg.c_str()))); |
| 482 return false; | 430 return false; |
| 483 } | 431 } |
| 484 | 432 |
| 485 Feature::Availability availability = context->GetAvailability(function_name); | 433 Feature::Availability availability = context->GetAvailability(function_name); |
| 486 if (!availability.is_available()) { | 434 if (!availability.is_available()) { |
| 487 context->isolate()->ThrowException( | 435 context->isolate()->ThrowException( |
| 488 v8::Exception::Error(v8::String::NewFromUtf8( | 436 v8::Exception::Error(v8::String::NewFromUtf8( |
| 489 context->isolate(), availability.message().c_str()))); | 437 context->isolate(), availability.message().c_str()))); |
| 490 } | 438 } |
| 491 | 439 |
| 492 return availability.is_available(); | 440 return availability.is_available(); |
| 493 } | 441 } |
| 494 | 442 |
| 495 void Dispatcher::DispatchEvent(const std::string& extension_id, | 443 void Dispatcher::DispatchEvent(const std::string& extension_id, |
| 496 const std::string& event_name) const { | 444 const std::string& event_name) const { |
| 497 base::ListValue args; | 445 base::ListValue args; |
| 498 args.Set(0, new base::StringValue(event_name)); | 446 args.Set(0, new base::StringValue(event_name)); |
| 499 args.Set(1, new base::ListValue()); | 447 args.Set(1, new base::ListValue()); |
| 500 | 448 |
| 501 // Needed for Windows compilation, since kEventBindings is declared extern. | 449 // Needed for Windows compilation, since kEventBindings is declared extern. |
| 502 const char* local_event_bindings = kEventBindings; | 450 const char* local_event_bindings = kEventBindings; |
| 503 script_context_set_.ForEach(extension_id, | 451 script_context_set_->ForEach( |
| 504 base::Bind(&CallModuleMethod, | 452 extension_id, base::Bind(&CallModuleMethod, local_event_bindings, |
| 505 local_event_bindings, | 453 kEventDispatchFunction, &args)); |
| 506 kEventDispatchFunction, | |
| 507 &args)); | |
| 508 } | 454 } |
| 509 | 455 |
| 510 void Dispatcher::InvokeModuleSystemMethod(content::RenderView* render_view, | 456 void Dispatcher::InvokeModuleSystemMethod(content::RenderView* render_view, |
| 511 const std::string& extension_id, | 457 const std::string& extension_id, |
| 512 const std::string& module_name, | 458 const std::string& module_name, |
| 513 const std::string& function_name, | 459 const std::string& function_name, |
| 514 const base::ListValue& args, | 460 const base::ListValue& args, |
| 515 bool user_gesture) { | 461 bool user_gesture) { |
| 516 scoped_ptr<WebScopedUserGesture> web_user_gesture; | 462 scoped_ptr<WebScopedUserGesture> web_user_gesture; |
| 517 if (user_gesture) | 463 if (user_gesture) |
| 518 web_user_gesture.reset(new WebScopedUserGesture); | 464 web_user_gesture.reset(new WebScopedUserGesture); |
| 519 | 465 |
| 520 script_context_set_.ForEach( | 466 script_context_set_->ForEach( |
| 521 extension_id, | 467 extension_id, render_view, |
| 522 render_view, | |
| 523 base::Bind(&CallModuleMethod, module_name, function_name, &args)); | 468 base::Bind(&CallModuleMethod, module_name, function_name, &args)); |
| 524 | 469 |
| 525 // Reset the idle handler each time there's any activity like event or message | 470 // Reset the idle handler each time there's any activity like event or message |
| 526 // dispatch, for which Invoke is the chokepoint. | 471 // dispatch, for which Invoke is the chokepoint. |
| 527 if (set_idle_notifications_) { | 472 if (set_idle_notifications_) { |
| 528 RenderThread::Get()->ScheduleIdleHandler( | 473 RenderThread::Get()->ScheduleIdleHandler( |
| 529 kInitialExtensionIdleHandlerDelayMs); | 474 kInitialExtensionIdleHandlerDelayMs); |
| 530 } | 475 } |
| 531 | 476 |
| 532 // Tell the browser process when an event has been dispatched with a lazy | 477 // Tell the browser process when an event has been dispatched with a lazy |
| (...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 920 | 865 |
| 921 void Dispatcher::OnDeliverMessage(int target_port_id, const Message& message) { | 866 void Dispatcher::OnDeliverMessage(int target_port_id, const Message& message) { |
| 922 scoped_ptr<RequestSender::ScopedTabID> scoped_tab_id; | 867 scoped_ptr<RequestSender::ScopedTabID> scoped_tab_id; |
| 923 std::map<int, int>::const_iterator it = | 868 std::map<int, int>::const_iterator it = |
| 924 port_to_tab_id_map_.find(target_port_id); | 869 port_to_tab_id_map_.find(target_port_id); |
| 925 if (it != port_to_tab_id_map_.end()) { | 870 if (it != port_to_tab_id_map_.end()) { |
| 926 scoped_tab_id.reset( | 871 scoped_tab_id.reset( |
| 927 new RequestSender::ScopedTabID(request_sender(), it->second)); | 872 new RequestSender::ScopedTabID(request_sender(), it->second)); |
| 928 } | 873 } |
| 929 | 874 |
| 930 MessagingBindings::DeliverMessage(script_context_set_, | 875 MessagingBindings::DeliverMessage(*script_context_set_, target_port_id, |
| 931 target_port_id, | |
| 932 message, | 876 message, |
| 933 NULL); // All render frames. | 877 NULL); // All render frames. |
| 934 } | 878 } |
| 935 | 879 |
| 936 void Dispatcher::OnDispatchOnConnect( | 880 void Dispatcher::OnDispatchOnConnect( |
| 937 int target_port_id, | 881 int target_port_id, |
| 938 const std::string& channel_name, | 882 const std::string& channel_name, |
| 939 const ExtensionMsg_TabConnectionInfo& source, | 883 const ExtensionMsg_TabConnectionInfo& source, |
| 940 const ExtensionMsg_ExternalConnectionInfo& info, | 884 const ExtensionMsg_ExternalConnectionInfo& info, |
| 941 const std::string& tls_channel_id) { | 885 const std::string& tls_channel_id) { |
| 942 DCHECK(!ContainsKey(port_to_tab_id_map_, target_port_id)); | 886 DCHECK(!ContainsKey(port_to_tab_id_map_, target_port_id)); |
| 943 DCHECK_EQ(1, target_port_id % 2); // target renderer ports have odd IDs. | 887 DCHECK_EQ(1, target_port_id % 2); // target renderer ports have odd IDs. |
| 944 int sender_tab_id = -1; | 888 int sender_tab_id = -1; |
| 945 source.tab.GetInteger("id", &sender_tab_id); | 889 source.tab.GetInteger("id", &sender_tab_id); |
| 946 port_to_tab_id_map_[target_port_id] = sender_tab_id; | 890 port_to_tab_id_map_[target_port_id] = sender_tab_id; |
| 947 | 891 |
| 948 MessagingBindings::DispatchOnConnect(script_context_set_, | 892 MessagingBindings::DispatchOnConnect(*script_context_set_, target_port_id, |
| 949 target_port_id, | 893 channel_name, source, info, |
| 950 channel_name, | |
| 951 source, | |
| 952 info, | |
| 953 tls_channel_id, | 894 tls_channel_id, |
| 954 NULL); // All render frames. | 895 NULL); // All render frames. |
| 955 } | 896 } |
| 956 | 897 |
| 957 void Dispatcher::OnDispatchOnDisconnect(int port_id, | 898 void Dispatcher::OnDispatchOnDisconnect(int port_id, |
| 958 const std::string& error_message) { | 899 const std::string& error_message) { |
| 959 MessagingBindings::DispatchOnDisconnect(script_context_set_, | 900 MessagingBindings::DispatchOnDisconnect(*script_context_set_, port_id, |
| 960 port_id, | |
| 961 error_message, | 901 error_message, |
| 962 NULL); // All render frames. | 902 NULL); // All render frames. |
| 963 } | 903 } |
| 964 | 904 |
| 965 void Dispatcher::OnLoaded( | 905 void Dispatcher::OnLoaded( |
| 966 const std::vector<ExtensionMsg_Loaded_Params>& loaded_extensions) { | 906 const std::vector<ExtensionMsg_Loaded_Params>& loaded_extensions) { |
| 967 std::vector<ExtensionMsg_Loaded_Params>::const_iterator i; | 907 std::vector<ExtensionMsg_Loaded_Params>::const_iterator i; |
| 968 for (i = loaded_extensions.begin(); i != loaded_extensions.end(); ++i) { | 908 for (i = loaded_extensions.begin(); i != loaded_extensions.end(); ++i) { |
| 969 std::string error; | 909 std::string error; |
| 970 scoped_refptr<const Extension> extension = i->ConvertToExtension(&error); | 910 scoped_refptr<const Extension> extension = i->ConvertToExtension(&error); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 | 980 |
| 1041 script_injection_manager_->OnExtensionUnloaded(id); | 981 script_injection_manager_->OnExtensionUnloaded(id); |
| 1042 | 982 |
| 1043 // If the extension is later reloaded with a different set of permissions, | 983 // If the extension is later reloaded with a different set of permissions, |
| 1044 // we'd like it to get a new isolated world ID, so that it can pick up the | 984 // we'd like it to get a new isolated world ID, so that it can pick up the |
| 1045 // changed origin whitelist. | 985 // changed origin whitelist. |
| 1046 ScriptInjection::RemoveIsolatedWorld(id); | 986 ScriptInjection::RemoveIsolatedWorld(id); |
| 1047 | 987 |
| 1048 // Invalidate all of the contexts that were removed. | 988 // Invalidate all of the contexts that were removed. |
| 1049 // TODO(kalman): add an invalidation observer interface to ScriptContext. | 989 // TODO(kalman): add an invalidation observer interface to ScriptContext. |
| 1050 ScriptContextSet::ContextSet removed_contexts = | 990 std::set<ScriptContext*> removed_contexts = |
| 1051 script_context_set_.OnExtensionUnloaded(id); | 991 script_context_set_->OnExtensionUnloaded(id); |
| 1052 for (ScriptContextSet::ContextSet::iterator it = removed_contexts.begin(); | 992 for (ScriptContext* context : removed_contexts) { |
| 1053 it != removed_contexts.end(); | 993 request_sender_->InvalidateSource(context); |
| 1054 ++it) { | |
| 1055 request_sender_->InvalidateSource(*it); | |
| 1056 } | 994 } |
| 1057 | 995 |
| 1058 // Update the available bindings for the remaining contexts. These may have | 996 // Update the available bindings for the remaining contexts. These may have |
| 1059 // changed if an externally_connectable extension is unloaded and a webpage | 997 // changed if an externally_connectable extension is unloaded and a webpage |
| 1060 // is no longer accessible. | 998 // is no longer accessible. |
| 1061 UpdateBindings(""); | 999 UpdateBindings(""); |
| 1062 | 1000 |
| 1063 // Invalidates the messages map for the extension in case the extension is | 1001 // Invalidates the messages map for the extension in case the extension is |
| 1064 // reloaded with a new messages map. | 1002 // reloaded with a new messages map. |
| 1065 EraseL10nMessagesMap(id); | 1003 EraseL10nMessagesMap(id); |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1411 for (std::set<std::string>::iterator iter = active_extension_ids_.begin(); | 1349 for (std::set<std::string>::iterator iter = active_extension_ids_.begin(); |
| 1412 iter != active_extension_ids_.end(); | 1350 iter != active_extension_ids_.end(); |
| 1413 ++iter) { | 1351 ++iter) { |
| 1414 const Extension* extension = extensions_.GetByID(*iter); | 1352 const Extension* extension = extensions_.GetByID(*iter); |
| 1415 if (extension && extension->is_platform_app()) | 1353 if (extension && extension->is_platform_app()) |
| 1416 return true; | 1354 return true; |
| 1417 } | 1355 } |
| 1418 return false; | 1356 return false; |
| 1419 } | 1357 } |
| 1420 | 1358 |
| 1421 // TODO(kalman): This is checking for the wrong thing, it should be checking if | |
| 1422 // the frame's security origin is unique. The extension sandbox directive is | |
| 1423 // checked for in extensions/common/manifest_handlers/csp_info.cc. | |
| 1424 bool Dispatcher::IsSandboxedPage(const GURL& url) const { | |
| 1425 if (url.SchemeIs(kExtensionScheme)) { | |
| 1426 const Extension* extension = extensions_.GetByID(url.host()); | |
| 1427 if (extension) { | |
| 1428 return SandboxedPageInfo::IsSandboxedPage(extension, url.path()); | |
| 1429 } | |
| 1430 } | |
| 1431 return false; | |
| 1432 } | |
| 1433 | |
| 1434 Feature::Context Dispatcher::ClassifyJavaScriptContext( | |
| 1435 const Extension* extension, | |
| 1436 int extension_group, | |
| 1437 const GURL& url, | |
| 1438 const blink::WebSecurityOrigin& origin) { | |
| 1439 // WARNING: This logic must match ProcessMap::GetContextType, as much as | |
| 1440 // possible. | |
| 1441 | |
| 1442 DCHECK_GE(extension_group, 0); | |
| 1443 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) { | |
| 1444 return extension ? // TODO(kalman): when does this happen? | |
| 1445 Feature::CONTENT_SCRIPT_CONTEXT | |
| 1446 : Feature::UNSPECIFIED_CONTEXT; | |
| 1447 } | |
| 1448 | |
| 1449 // We have an explicit check for sandboxed pages before checking whether the | |
| 1450 // extension is active in this process because: | |
| 1451 // 1. Sandboxed pages run in the same process as regular extension pages, so | |
| 1452 // the extension is considered active. | |
| 1453 // 2. ScriptContext creation (which triggers bindings injection) happens | |
| 1454 // before the SecurityContext is updated with the sandbox flags (after | |
| 1455 // reading the CSP header), so the caller can't check if the context's | |
| 1456 // security origin is unique yet. | |
| 1457 if (IsSandboxedPage(url)) | |
| 1458 return Feature::WEB_PAGE_CONTEXT; | |
| 1459 | |
| 1460 if (extension && IsExtensionActive(extension->id())) { | |
| 1461 // |extension| is active in this process, but it could be either a true | |
| 1462 // extension process or within the extent of a hosted app. In the latter | |
| 1463 // case this would usually be considered a (blessed) web page context, | |
| 1464 // unless the extension in question is a component extension, in which case | |
| 1465 // we cheat and call it blessed. | |
| 1466 return (extension->is_hosted_app() && | |
| 1467 extension->location() != Manifest::COMPONENT) | |
| 1468 ? Feature::BLESSED_WEB_PAGE_CONTEXT | |
| 1469 : Feature::BLESSED_EXTENSION_CONTEXT; | |
| 1470 } | |
| 1471 | |
| 1472 // TODO(kalman): This isUnique() check is wrong, it should be performed as | |
| 1473 // part of IsSandboxedPage(). | |
| 1474 if (!origin.isUnique() && extensions_.ExtensionBindingsAllowed(url)) { | |
| 1475 if (!extension) // TODO(kalman): when does this happen? | |
| 1476 return Feature::UNSPECIFIED_CONTEXT; | |
| 1477 return extension->is_hosted_app() ? Feature::BLESSED_WEB_PAGE_CONTEXT | |
| 1478 : Feature::UNBLESSED_EXTENSION_CONTEXT; | |
| 1479 } | |
| 1480 | |
| 1481 if (!url.is_valid()) | |
| 1482 return Feature::UNSPECIFIED_CONTEXT; | |
| 1483 | |
| 1484 if (url.SchemeIs(content::kChromeUIScheme)) | |
| 1485 return Feature::WEBUI_CONTEXT; | |
| 1486 | |
| 1487 return Feature::WEB_PAGE_CONTEXT; | |
| 1488 } | |
| 1489 | |
| 1490 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( | 1359 v8::Handle<v8::Object> Dispatcher::GetOrCreateObject( |
| 1491 const v8::Handle<v8::Object>& object, | 1360 const v8::Handle<v8::Object>& object, |
| 1492 const std::string& field, | 1361 const std::string& field, |
| 1493 v8::Isolate* isolate) { | 1362 v8::Isolate* isolate) { |
| 1494 v8::Handle<v8::String> key = v8::String::NewFromUtf8(isolate, field.c_str()); | 1363 v8::Handle<v8::String> key = v8::String::NewFromUtf8(isolate, field.c_str()); |
| 1495 // If the object has a callback property, it is assumed it is an unavailable | 1364 // If the object has a callback property, it is assumed it is an unavailable |
| 1496 // API, so it is safe to delete. This is checked before GetOrCreateObject is | 1365 // API, so it is safe to delete. This is checked before GetOrCreateObject is |
| 1497 // called. | 1366 // called. |
| 1498 if (object->HasRealNamedCallbackProperty(key)) { | 1367 if (object->HasRealNamedCallbackProperty(key)) { |
| 1499 object->Delete(key); | 1368 object->Delete(key); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1553 return v8::Handle<v8::Object>(); | 1422 return v8::Handle<v8::Object>(); |
| 1554 | 1423 |
| 1555 if (bind_name) | 1424 if (bind_name) |
| 1556 *bind_name = split.back(); | 1425 *bind_name = split.back(); |
| 1557 | 1426 |
| 1558 return bind_object.IsEmpty() ? AsObjectOrEmpty(GetOrCreateChrome(context)) | 1427 return bind_object.IsEmpty() ? AsObjectOrEmpty(GetOrCreateChrome(context)) |
| 1559 : bind_object; | 1428 : bind_object; |
| 1560 } | 1429 } |
| 1561 | 1430 |
| 1562 } // namespace extensions | 1431 } // namespace extensions |
| OLD | NEW |