Index: chrome/renderer/extensions/user_script_slave.cc |
diff --git a/chrome/renderer/extensions/user_script_slave.cc b/chrome/renderer/extensions/user_script_slave.cc |
index b8309ac74042484ad7ec7d5694f870a5cc8f8855..e9fa98837c4015bf2105ab248ab683ba289d5773 100644 |
--- a/chrome/renderer/extensions/user_script_slave.cc |
+++ b/chrome/renderer/extensions/user_script_slave.cc |
@@ -17,15 +17,20 @@ |
#include "chrome/common/extensions/extension_set.h" |
#include "chrome/common/url_constants.h" |
#include "chrome/renderer/chrome_render_process_observer.h" |
+#include "chrome/renderer/extensions/extension_dispatcher.h" |
#include "chrome/renderer/extensions/extension_groups.h" |
#include "googleurl/src/gurl.h" |
#include "grit/renderer_resources.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityPolicy.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebVector.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
#include "ui/base/resource/resource_bundle.h" |
using WebKit::WebFrame; |
+using WebKit::WebSecurityOrigin; |
+using WebKit::WebSecurityPolicy; |
using WebKit::WebString; |
using WebKit::WebVector; |
using WebKit::WebView; |
@@ -40,7 +45,6 @@ static const char kUserScriptTail[] = "\n})(window);"; |
static const char kInitExtension[] = |
"if (chrome.initExtension) chrome.initExtension('%s', true, %s);"; |
- |
int UserScriptSlave::GetIsolatedWorldId(const std::string& extension_id) { |
typedef std::map<std::string, int> IsolatedWorldMap; |
@@ -60,6 +64,86 @@ int UserScriptSlave::GetIsolatedWorldId(const std::string& extension_id) { |
return new_id; |
} |
+// Associates the extension's isolated world with the extension's URL as the |
+// origin, and whitelists that origin to have access to 1) the current frame's |
+// origin 2) origins whitelisted in host permission. |
+// Unlike the whitelisting done in the extension process by |
+// ExtensionDispatcher::InitHostPermissions, this is more complex because the |
+// 1) the current frame's origin changes as the page is navigated 2) the set of |
+// extensions may change as they are loaded, unloaded and reloaded. |
+// To solve 1), we keep track of the last origin that we whitelisted for a |
+// frame, and un-whitelist it when getting a new one. To solve 2), we keep track |
+// of what host permission origins we've already whitelisted, and don't |
+// whitelist them again. This means that if an extension is reloaded with fewer |
+// host permissions we will not remove now-obsolete permissions. |
+void UserScriptSlave::InitializeIsolatedWorld( |
Matt Perry
2011/05/27 19:10:54
This seems like a lot of effort to work around def
|
+ WebFrame* frame, |
+ int isolated_world_id, |
+ const Extension* extension) { |
+ frame->setIsolatedWorldSecurityOrigin( |
+ isolated_world_id, |
+ WebSecurityOrigin::create(extension->url())); |
+ |
+ // We always have access to the origin of the frame that we're injecting in. |
+ FrameOriginMap::iterator iter = frame_origins_.find(frame->identifier()); |
+ if (iter != frame_origins_.end()) { |
+ std::pair<std::string, std::string> frame_origin = iter->second; |
+ WebSecurityPolicy::removeOriginAccessWhitelistEntry( |
+ extension->url(), |
+ WebString::fromUTF8(frame_origin.first), |
+ WebString::fromUTF8(frame_origin.second), |
+ false); // do not match subdomains |
+ } |
+ |
+ GURL frame_url = GURL(frame->url()); |
+ WebSecurityPolicy::addOriginAccessWhitelistEntry( |
+ extension->url(), |
+ WebString::fromUTF8(frame_url.scheme()), |
+ WebString::fromUTF8(frame_url.host()), |
+ false); // do not match subdomains |
+ frame_origins_[frame->identifier()] = |
+ std::pair<std::string, std::string>(frame_url.scheme(), frame_url.host()); |
+ |
+ const URLPatternList& permissions = extension->host_permissions(); |
+ for (size_t i = 0; i < permissions.size(); ++i) { |
+ const URLPattern& permission = permissions[i]; |
+ |
+ bool already_whitelisted = false; |
+ ExtensionOriginMap::iterator iter = |
+ extension_origins_.find(extension->id()); |
+ ExtensionOriginMap::iterator end = |
+ extension_origins_.upper_bound(extension->id()); |
+ for (; iter != end; ++iter) { |
+ if (iter->second.scheme() == permission.scheme() && |
+ iter->second.host() == permission.host() && |
+ iter->second.match_subdomains() == permission.match_subdomains()) { |
+ already_whitelisted = true; |
+ break; |
+ } |
+ } |
+ if (already_whitelisted) continue; |
+ |
+ extension_origins_.insert( |
+ std::pair<std::string, URLPattern>(extension->id(), permission)); |
+ |
+ const char* schemes[] = { |
+ chrome::kHttpScheme, |
+ chrome::kHttpsScheme, |
+ chrome::kFileScheme, |
+ chrome::kChromeUIScheme, |
+ }; |
+ for (size_t j = 0; j < arraysize(schemes); ++j) { |
+ if (permission.MatchesScheme(schemes[j])) { |
+ WebSecurityPolicy::addOriginAccessWhitelistEntry( |
+ extension->url(), |
+ WebString::fromUTF8(schemes[j]), |
+ WebString::fromUTF8(permission.host()), |
+ permission.match_subdomains()); |
+ } |
+ } |
+ } |
+} |
+ |
UserScriptSlave::UserScriptSlave(const ExtensionSet* extensions) |
: shared_memory_(NULL), |
script_deleter_(&scripts_), |
@@ -249,6 +333,7 @@ void UserScriptSlave::InjectScripts(WebFrame* frame, |
if (!script->extension_id().empty()) { |
InsertInitExtensionCode(&sources, script->extension_id()); |
isolated_world_id = GetIsolatedWorldId(script->extension_id()); |
+ InitializeIsolatedWorld(frame, isolated_world_id, extension); |
} |
PerfTimer exec_timer; |