summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 17:57:44 +0000
committermpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-03 17:57:44 +0000
commitc2e74fe834afaeed3bf8d21034bb995437518843 (patch)
treec9b3876a00bbbb78984b619246a4069ded4c1664
parent3f7116cf4b4e725cc43c7331fed6cd1a1b03bc96 (diff)
downloadchromium_src-c2e74fe834afaeed3bf8d21034bb995437518843.zip
chromium_src-c2e74fe834afaeed3bf8d21034bb995437518843.tar.gz
chromium_src-c2e74fe834afaeed3bf8d21034bb995437518843.tar.bz2
Revert "Revert "Allow DOMUI pages to call window.open(), giving DOMUI privileges to the new""
Second attempt at r25250. The tests were broken in Release mode due to a race. Should be fixed. BUG=17636 Review URL: http://codereview.chromium.org/172120 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25329 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/dom_ui/dom_ui_factory.cc139
-rw-r--r--chrome/browser/dom_ui/dom_ui_factory.h13
-rw-r--r--chrome/browser/extensions/extension_browsertests_misc.cc74
-rw-r--r--chrome/browser/extensions/extension_dom_ui.cc2
-rw-r--r--chrome/browser/extensions/extension_host.cc2
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc9
-rw-r--r--chrome/browser/renderer_host/render_view_host.h6
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.cc3
-rw-r--r--chrome/browser/tab_contents/render_view_host_delegate_helper.h4
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.cc5
-rw-r--r--chrome/browser/tab_contents/render_view_host_manager.h5
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc25
-rw-r--r--chrome/browser/tab_contents/tab_contents.h9
-rw-r--r--chrome/browser/tab_contents/tab_contents_view.cc7
-rw-r--r--chrome/test/data/extensions/uitest/window_open/manifest.json6
-rw-r--r--chrome/test/data/extensions/uitest/window_open/newtab.html12
-rw-r--r--chrome/test/data/extensions/uitest/window_open/test.html8
17 files changed, 236 insertions, 93 deletions
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc
index f776baa..cdfbd7f 100644
--- a/chrome/browser/dom_ui/dom_ui_factory.cc
+++ b/chrome/browser/dom_ui/dom_ui_factory.cc
@@ -18,102 +18,83 @@
#include "chrome/common/url_constants.h"
#include "googleurl/src/gurl.h"
-// Backend for both querying for and creating new DOMUI objects. If you're just
-// querying whether there's a DOM UI for the given URL, pass NULL for both the
-// web contents and the new_ui. The return value will indiacate whether a DOM UI
-// exists for the given URL.
-//
-// If you want to create a DOM UI, pass non-NULL pointers for both tab_contents
-// and new_ui. The *new_ui pointer will be filled with the created UI if it
-// succeeds (indicated by a return value of true). The caller owns the *new_ui
-// pointer.
-static bool CreateDOMUI(const GURL& url, TabContents* tab_contents,
- DOMUI** new_ui) {
+const DOMUITypeID DOMUIFactory::kNoDOMUI = NULL;
+
+// A function for creating a new DOMUI. The caller owns the return value, which
+// may be NULL (for example, if the URL refers to an non-existent extension).
+typedef DOMUI* (*DOMUIFactoryFunction)(TabContents* tab_contents,
+ const GURL& url);
+
+// Template for defining DOMUIFactoryFunction.
+template<class T>
+DOMUI* NewDOMUI(TabContents* contents, const GURL& url) {
+ return new T(contents);
+}
+
+// Special case for extensions.
+template<>
+DOMUI* NewDOMUI<ExtensionDOMUI>(TabContents* contents, const GURL& url) {
+ // Don't use a DOMUI for non-existent extensions.
+ ExtensionsService* service = contents->profile()->GetExtensionsService();
+ bool valid_extension = (service && service->GetExtensionById(url.host()));
+ if (valid_extension)
+ return new ExtensionDOMUI(contents);
+ return NULL;
+}
+
+// Returns a function that can be used to create the right type of DOMUI for a
+// tab, based on its URL. Returns NULL if the URL doesn't have DOMUI associated
+// with it. Even if the factory function is valid, it may yield a NULL DOMUI
+// when invoked for a particular tab - see NewDOMUI<ExtensionDOMUI>.
+static DOMUIFactoryFunction GetDOMUIFactoryFunction(const GURL& url) {
// Currently, any gears: URL means an HTML dialog.
- if (url.SchemeIs(chrome::kGearsScheme)) {
- if (new_ui)
- *new_ui = new HtmlDialogUI(tab_contents);
- return true;
- }
-
- if (url.SchemeIs(chrome::kExtensionScheme)) {
- // We assume we have a valid extension unless we have a TabContents which
- // can prove us wrong. This can can happen if the user types in a URL
- // manually.
- bool valid_extension = true;
- if (tab_contents) {
- // TabContents can be NULL if we're doing a quick UseDOMUIForURL check.
- ExtensionsService* service =
- tab_contents->profile()->GetExtensionsService();
- valid_extension = (service && service->GetExtensionById(url.host()));
- }
- if (valid_extension) {
- if (new_ui)
- *new_ui = new ExtensionDOMUI(tab_contents);
- return true;
- }
- return false;
- }
+ if (url.SchemeIs(chrome::kGearsScheme))
+ return &NewDOMUI<HtmlDialogUI>;
+
+ if (url.SchemeIs(chrome::kExtensionScheme))
+ return &NewDOMUI<ExtensionDOMUI>;
// TODO(mhm) Make sure this ifdef is removed once print is complete.
#if !defined(GOOGLE_CHROME_BUILD)
- if (url.SchemeIs(chrome::kPrintScheme)) {
- if (new_ui)
- *new_ui = new PrintUI(tab_contents);
- return true;
- }
+ if (url.SchemeIs(chrome::kPrintScheme))
+ return &NewDOMUI<PrintUI>;
#endif
// This will get called a lot to check all URLs, so do a quick check of other
// schemes (gears was handled above) to filter out most URLs.
if (!url.SchemeIs(chrome::kChromeInternalScheme) &&
!url.SchemeIs(chrome::kChromeUIScheme))
- return false;
+ return NULL;
- if (url.host() == chrome::kSyncResourcesHost) {
- if (new_ui)
- *new_ui = new HtmlDialogUI(tab_contents);
- return true;
- }
+ if (url.host() == chrome::kSyncResourcesHost)
+ return &NewDOMUI<HtmlDialogUI>;
// Special case the new tab page. In older versions of Chrome, the new tab
// page was hosted at chrome-internal:<blah>. This might be in people's saved
// sessions or bookmarks, so we say any URL with that scheme triggers the new
// tab page.
if (url.host() == chrome::kChromeUINewTabHost ||
- url.SchemeIs(chrome::kChromeInternalScheme)) {
- if (new_ui)
- *new_ui = new NewTabUI(tab_contents);
- return true;
- }
+ url.SchemeIs(chrome::kChromeInternalScheme))
+ return &NewDOMUI<NewTabUI>;
// We must compare hosts only since some of the DOM UIs append extra stuff
// after the host name.
- if (url.host() == chrome::kChromeUIHistoryHost) {
- if (new_ui)
- *new_ui = new HistoryUI(tab_contents);
- return true;
- }
-
- if (url.host() == chrome::kChromeUIDownloadsHost) {
- if (new_ui)
- *new_ui = new DownloadsUI(tab_contents);
- return true;
- }
-
- if (url.host() == chrome::kChromeUIExtensionsHost) {
- if (new_ui)
- *new_ui = new ExtensionsUI(tab_contents);
- return true;
- }
-
- if (url.host() == chrome::kChromeUIDevToolsHost) {
- if (new_ui)
- *new_ui = new DevToolsUI(tab_contents);
- return true;
- }
+ if (url.host() == chrome::kChromeUIHistoryHost)
+ return &NewDOMUI<HistoryUI>;
+ if (url.host() == chrome::kChromeUIDownloadsHost)
+ return &NewDOMUI<DownloadsUI>;
+ if (url.host() == chrome::kChromeUIExtensionsHost)
+ return &NewDOMUI<ExtensionsUI>;
+ if (url.host() == chrome::kChromeUIDevToolsHost)
+ return &NewDOMUI<DevToolsUI>;
+
+ return NULL;
+}
- return false;
+// static
+DOMUITypeID DOMUIFactory::GetDOMUIType(const GURL& url) {
+ DOMUIFactoryFunction function = GetDOMUIFactoryFunction(url);
+ return function ? reinterpret_cast<DOMUITypeID>(function) : kNoDOMUI;
}
// static
@@ -126,16 +107,16 @@ bool DOMUIFactory::HasDOMUIScheme(const GURL& url) {
// static
bool DOMUIFactory::UseDOMUIForURL(const GURL& url) {
- return CreateDOMUI(url, NULL, NULL);
+ return GetDOMUIFactoryFunction(url) != NULL;
}
// static
DOMUI* DOMUIFactory::CreateDOMUIForURL(TabContents* tab_contents,
const GURL& url) {
- DOMUI* dom_ui;
- if (!CreateDOMUI(url, tab_contents, &dom_ui))
+ DOMUIFactoryFunction function = GetDOMUIFactoryFunction(url);
+ if (!function)
return NULL;
- return dom_ui;
+ return (*function)(tab_contents, url);
}
// static
diff --git a/chrome/browser/dom_ui/dom_ui_factory.h b/chrome/browser/dom_ui/dom_ui_factory.h
index e4e36c3..db1500c 100644
--- a/chrome/browser/dom_ui/dom_ui_factory.h
+++ b/chrome/browser/dom_ui/dom_ui_factory.h
@@ -11,8 +11,21 @@ class DOMUI;
class GURL;
class TabContents;
+// An opaque identifier used to identify a DOMUI. This can only be compared to
+// kNoDOMUI or other DOMUI types. See GetDOMUIType.
+typedef void* DOMUITypeID;
+
class DOMUIFactory {
public:
+ // A special DOMUI type that signifies that a given page would not use the
+ // DOM UI system.
+ static const DOMUITypeID kNoDOMUI;
+
+ // Returns a type identifier indicating what DOMUI we would use for the
+ // given URL. This is useful for comparing the potential DOMUIs for two URLs.
+ // Returns kNoDOMUI if the given URL will not use the DOM UI system.
+ static DOMUITypeID GetDOMUIType(const GURL& url);
+
// Returns true if the given URL's scheme would trigger the DOM UI system.
// This is a less precise test than UseDONUIForURL, which tells you whether
// that specific URL matches a known one. This one is faster and can be used
diff --git a/chrome/browser/extensions/extension_browsertests_misc.cc b/chrome/browser/extensions/extension_browsertests_misc.cc
index b2efa99..db4a670 100644
--- a/chrome/browser/extensions/extension_browsertests_misc.cc
+++ b/chrome/browser/extensions/extension_browsertests_misc.cc
@@ -501,3 +501,77 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, UninstallDisabled) {
EXPECT_EQ(0u, service->extensions()->size());
EXPECT_EQ(0u, service->disabled_extensions()->size());
}
+
+// Helper function for common code shared by the 3 WindowOpen tests below.
+static TabContents* WindowOpenHelper(Browser* browser, const GURL& start_url,
+ const std::string& newtab_url) {
+ ui_test_utils::NavigateToURL(browser, start_url);
+
+ bool result = false;
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ browser->GetSelectedTabContents()->render_view_host(), L"",
+ L"window.open('" + UTF8ToWide(newtab_url) + L"');"
+ L"window.domAutomationController.send(true);", &result);
+ EXPECT_TRUE(result);
+
+ // Now the current tab should be the new tab.
+ TabContents* newtab = browser->GetSelectedTabContents();
+ GURL expected_url = start_url.Resolve(newtab_url);
+ if (newtab->GetURL() != expected_url) {
+ ui_test_utils::WaitForNavigation(
+ &browser->GetSelectedTabContents()->controller());
+ }
+ EXPECT_EQ(newtab->GetURL(), expected_url);
+
+ return newtab;
+}
+
+// Tests that an extension page can call window.open to an extension URL and
+// the new window has extension privileges.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenExtension) {
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
+
+ TabContents* newtab = WindowOpenHelper(
+ browser(),
+ GURL("chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.html"),
+ "newtab.html");
+
+ bool result = false;
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ newtab->render_view_host(), L"", L"testExtensionApi()", &result);
+ EXPECT_TRUE(result);
+}
+
+// Tests that if an extension page calls window.open to an invalid extension
+// URL, the browser doesn't crash.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenInvalidExtension) {
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
+
+ WindowOpenHelper(
+ browser(),
+ GURL("chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/test.html"),
+ "chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab/newtab.html");
+
+ // If we got to this point, we didn't crash, so we're good.
+}
+
+// Tests that calling window.open from the newtab page to an extension URL
+// does not give the new window extension privileges - because the opening page
+// does not have extension privileges.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenNoPrivileges) {
+ ASSERT_TRUE(LoadExtension(
+ test_data_dir_.AppendASCII("uitest").AppendASCII("window_open")));
+
+ TabContents* newtab = WindowOpenHelper(
+ browser(),
+ GURL("about:blank"),
+ "chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/newtab.html");
+
+ // Extension API should fail.
+ bool result = false;
+ ui_test_utils::ExecuteJavaScriptAndExtractBool(
+ newtab->render_view_host(), L"", L"testExtensionApi()", &result);
+ EXPECT_FALSE(result);
+}
diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc
index 044a28a..c3741c7 100644
--- a/chrome/browser/extensions/extension_dom_ui.cc
+++ b/chrome/browser/extensions/extension_dom_ui.cc
@@ -40,7 +40,7 @@ void ExtensionDOMUI::ResetExtensionFunctionDispatcher(
// Use the NavigationController to get the URL rather than the TabContents
// since this is the real underlying URL (see HandleChromeURLOverride).
NavigationController& controller = tab_contents()->controller();
- const GURL& url = controller.pending_entry()->url();
+ const GURL& url = controller.GetActiveEntry()->url();
extension_function_dispatcher_.reset(
new ExtensionFunctionDispatcher(render_view_host, this, url));
}
diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc
index 60aa0d3..8690e6a 100644
--- a/chrome/browser/extensions/extension_host.cc
+++ b/chrome/browser/extensions/extension_host.cc
@@ -232,7 +232,7 @@ void ExtensionHost::CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event) {
delegate_view_helper_.CreateNewWindow(
route_id, modal_dialog_event, render_view_host()->process()->profile(),
- site_instance());
+ site_instance(), DOMUIFactory::GetDOMUIType(url_));
}
void ExtensionHost::CreateNewWidget(int route_id, bool activatable) {
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 41cbd00..95a53dd 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1609,7 +1609,9 @@ void RenderViewHost::OnExtensionRequest(const std::string& name,
bool has_callback) {
if (!ChildProcessSecurityPolicy::GetInstance()->
HasExtensionBindings(process()->id())) {
- NOTREACHED() << "Blocked unauthorized use of extension bindings.";
+ // This can happen if someone uses window.open() to open an extension URL
+ // from a non-extension context.
+ BlockExtensionRequest(request_id);
return;
}
@@ -1623,6 +1625,11 @@ void RenderViewHost::SendExtensionResponse(int request_id, bool success,
response, error));
}
+void RenderViewHost::BlockExtensionRequest(int request_id) {
+ SendExtensionResponse(request_id, false, "",
+ "Access to extension API denied.");
+}
+
void RenderViewHost::OnExtensionPostMessage(
int port_id, const std::string& message) {
if (process()->profile()->GetExtensionMessageService()) {
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 6381ef1..0fe33e8 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -418,11 +418,15 @@ class RenderViewHost : public RenderWidgetHost,
// Creates a new RenderWidget with the given route id.
void CreateNewWidget(int route_id, bool activatable);
- // Senf the response to an extension api call.
+ // Send the response to an extension api call.
void SendExtensionResponse(int request_id, bool success,
const std::string& response,
const std::string& error);
+ // Send a response to an extension api call that it was blocked for lack of
+ // permission.
+ void BlockExtensionRequest(int request_id);
+
void SignalModalDialogEvent();
void ResetModalDialogEvent();
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
index 184fc5e..2f0eef8 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.cc
@@ -21,7 +21,7 @@
void RenderViewHostDelegateViewHelper::CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event, Profile* profile,
- SiteInstance* site) {
+ SiteInstance* site, DOMUITypeID domui_type) {
// Create the new web contents. This will automatically create the new
// TabContentsView. In the future, we may want to create the view separately.
TabContents* new_contents =
@@ -29,6 +29,7 @@ void RenderViewHostDelegateViewHelper::CreateNewWindow(int route_id,
site,
route_id,
modal_dialog_event);
+ new_contents->set_opener_dom_ui_type(domui_type);
TabContentsView* new_view = new_contents->view();
// TODO(brettw) it seems bogus that we have to call this function on the
diff --git a/chrome/browser/tab_contents/render_view_host_delegate_helper.h b/chrome/browser/tab_contents/render_view_host_delegate_helper.h
index 4f9e600..215cddcc 100644
--- a/chrome/browser/tab_contents/render_view_host_delegate_helper.h
+++ b/chrome/browser/tab_contents/render_view_host_delegate_helper.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "base/gfx/rect.h"
#include "base/waitable_event.h"
+#include "chrome/browser/dom_ui/dom_ui_factory.h"
#include "webkit/glue/webpreferences.h"
#include "webkit/glue/window_open_disposition.h"
@@ -31,7 +32,8 @@ class RenderViewHostDelegateViewHelper {
virtual void CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event,
- Profile* profile, SiteInstance* site);
+ Profile* profile, SiteInstance* site,
+ DOMUITypeID domui_type);
virtual RenderWidgetHostView* CreateNewWidget(int route_id, bool activatable,
RenderProcessHost* process);
virtual TabContents* GetCreatedWindow(int route_id);
diff --git a/chrome/browser/tab_contents/render_view_host_manager.cc b/chrome/browser/tab_contents/render_view_host_manager.cc
index 101c1f8..6b3866f 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.cc
+++ b/chrome/browser/tab_contents/render_view_host_manager.cc
@@ -187,6 +187,11 @@ void RenderViewHostManager::DidNavigateMainFrame(
}
}
+void RenderViewHostManager::SetDOMUIPostCommit(DOMUI* dom_ui) {
+ DCHECK(!dom_ui_.get());
+ dom_ui_.reset(dom_ui);
+}
+
void RenderViewHostManager::RendererAbortedProvisionalLoad(
RenderViewHost* render_view_host) {
// We used to cancel the pending renderer here for cross-site downloads.
diff --git a/chrome/browser/tab_contents/render_view_host_manager.h b/chrome/browser/tab_contents/render_view_host_manager.h
index 8c8dde2..c562628 100644
--- a/chrome/browser/tab_contents/render_view_host_manager.h
+++ b/chrome/browser/tab_contents/render_view_host_manager.h
@@ -127,6 +127,11 @@ class RenderViewHostManager
// Called when a renderer's main frame navigates.
void DidNavigateMainFrame(RenderViewHost* render_view_host);
+ // Set the DOMUI after committing a page load. This is useful for navigations
+ // initiated from a renderer, where we want to give the new renderer DOMUI
+ // privileges from the originating renderer.
+ void SetDOMUIPostCommit(DOMUI* dom_ui);
+
// Called when a provisional load on the given renderer is aborted.
void RendererAbortedProvisionalLoad(RenderViewHost* render_view_host);
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 00d313a..083296c 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -260,7 +260,8 @@ TabContents::TabContents(Profile* profile,
message_box_active_(CreateEvent(NULL, TRUE, FALSE, NULL)),
#endif
last_javascript_message_dismissal_(),
- suppress_javascript_messages_(false) {
+ suppress_javascript_messages_(false),
+ opener_dom_ui_type_(DOMUIFactory::kNoDOMUI) {
pending_install_.page_id = 0;
pending_install_.callback_functor = NULL;
@@ -1273,6 +1274,21 @@ DOMUI* TabContents::GetDOMUIForCurrentState() {
void TabContents::DidNavigateMainFramePostCommit(
const NavigationController::LoadCommittedDetails& details,
const ViewHostMsg_FrameNavigate_Params& params) {
+ if (opener_dom_ui_type_ != DOMUIFactory::kNoDOMUI) {
+ // If this is a window.open navigation, use the same DOMUI as the renderer
+ // that opened the window, as long as both renderers have the same
+ // privileges.
+ if (opener_dom_ui_type_ == DOMUIFactory::GetDOMUIType(GetURL())) {
+ DOMUI* dom_ui = DOMUIFactory::CreateDOMUIForURL(this, GetURL());
+ // dom_ui might be NULL if the URL refers to a non-existent extension.
+ if (dom_ui) {
+ render_manager_.SetDOMUIPostCommit(dom_ui);
+ dom_ui->RenderViewCreated(render_view_host());
+ }
+ }
+ opener_dom_ui_type_ = DOMUIFactory::kNoDOMUI;
+ }
+
if (details.is_user_initiated_main_frame_load()) {
// Clear the status bubble. This is a workaround for a bug where WebKit
// doesn't let us know that the cursor left an element during a
@@ -2113,10 +2129,9 @@ void TabContents::ProcessDOMUIMessage(const std::string& message,
int request_id,
bool has_callback) {
if (!render_manager_.dom_ui()) {
- // We shouldn't get a DOM UI message when we haven't enabled the DOM UI.
- // Because the renderer might be owned and sending random messages, we need
- // to ignore these inproper ones.
- NOTREACHED();
+ // This can happen if someone uses window.open() to open an extension URL
+ // from a non-extension context.
+ render_view_host()->BlockExtensionRequest(request_id);
return;
}
render_manager_.dom_ui()->ProcessDOMUIMessage(message, content, request_id,
diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h
index 2935273..51b8954 100644
--- a/chrome/browser/tab_contents/tab_contents.h
+++ b/chrome/browser/tab_contents/tab_contents.h
@@ -18,6 +18,7 @@
#include "base/scoped_ptr.h"
#include "chrome/browser/autocomplete/autocomplete_edit.h"
#include "chrome/browser/cancelable_request.h"
+#include "chrome/browser/dom_ui/dom_ui_factory.h"
#include "chrome/browser/download/save_package.h"
#include "chrome/browser/fav_icon_helper.h"
#include "chrome/browser/find_notification_details.h"
@@ -590,6 +591,10 @@ class TabContents : public PageNavigator,
return &renderer_preferences_;
}
+ void set_opener_dom_ui_type(DOMUITypeID opener_dom_ui_type) {
+ opener_dom_ui_type_ = opener_dom_ui_type;
+ }
+
private:
friend class NavigationController;
// Used to access the child_windows_ (ConstrainedWindowList) for testing
@@ -1112,6 +1117,10 @@ class TabContents : public PageNavigator,
// Settings that get passed to the renderer process.
RendererPreferences renderer_preferences_;
+ // If this tab was created from a renderer using window.open, this will be
+ // non-NULL and represent the DOMUI of the opening renderer.
+ DOMUITypeID opener_dom_ui_type_;
+
// ---------------------------------------------------------------------------
DISALLOW_COPY_AND_ASSIGN(TabContents);
diff --git a/chrome/browser/tab_contents/tab_contents_view.cc b/chrome/browser/tab_contents/tab_contents_view.cc
index 78d084a..ecdf697 100644
--- a/chrome/browser/tab_contents/tab_contents_view.cc
+++ b/chrome/browser/tab_contents/tab_contents_view.cc
@@ -32,9 +32,10 @@ void TabContentsView::UpdatePreferredWidth(int pref_width) {
void TabContentsView::CreateNewWindow(int route_id,
base::WaitableEvent* modal_dialog_event) {
- delegate_view_helper_.CreateNewWindow(route_id, modal_dialog_event,
- tab_contents_->profile(),
- tab_contents_->GetSiteInstance());
+ delegate_view_helper_.CreateNewWindow(
+ route_id, modal_dialog_event,
+ tab_contents_->profile(), tab_contents_->GetSiteInstance(),
+ DOMUIFactory::GetDOMUIType(tab_contents_->GetURL()));
}
void TabContentsView::CreateNewWidget(int route_id, bool activatable) {
diff --git a/chrome/test/data/extensions/uitest/window_open/manifest.json b/chrome/test/data/extensions/uitest/window_open/manifest.json
new file mode 100644
index 0000000..bcdc692
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/window_open/manifest.json
@@ -0,0 +1,6 @@
+{
+ "version": "1.0.0.0",
+ "name": "window.open test",
+ "description": "An extension for an extension UITest.",
+ "permissions": ["tabs"]
+}
diff --git a/chrome/test/data/extensions/uitest/window_open/newtab.html b/chrome/test/data/extensions/uitest/window_open/newtab.html
new file mode 100644
index 0000000..8fb5b96
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/window_open/newtab.html
@@ -0,0 +1,12 @@
+<script>
+function testExtensionApi() {
+ try {
+ chrome.tabs.getAllInWindow(null, function() {
+ window.domAutomationController.send(
+ !chrome.extension.lastError);
+ });
+ } catch (e) {
+ window.domAutomationController.send(false);
+ }
+}
+</script>
diff --git a/chrome/test/data/extensions/uitest/window_open/test.html b/chrome/test/data/extensions/uitest/window_open/test.html
new file mode 100644
index 0000000..c267f19
--- /dev/null
+++ b/chrome/test/data/extensions/uitest/window_open/test.html
@@ -0,0 +1,8 @@
+HOWDIE!!!
+
+<script>
+function testWindowOpen(url) {
+ window.open(url);
+ window.domAutomationController.send(true);
+}
+</script>