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/dispatcher.h" | 5 #include "chrome/renderer/extensions/dispatcher.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/debug/alias.h" | 9 #include "base/debug/alias.h" |
| 10 #include "base/json/json_reader.h" | 10 #include "base/json/json_reader.h" |
| (...skipping 995 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1006 // CSP blocks extension page loading by switching the extension ID to | 1006 // CSP blocks extension page loading by switching the extension ID to |
| 1007 // "invalid". This isn't interesting. | 1007 // "invalid". This isn't interesting. |
| 1008 if (extension_id != "invalid") { | 1008 if (extension_id != "invalid") { |
| 1009 LOG(ERROR) << "Extension \"" << extension_id << "\" not found"; | 1009 LOG(ERROR) << "Extension \"" << extension_id << "\" not found"; |
| 1010 RenderThread::Get()->RecordUserMetrics("ExtensionNotFound_ED"); | 1010 RenderThread::Get()->RecordUserMetrics("ExtensionNotFound_ED"); |
| 1011 } | 1011 } |
| 1012 | 1012 |
| 1013 extension_id = ""; | 1013 extension_id = ""; |
| 1014 } | 1014 } |
| 1015 | 1015 |
| 1016 ExtensionURLInfo url_info(frame->document().securityOrigin(), | 1016 // Frames loaded on a unique security origin are not accessible to extensions. |
| 1017 UserScriptSlave::GetDataSourceURLForFrame(frame)); | 1017 GURL effective_frame_url; |
|
abarth-chromium
2013/07/13 00:25:40
Can you call this effective_document_url? Frames
| |
| 1018 if (!frame->document().securityOrigin().isUnique()) | |
| 1019 effective_frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); | |
|
abarth-chromium
2013/07/13 00:25:40
This crazy code, huh?
| |
| 1018 | 1020 |
| 1019 Feature::Context context_type = | 1021 Feature::Context context_type = ClassifyJavaScriptContext( |
| 1020 ClassifyJavaScriptContext(extension_id, extension_group, url_info); | 1022 extension_id, extension_group, effective_frame_url); |
| 1021 | 1023 |
| 1022 ChromeV8Context* context = | 1024 ChromeV8Context* context = |
| 1023 new ChromeV8Context(v8_context, frame, extension, context_type); | 1025 new ChromeV8Context(v8_context, frame, extension, context_type); |
| 1024 v8_context_set_.Add(context); | 1026 v8_context_set_.Add(context); |
| 1025 | 1027 |
| 1026 { | 1028 { |
| 1027 scoped_ptr<ModuleSystem> module_system(new ModuleSystem(context, | 1029 scoped_ptr<ModuleSystem> module_system(new ModuleSystem(context, |
| 1028 &source_map_)); | 1030 &source_map_)); |
| 1029 context->set_module_system(module_system.Pass()); | 1031 context->set_module_system(module_system.Pass()); |
| 1030 } | 1032 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1118 | 1120 |
| 1119 VLOG(1) << "Num tracked contexts: " << v8_context_set_.size(); | 1121 VLOG(1) << "Num tracked contexts: " << v8_context_set_.size(); |
| 1120 } | 1122 } |
| 1121 | 1123 |
| 1122 std::string Dispatcher::GetExtensionID(const WebFrame* frame, int world_id) { | 1124 std::string Dispatcher::GetExtensionID(const WebFrame* frame, int world_id) { |
| 1123 if (world_id != 0) { | 1125 if (world_id != 0) { |
| 1124 // Isolated worlds (content script). | 1126 // Isolated worlds (content script). |
| 1125 return user_script_slave_->GetExtensionIdForIsolatedWorld(world_id); | 1127 return user_script_slave_->GetExtensionIdForIsolatedWorld(world_id); |
| 1126 } | 1128 } |
| 1127 | 1129 |
| 1130 if (frame->document().securityOrigin().isUnique()) | |
| 1131 return std::string(); | |
| 1132 | |
| 1128 // Extension pages (chrome-extension:// URLs). | 1133 // Extension pages (chrome-extension:// URLs). |
| 1129 GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); | 1134 GURL frame_url = UserScriptSlave::GetDataSourceURLForFrame(frame); |
| 1130 return extensions_.GetExtensionOrAppIDByURL( | 1135 return extensions_.GetExtensionOrAppIDByURL(frame_url); |
| 1131 ExtensionURLInfo(frame->document().securityOrigin(), frame_url)); | |
| 1132 } | 1136 } |
| 1133 | 1137 |
| 1134 bool Dispatcher::IsWithinPlatformApp(const WebFrame* frame) { | 1138 bool Dispatcher::IsWithinPlatformApp(const WebFrame* frame) { |
| 1135 // We intentionally don't use the origin parameter for ExtensionURLInfo since | 1139 GURL url(UserScriptSlave::GetDataSourceURLForFrame(frame->top())); |
| 1136 // it would be empty (i.e. unique) for sandboxed resources and thus not match. | 1140 const Extension* extension = extensions_.GetExtensionOrAppByURL(url); |
| 1137 ExtensionURLInfo url_info( | |
| 1138 UserScriptSlave::GetDataSourceURLForFrame(frame->top())); | |
| 1139 const Extension* extension = extensions_.GetExtensionOrAppByURL(url_info); | |
| 1140 | 1141 |
| 1141 return extension && extension->is_platform_app(); | 1142 return extension && extension->is_platform_app(); |
| 1142 } | 1143 } |
| 1143 | 1144 |
| 1144 void Dispatcher::WillReleaseScriptContext( | 1145 void Dispatcher::WillReleaseScriptContext( |
| 1145 WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { | 1146 WebFrame* frame, v8::Handle<v8::Context> v8_context, int world_id) { |
| 1146 ChromeV8Context* context = v8_context_set_.GetByV8Context(v8_context); | 1147 ChromeV8Context* context = v8_context_set_.GetByV8Context(v8_context); |
| 1147 if (!context) | 1148 if (!context) |
| 1148 return; | 1149 return; |
| 1149 | 1150 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 RenderThread::Get()->Send(new ExtensionHostMsg_SuspendAck(extension_id)); | 1370 RenderThread::Get()->Send(new ExtensionHostMsg_SuspendAck(extension_id)); |
| 1370 } | 1371 } |
| 1371 | 1372 |
| 1372 void Dispatcher::OnCancelSuspend(const std::string& extension_id) { | 1373 void Dispatcher::OnCancelSuspend(const std::string& extension_id) { |
| 1373 DispatchEvent(extension_id, kOnSuspendCanceledEvent); | 1374 DispatchEvent(extension_id, kOnSuspendCanceledEvent); |
| 1374 } | 1375 } |
| 1375 | 1376 |
| 1376 Feature::Context Dispatcher::ClassifyJavaScriptContext( | 1377 Feature::Context Dispatcher::ClassifyJavaScriptContext( |
| 1377 const std::string& extension_id, | 1378 const std::string& extension_id, |
| 1378 int extension_group, | 1379 int extension_group, |
| 1379 const ExtensionURLInfo& url_info) { | 1380 const GURL& url) { |
| 1380 DCHECK_GE(extension_group, 0); | 1381 DCHECK_GE(extension_group, 0); |
| 1381 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) { | 1382 if (extension_group == EXTENSION_GROUP_CONTENT_SCRIPTS) { |
| 1382 return extensions_.Contains(extension_id) ? | 1383 return extensions_.Contains(extension_id) ? |
| 1383 Feature::CONTENT_SCRIPT_CONTEXT : Feature::UNSPECIFIED_CONTEXT; | 1384 Feature::CONTENT_SCRIPT_CONTEXT : Feature::UNSPECIFIED_CONTEXT; |
| 1384 } | 1385 } |
| 1385 | 1386 |
| 1386 // We have an explicit check for sandboxed pages before checking whether the | 1387 // We have an explicit check for sandboxed pages before checking whether the |
| 1387 // extension is active in this process because: | 1388 // extension is active in this process because: |
| 1388 // 1. Sandboxed pages run in the same process as regular extension pages, so | 1389 // 1. Sandboxed pages run in the same process as regular extension pages, so |
| 1389 // the extension is considered active. | 1390 // the extension is considered active. |
| 1390 // 2. ScriptContext creation (which triggers bindings injection) happens | 1391 // 2. ScriptContext creation (which triggers bindings injection) happens |
| 1391 // before the SecurityContext is updated with the sandbox flags (after | 1392 // before the SecurityContext is updated with the sandbox flags (after |
| 1392 // reading the CSP header), so url_info.url().securityOrigin() is not | 1393 // reading the CSP header), so the caller can't check if the context's |
| 1393 // unique yet. | 1394 // security origin is unique yet. |
| 1394 if (extensions_.IsSandboxedPage(url_info)) | 1395 if (extensions_.IsSandboxedPage(url)) |
| 1395 return Feature::WEB_PAGE_CONTEXT; | 1396 return Feature::WEB_PAGE_CONTEXT; |
| 1396 | 1397 |
| 1397 if (IsExtensionActive(extension_id)) | 1398 if (IsExtensionActive(extension_id)) |
| 1398 return Feature::BLESSED_EXTENSION_CONTEXT; | 1399 return Feature::BLESSED_EXTENSION_CONTEXT; |
| 1399 | 1400 |
| 1400 if (extensions_.ExtensionBindingsAllowed(url_info)) { | 1401 if (extensions_.ExtensionBindingsAllowed(url)) { |
| 1401 return extensions_.Contains(extension_id) ? | 1402 return extensions_.Contains(extension_id) ? |
| 1402 Feature::UNBLESSED_EXTENSION_CONTEXT : Feature::UNSPECIFIED_CONTEXT; | 1403 Feature::UNBLESSED_EXTENSION_CONTEXT : Feature::UNSPECIFIED_CONTEXT; |
| 1403 } | 1404 } |
| 1404 | 1405 |
| 1405 if (url_info.url().is_valid()) | 1406 if (url.is_valid()) |
| 1406 return Feature::WEB_PAGE_CONTEXT; | 1407 return Feature::WEB_PAGE_CONTEXT; |
| 1407 | 1408 |
| 1408 return Feature::UNSPECIFIED_CONTEXT; | 1409 return Feature::UNSPECIFIED_CONTEXT; |
| 1409 } | 1410 } |
| 1410 | 1411 |
| 1411 void Dispatcher::OnExtensionResponse(int request_id, | 1412 void Dispatcher::OnExtensionResponse(int request_id, |
| 1412 bool success, | 1413 bool success, |
| 1413 const base::ListValue& response, | 1414 const base::ListValue& response, |
| 1414 const std::string& error) { | 1415 const std::string& error) { |
| 1415 request_sender_->HandleResponse(request_id, success, response, error); | 1416 request_sender_->HandleResponse(request_id, success, response, error); |
| 1416 } | 1417 } |
| 1417 | 1418 |
| 1418 bool Dispatcher::CheckContextAccessToExtensionAPI( | 1419 bool Dispatcher::CheckContextAccessToExtensionAPI( |
| 1419 const std::string& function_name, ChromeV8Context* context) const { | 1420 const std::string& function_name, ChromeV8Context* context) const { |
| 1420 if (!context) { | 1421 if (!context) { |
| 1421 DLOG(ERROR) << "Not in a v8::Context"; | 1422 DLOG(ERROR) << "Not in a v8::Context"; |
| 1422 return false; | 1423 return false; |
| 1423 } | 1424 } |
| 1424 | 1425 |
| 1425 if (!context->extension()) { | 1426 if (!context->extension()) { |
| 1426 v8::ThrowException( | 1427 v8::ThrowException( |
| 1427 v8::Exception::Error(v8::String::New("Not in an extension."))); | 1428 v8::Exception::Error(v8::String::New("Not in an extension."))); |
| 1428 return false; | 1429 return false; |
| 1429 } | 1430 } |
| 1430 | 1431 |
| 1431 // Theoretically we could end up with bindings being injected into sandboxed | 1432 // Theoretically we could end up with bindings being injected into sandboxed |
| 1432 // frames, for example content scripts. Don't let them execute API functions. | 1433 // frames, for example content scripts. Don't let them execute API functions. |
| 1433 WebKit::WebFrame* frame = context->web_frame(); | 1434 WebKit::WebFrame* frame = context->web_frame(); |
| 1434 ExtensionURLInfo url_info(frame->document().securityOrigin(), | 1435 if (frame->document().securityOrigin().isUnique() || |
| 1435 UserScriptSlave::GetDataSourceURLForFrame(frame)); | 1436 extensions_.IsSandboxedPage( |
| 1436 if (extensions_.IsSandboxedPage(url_info)) { | 1437 UserScriptSlave::GetDataSourceURLForFrame(frame))) { |
| 1437 static const char kMessage[] = | 1438 static const char kMessage[] = |
| 1438 "%s cannot be used within a sandboxed frame."; | 1439 "%s cannot be used within a sandboxed frame."; |
| 1439 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); | 1440 std::string error_msg = base::StringPrintf(kMessage, function_name.c_str()); |
| 1440 v8::ThrowException( | 1441 v8::ThrowException( |
| 1441 v8::Exception::Error(v8::String::New(error_msg.c_str()))); | 1442 v8::Exception::Error(v8::String::New(error_msg.c_str()))); |
| 1442 return false; | 1443 return false; |
| 1443 } | 1444 } |
| 1444 | 1445 |
| 1445 Feature::Availability availability = context->GetAvailability(function_name); | 1446 Feature::Availability availability = context->GetAvailability(function_name); |
| 1446 if (!availability.is_available()) { | 1447 if (!availability.is_available()) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 RenderView* background_view = | 1498 RenderView* background_view = |
| 1498 ExtensionHelper::GetBackgroundPage(extension_id); | 1499 ExtensionHelper::GetBackgroundPage(extension_id); |
| 1499 if (background_view) { | 1500 if (background_view) { |
| 1500 background_view->Send(new ExtensionHostMsg_EventAck( | 1501 background_view->Send(new ExtensionHostMsg_EventAck( |
| 1501 background_view->GetRoutingID())); | 1502 background_view->GetRoutingID())); |
| 1502 } | 1503 } |
| 1503 } | 1504 } |
| 1504 } | 1505 } |
| 1505 | 1506 |
| 1506 } // namespace extensions | 1507 } // namespace extensions |
| OLD | NEW |