Implement app process model isolation.
The process grouping logic is unfortunately duplicated in SiteInstance and
RenderView. URLs that are part of extension X's web extent get converted into
a pseudo URL of the form chrome-extension://X/path. This groups pages from an
extension app and its offline resources into the same process.
The rest is mostly plumbing and passing data around.
BUG=41273
Review URL: http://codereview.chromium.org/1735004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45384 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index 38e068a..b7fb2af 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -474,6 +474,15 @@
ExtensionProcessBindings::SetFunctionNames(names);
}
+void RenderThread::OnExtensionExtentsUpdated(
+ const ViewMsg_ExtensionExtentsUpdated_Params& params) {
+ extension_extents_.resize(params.extension_apps.size());
+ for (size_t i = 0; i < params.extension_apps.size(); ++i) {
+ extension_extents_[i].extension_id = params.extension_apps[i].first;
+ extension_extents_[i].web_extent = params.extension_apps[i].second;
+ }
+}
+
void RenderThread::OnPageActionsUpdated(
const std::string& extension_id,
const std::vector<std::string>& page_actions) {
@@ -548,6 +557,8 @@
OnExtensionMessageInvoke)
IPC_MESSAGE_HANDLER(ViewMsg_Extension_SetFunctionNames,
OnSetExtensionFunctionNames)
+ IPC_MESSAGE_HANDLER(ViewMsg_ExtensionExtentsUpdated,
+ OnExtensionExtentsUpdated)
IPC_MESSAGE_HANDLER(ViewMsg_PurgeMemory, OnPurgeMemory)
IPC_MESSAGE_HANDLER(ViewMsg_PurgePluginListCache,
OnPurgePluginListCache)
@@ -1012,3 +1023,15 @@
gpu_channel_ = NULL;
}
}
+
+std::string RenderThread::GetExtensionIdForURL(const GURL& url) {
+ if (url.SchemeIs(chrome::kExtensionScheme))
+ return url.host();
+
+ for (size_t i = 0; i < extension_extents_.size(); ++i) {
+ if (extension_extents_[i].web_extent.ContainsURL(url))
+ return extension_extents_[i].extension_id;
+ }
+
+ return std::string();
+}
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index e8396dd..ba5c849 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -18,6 +18,8 @@
#include "chrome/common/child_thread.h"
#include "chrome/common/css_colors.h"
#include "chrome/common/dom_storage_common.h"
+#include "chrome/common/extensions/extension_extent.h"
+#include "chrome/common/render_messages.h"
#include "chrome/renderer/gpu_channel_host.h"
#include "chrome/renderer/renderer_histogram_snapshots.h"
#include "chrome/renderer/visitedlink_slave.h"
@@ -185,7 +187,21 @@
// has been lost.
GpuChannelHost* GetGpuChannel();
+ // Returns the extension ID that the given URL is a part of, or empty if
+ // none. This includes web URLs that are part of an extension's web extent.
+ // TODO(mpcomplete): this doesn't feel like it belongs here. Find a better
+ // place.
+ std::string GetExtensionIdForURL(const GURL& url);
+
private:
+ // Contains extension-related data that the renderer needs to know about.
+ // TODO(mpcomplete): this doesn't feel like it belongs here. Find a better
+ // place.
+ struct ExtensionInfo {
+ std::string extension_id;
+ ExtensionExtent web_extent;
+ };
+
virtual void OnControlMessageReceived(const IPC::Message& msg);
void Init();
@@ -198,6 +214,8 @@
const GURL& url, const ContentSettings& content_settings);
void OnUpdateUserScripts(base::SharedMemoryHandle table);
void OnSetExtensionFunctionNames(const std::vector<std::string>& names);
+ void OnExtensionExtentsUpdated(
+ const ViewMsg_ExtensionExtentsUpdated_Params& params);
void OnPageActionsUpdated(const std::string& extension_id,
const std::vector<std::string>& page_actions);
void OnDOMStorageEvent(const ViewMsg_DOMStorageEvent_Params& params);
@@ -314,6 +332,10 @@
// The channel from the renderer process to the GPU process.
scoped_refptr<GpuChannelHost> gpu_channel_;
+ // A list of extension web extents, which tells us which URLs belong to an
+ // installed app.
+ std::vector<ExtensionInfo> extension_extents_;
+
DISALLOW_COPY_AND_ASSIGN(RenderThread);
};
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 1aaf0a4..3364d16 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -320,6 +320,25 @@
return false;
}
+// Returns true if the frame is navigating to an URL either into or out of an
+// extension app's extent.
+static bool CrossesExtensionExtents(WebFrame* frame, const GURL& new_url) {
+ if (!RenderThread::current())
+ return false;
+
+ // If the URL is still empty, this is a window.open navigation. Check the
+ // opener's URL.
+ GURL old_url(frame->url());
+ if (old_url.is_empty() && frame->opener())
+ old_url = frame->opener()->url();
+
+ std::string old_extension =
+ RenderThread::current()->GetExtensionIdForURL(old_url);
+ std::string new_extension =
+ RenderThread::current()->GetExtensionIdForURL(new_url);
+ return (old_extension != new_extension);
+}
+
///////////////////////////////////////////////////////////////////////////////
int32 RenderView::next_page_id_ = 1;
@@ -2210,7 +2229,7 @@
const GURL& url = request.url();
// If the browser is interested, then give it a chance to look at top level
- // navigations
+ // navigations.
if (ShouldRouteNavigationToBrowser(url, frame, type)) {
last_top_level_navigation_page_id_ = page_id_;
GURL referrer(request.httpHeaderField(WebString::fromUTF8("Referer")));
@@ -2233,7 +2252,8 @@
!url.SchemeIs(chrome::kAboutScheme)) {
// When we received such unsolicited navigations, we sometimes want to
// punt them up to the browser to handle.
- if (BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
+ if (CrossesExtensionExtents(frame, url) ||
+ BindingsPolicy::is_dom_ui_enabled(enabled_bindings_) ||
BindingsPolicy::is_extension_enabled(enabled_bindings_) ||
frame->isViewSourceModeEnabled() ||
url.SchemeIs(chrome::kViewSourceScheme) ||