Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/renderer/extensions/extension_dispatcher.h" | 5 #include "chrome/renderer/extensions/extension_dispatcher.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "chrome/common/child_process_logging.h" | 8 #include "chrome/common/child_process_logging.h" |
| 9 #include "chrome/common/chrome_switches.h" | 9 #include "chrome/common/chrome_switches.h" |
| 10 #include "chrome/common/extensions/api/extension_api.h" | |
| 10 #include "chrome/common/extensions/extension.h" | 11 #include "chrome/common/extensions/extension.h" |
| 11 #include "chrome/common/extensions/extension_messages.h" | 12 #include "chrome/common/extensions/extension_messages.h" |
| 12 #include "chrome/common/extensions/extension_permission_set.h" | 13 #include "chrome/common/extensions/extension_permission_set.h" |
| 13 #include "chrome/common/url_constants.h" | 14 #include "chrome/common/url_constants.h" |
| 14 #include "chrome/renderer/chrome_render_process_observer.h" | 15 #include "chrome/renderer/chrome_render_process_observer.h" |
| 15 #include "chrome/renderer/extensions/app_bindings.h" | |
| 16 #include "chrome/renderer/extensions/chrome_v8_context.h" | 16 #include "chrome/renderer/extensions/chrome_v8_context.h" |
| 17 #include "chrome/renderer/extensions/chrome_v8_extension.h" | 17 #include "chrome/renderer/extensions/chrome_v8_extension.h" |
| 18 #include "chrome/renderer/extensions/custom_bindings_util.h" | 18 #include "chrome/renderer/extensions/custom_bindings_util.h" |
| 19 #include "chrome/renderer/extensions/event_bindings.h" | 19 #include "chrome/renderer/extensions/event_bindings.h" |
| 20 #include "chrome/renderer/extensions/extension_groups.h" | 20 #include "chrome/renderer/extensions/extension_groups.h" |
| 21 #include "chrome/renderer/extensions/miscellaneous_bindings.h" | 21 #include "chrome/renderer/extensions/miscellaneous_bindings.h" |
| 22 #include "chrome/renderer/extensions/schema_generated_bindings.h" | 22 #include "chrome/renderer/extensions/schema_generated_bindings.h" |
| 23 #include "chrome/renderer/extensions/user_script_slave.h" | 23 #include "chrome/renderer/extensions/user_script_slave.h" |
| 24 #include "chrome/renderer/extensions/webstore_bindings.h" | 24 #include "chrome/renderer/extensions/webstore_bindings.h" |
| 25 #include "content/public/renderer/render_thread.h" | 25 #include "content/public/renderer/render_thread.h" |
| 26 #include "grit/renderer_resources.h" | 26 #include "grit/renderer_resources.h" |
| 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" | 27 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" |
| 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
| 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h" | 30 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h" |
| 31 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 31 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
| 32 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques t.h" | 32 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques t.h" |
| 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 33 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 34 #include "ui/base/resource/resource_bundle.h" | 34 #include "ui/base/resource/resource_bundle.h" |
| 35 #include "v8/include/v8.h" | 35 #include "v8/include/v8.h" |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 static const int64 kInitialExtensionIdleHandlerDelayMs = 5*1000; | 39 static const int64 kInitialExtensionIdleHandlerDelayMs = 5*1000; |
| 40 static const int64 kMaxExtensionIdleHandlerDelayMs = 5*60*1000; | 40 static const int64 kMaxExtensionIdleHandlerDelayMs = 5*60*1000; |
| 41 | 41 |
| 42 ChromeV8Context::ContextType ExtensionGroupToContextType(int extension_group) { | |
| 43 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) | |
| 44 return ChromeV8Context::CONTENT_SCRIPT; | |
| 45 return ChromeV8Context::OTHER; | |
| 46 } | |
| 47 | |
| 48 } | 42 } |
| 49 | 43 |
| 50 using namespace extensions; | 44 using namespace extensions; |
| 51 | 45 |
| 52 using WebKit::WebDataSource; | 46 using WebKit::WebDataSource; |
| 53 using WebKit::WebDocument; | 47 using WebKit::WebDocument; |
| 54 using WebKit::WebFrame; | 48 using WebKit::WebFrame; |
| 55 using WebKit::WebSecurityPolicy; | 49 using WebKit::WebSecurityPolicy; |
| 56 using WebKit::WebString; | 50 using WebKit::WebString; |
| 57 using WebKit::WebVector; | 51 using WebKit::WebVector; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 | 97 |
| 104 void ExtensionDispatcher::WebKitInitialized() { | 98 void ExtensionDispatcher::WebKitInitialized() { |
| 105 // For extensions, we want to ensure we call the IdleHandler every so often, | 99 // For extensions, we want to ensure we call the IdleHandler every so often, |
| 106 // even if the extension keeps up activity. | 100 // even if the extension keeps up activity. |
| 107 if (is_extension_process_) { | 101 if (is_extension_process_) { |
| 108 forced_idle_timer_.Start(FROM_HERE, | 102 forced_idle_timer_.Start(FROM_HERE, |
| 109 base::TimeDelta::FromMilliseconds(kMaxExtensionIdleHandlerDelayMs), | 103 base::TimeDelta::FromMilliseconds(kMaxExtensionIdleHandlerDelayMs), |
| 110 RenderThread::Get(), &RenderThread::IdleHandler); | 104 RenderThread::Get(), &RenderThread::IdleHandler); |
| 111 } | 105 } |
| 112 | 106 |
| 113 RegisterExtension(new AppBindings(this), false); | 107 // Unrestricted extension-related v8-extensions. |
| 108 RegisterExtension(EventBindings::Get(this), false); | |
| 109 RegisterExtension(SchemaGeneratedBindings::Get(this), false); | |
| 110 RegisterExtension(new ChromeV8Extension( | |
| 111 "extensions/json_schema.js", IDR_JSON_SCHEMA_JS, NULL), false); | |
| 112 // TODO(kalman): move this to the custom_bindings infrastructure. | |
| 114 RegisterExtension(new WebstoreBindings(this), false); | 113 RegisterExtension(new WebstoreBindings(this), false); |
| 115 | 114 |
| 116 // Add v8 extensions related to chrome extensions. | 115 // Permissions-checked extension-related v8-extensions. |
| 117 RegisterExtension(new ChromeV8Extension( | |
| 118 "extensions/json_schema.js", IDR_JSON_SCHEMA_JS, NULL), true); | |
| 119 RegisterExtension(EventBindings::Get(this), true); | |
| 120 RegisterExtension(MiscellaneousBindings::Get(this), true); | 116 RegisterExtension(MiscellaneousBindings::Get(this), true); |
| 121 RegisterExtension(SchemaGeneratedBindings::Get(this), true); | |
| 122 RegisterExtension(new ChromeV8Extension( | 117 RegisterExtension(new ChromeV8Extension( |
| 123 "extensions/apitest.js", IDR_EXTENSION_APITEST_JS, NULL), true); | 118 "extensions/apitest.js", IDR_EXTENSION_APITEST_JS, NULL), true); |
| 124 | 119 |
| 125 std::vector<v8::Extension*> custom_bindings = | 120 std::vector<v8::Extension*> custom_bindings = |
| 126 custom_bindings_util::GetAll(this); | 121 custom_bindings_util::GetAll(this); |
| 127 for (std::vector<v8::Extension*>::iterator it = custom_bindings.begin(); | 122 for (std::vector<v8::Extension*>::iterator it = custom_bindings.begin(); |
| 128 it != custom_bindings.end(); ++it) { | 123 it != custom_bindings.end(); ++it) { |
| 129 RegisterExtension(*it, true); | 124 RegisterExtension(*it, true); |
| 130 } | 125 } |
| 131 | 126 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 304 return true; | 299 return true; |
| 305 | 300 |
| 306 // If we don't know about it, it was added by WebCore, so we should allow it. | 301 // If we don't know about it, it was added by WebCore, so we should allow it. |
| 307 if (!RenderThread::Get()->IsRegisteredExtension(v8_extension_name)) | 302 if (!RenderThread::Get()->IsRegisteredExtension(v8_extension_name)) |
| 308 return true; | 303 return true; |
| 309 | 304 |
| 310 // If the V8 extension is not restricted, allow it to run anywhere. | 305 // If the V8 extension is not restricted, allow it to run anywhere. |
| 311 if (!restricted_v8_extensions_.count(v8_extension_name)) | 306 if (!restricted_v8_extensions_.count(v8_extension_name)) |
| 312 return true; | 307 return true; |
| 313 | 308 |
| 314 // Extension-only bindings should be restricted to content scripts and | |
| 315 // extension-blessed URLs. | |
| 316 ChromeV8Context::ContextType context_type = | 309 ChromeV8Context::ContextType context_type = |
| 317 ExtensionGroupToContextType(extension_group); | 310 GetContextType(extension_group, frame); |
| 318 | 311 |
| 319 if (context_type == ChromeV8Context::CONTENT_SCRIPT || | 312 std::string custom_binding_api_name = |
| 320 extensions_.ExtensionBindingsAllowed(ExtensionURLInfo( | 313 custom_bindings_util::GetAPIName(v8_extension_name); |
| 321 frame->document().securityOrigin(), | 314 if (!custom_binding_api_name.empty()) { |
| 322 UserScriptSlave::GetDataSourceURLForFrame(frame)))) { | 315 // Extension is a custom API binding, so do API-based permissions checking. |
| 323 // If the extension is a custom API binding, only allow if the extension | 316 if (context_type == ChromeV8Context::UNPRIVILEGED) { |
| 324 // has permission to use the API. | 317 GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); |
| 325 std::string custom_binding_api_name = | 318 return ExtensionAPI::GetInstance()->MatchesURL( |
| 326 custom_bindings_util::GetAPIName(v8_extension_name); | 319 custom_binding_api_name, frame_url); |
| 327 if (!custom_binding_api_name.empty()) { | 320 } else { |
| 328 std::string extension_id = GetExtensionID(frame, world_id); | 321 std::string extension_id = GetExtensionID(frame, world_id); |
| 329 const Extension* extension = extensions_.GetByID(extension_id); | 322 const Extension* extension = extensions_.GetByID(extension_id); |
| 330 if (!extension) { | 323 if (!extension) { |
| 331 // This can happen when a resource is blocked due to CSP; a valid | 324 // This can happen when a resource is blocked due to CSP; a valid |
| 332 // chrome-extension:// URL is navigated to, so it passes the initial | 325 // chrome-extension:// URL is navigated to, so it passes the initial |
| 333 // checks, but the URL gets changed to "chrome-extension://invalid" | 326 // checks, but the URL gets changed to "chrome-extension://invalid" |
| 334 // afterwards (see chrome_content_renderer_client.cc). An extension | 327 // afterwards (see chrome_content_renderer_client.cc). An extension |
| 335 // page still gets loaded, just for the extension with ID "invalid", | 328 // page still gets loaded, just for the extension with ID "invalid", |
| 336 // which of course isn't found so GetById extension will be NULL. | 329 // which of course isn't found so GetById extension will be NULL. |
| 337 // | 330 // |
| 338 // Reference: http://crbug.com/111614. | 331 // Reference: http://crbug.com/111614. |
| 339 CHECK_EQ("invalid", extension_id); | 332 CHECK_EQ("invalid", extension_id); |
| 340 return false; | 333 return false; |
| 341 } | 334 } |
| 342 return custom_bindings_util::AllowAPIInjection( | 335 return custom_bindings_util::AllowAPIInjection( |
| 343 custom_binding_api_name, *extension, this); | 336 custom_binding_api_name, *extension, this); |
| 344 } | 337 } |
| 345 | |
| 346 return true; | |
| 347 } | 338 } |
| 348 | 339 |
| 349 return false; | 340 // Extension-only bindings should be restricted to content scripts and |
| 341 // extension-blessed URLs. | |
| 342 return context_type != ChromeV8Context::UNPRIVILEGED; | |
|
koz (OOO until 15th September)
2012/02/27 03:04:11
Invert this conditional and remove this comment?
not at google - send to devlin
2012/02/27 04:44:24
Right. Good point.
| |
| 350 } | 343 } |
| 351 | 344 |
| 352 void ExtensionDispatcher::DidCreateScriptContext( | 345 void ExtensionDispatcher::DidCreateScriptContext( |
| 353 WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { | 346 WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { |
| 354 ChromeV8Context* context = | 347 ChromeV8Context* context = |
| 355 new ChromeV8Context( | 348 new ChromeV8Context( |
| 356 v8_context, | 349 v8_context, |
| 357 frame, | 350 frame, |
| 358 GetExtensionID(frame, world_id), | 351 GetExtensionID(frame, world_id), |
| 359 ExtensionGroupToContextType( | 352 GetContextType(hack_DidCreateScriptContext_extension_group, frame)); |
| 360 hack_DidCreateScriptContext_extension_group)); | |
| 361 v8_context_set_.Add(context); | 353 v8_context_set_.Add(context); |
| 362 | 354 |
| 363 const Extension* extension = extensions_.GetByID(context->extension_id()); | 355 const Extension* extension = extensions_.GetByID(context->extension_id()); |
| 364 int manifest_version = 1; | 356 int manifest_version = 1; |
| 365 if (extension) | 357 if (extension) |
| 366 manifest_version = extension->manifest_version(); | 358 manifest_version = extension->manifest_version(); |
| 367 | 359 |
| 368 context->DispatchOnLoadEvent( | 360 context->DispatchOnLoadEvent( |
| 369 is_extension_process_, | 361 is_extension_process_, |
| 370 ChromeRenderProcessObserver::is_incognito_process(), | 362 ChromeRenderProcessObserver::is_incognito_process(), |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 532 | 524 |
| 533 RenderThread::Get()->RegisterExtension(extension); | 525 RenderThread::Get()->RegisterExtension(extension); |
| 534 } | 526 } |
| 535 | 527 |
| 536 void ExtensionDispatcher::OnUsingWebRequestAPI( | 528 void ExtensionDispatcher::OnUsingWebRequestAPI( |
| 537 bool adblock, bool adblock_plus, bool other) { | 529 bool adblock, bool adblock_plus, bool other) { |
| 538 webrequest_adblock_ = adblock; | 530 webrequest_adblock_ = adblock; |
| 539 webrequest_adblock_plus_ = adblock_plus; | 531 webrequest_adblock_plus_ = adblock_plus; |
| 540 webrequest_other_ = other; | 532 webrequest_other_ = other; |
| 541 } | 533 } |
| 534 | |
| 535 ChromeV8Context::ContextType ExtensionDispatcher::GetContextType( | |
| 536 int extension_group, WebFrame* frame) { | |
| 537 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) | |
| 538 return ChromeV8Context::CONTENT_SCRIPT; | |
| 539 | |
| 540 if (extensions_.ExtensionBindingsAllowed(ExtensionURLInfo( | |
| 541 frame->document().securityOrigin(), | |
| 542 UserScriptSlave::GetDataSourceURLForFrame(frame)))) { | |
| 543 return ChromeV8Context::BLESSED; | |
|
koz (OOO until 15th September)
2012/02/27 03:04:11
Nice.
not at google - send to devlin
2012/02/27 04:44:24
Cheers.
| |
| 544 } | |
| 545 | |
| 546 return ChromeV8Context::UNPRIVILEGED; | |
| 547 } | |
| OLD | NEW |