diff options
author | jeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-26 00:29:28 +0000 |
---|---|---|
committer | jeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-26 00:29:28 +0000 |
commit | 50b6601e6fbe1862226c072952d52eae1556a6ae (patch) | |
tree | ca498a3a4cf302947283673b3f65d4fa466667ac | |
parent | 5eff57ede25d7fe51c3bb964aaba2745e3fb1896 (diff) | |
download | chromium_src-50b6601e6fbe1862226c072952d52eae1556a6ae.zip chromium_src-50b6601e6fbe1862226c072952d52eae1556a6ae.tar.gz chromium_src-50b6601e6fbe1862226c072952d52eae1556a6ae.tar.bz2 |
Make chrome.appWindow.create() provide access to the child window at a predictable time.
When you first create a window with chrome.appWindow.create(), it won't have
loaded any resources. So, at create time, you are guaranteed that:
child_window.location.href == 'about:blank'
child_window.document.documentElement.outerHTML ==
'<html><head></head><body></body></html>'
This is in line with the behaviour of window.open().
BUG=131735
TEST=browser_tests:PlatformAppBrowserTest.WindowsApi
Review URL: https://chromiumcodereview.appspot.com/10644006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@144072 0039d316-1c4b-4281-b951-d872f2087c98
11 files changed, 79 insertions, 19 deletions
diff --git a/chrome/browser/extensions/platform_app_browsertest.cc b/chrome/browser/extensions/platform_app_browsertest.cc index 11982ae..2343181 100644 --- a/chrome/browser/extensions/platform_app_browsertest.cc +++ b/chrome/browser/extensions/platform_app_browsertest.cc @@ -110,7 +110,7 @@ IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, Restrictions) { ASSERT_TRUE(RunPlatformAppTest("platform_apps/restrictions")) << message_; } -// Tests that platform apps can use the chrome.windows.* API. +// Tests that platform apps can use the chrome.appWindow.* API. IN_PROC_BROWSER_TEST_F(PlatformAppBrowserTest, WindowsApi) { ASSERT_TRUE(RunPlatformAppTest("platform_apps/windows_api")) << message_; } diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc index 722fb1b..ffc0223 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.cc +++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc @@ -35,6 +35,7 @@ #include "chrome/common/url_constants.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" +#include "content/public/browser/resource_dispatcher_host.h" #include "content/public/common/process_type.h" #include "googleurl/src/gurl.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" @@ -101,6 +102,8 @@ bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(ExtensionHostMsg_GenerateUniqueID, OnExtensionGenerateUniqueID) IPC_MESSAGE_HANDLER(ExtensionHostMsg_UnloadAck, OnExtensionUnloadAck) + IPC_MESSAGE_HANDLER(ExtensionHostMsg_ResumeRequests, + OnExtensionResumeRequests); #if defined(USE_TCMALLOC) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_WriteTcmallocHeapProfile_ACK, OnWriteTcmallocHeapProfile) @@ -417,6 +420,11 @@ void ChromeRenderMessageFilter::OnExtensionGenerateUniqueID(int* unique_id) { *unique_id = next_unique_id++; } +void ChromeRenderMessageFilter::OnExtensionResumeRequests(int route_id) { + content::ResourceDispatcherHost::Get()->ResumeBlockedRequestsForRoute( + render_process_id_, route_id); +} + #if defined(USE_TCMALLOC) void ChromeRenderMessageFilter::OnWriteTcmallocHeapProfile( const FilePath::StringType& filepath, diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h index af0b82b..45efb40 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.h +++ b/chrome/browser/renderer_host/chrome_render_message_filter.h @@ -125,6 +125,7 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter { int sequence_id); void OnExtensionUnloadAck(const std::string& extension_id); void OnExtensionGenerateUniqueID(int* unique_id); + void OnExtensionResumeRequests(int route_id); #if defined(USE_TCMALLOC) void OnRendererTcmalloc(const std::string& output); void OnWriteTcmallocHeapProfile(const FilePath::StringType& filename, diff --git a/chrome/browser/ui/extensions/shell_window.cc b/chrome/browser/ui/extensions/shell_window.cc index af6aa86..d447596 100644 --- a/chrome/browser/ui/extensions/shell_window.cc +++ b/chrome/browser/ui/extensions/shell_window.cc @@ -8,8 +8,8 @@ #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/shell_window_registry.h" #include "chrome/browser/file_select_helper.h" -#include "chrome/browser/intents/web_intents_util.h" #include "chrome/browser/infobars/infobar_tab_helper.h" +#include "chrome/browser/intents/web_intents_util.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/session_id.h" @@ -22,25 +22,39 @@ #include "chrome/common/chrome_notification_types.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_messages.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/browser/notification_types.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/resource_dispatcher_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_intents_dispatcher.h" #include "content/public/common/renderer_preferences.h" +using content::BrowserThread; using content::ConsoleMessageLevel; +using content::RenderViewHost; +using content::ResourceDispatcherHost; using content::SiteInstance; using content::WebContents; namespace { -static const int kDefaultWidth = 512; -static const int kDefaultHeight = 384; +const int kDefaultWidth = 512; +const int kDefaultHeight = 384; + +void SuspendRenderViewHost(RenderViewHost* rvh) { + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, + base::Bind(&ResourceDispatcherHost::BlockRequestsForRoute, + base::Unretained(ResourceDispatcherHost::Get()), + rvh->GetProcess()->GetID(), rvh->GetRoutingID())); +} + } // namespace ShellWindow::CreateParams::CreateParams() @@ -82,9 +96,25 @@ ShellWindow::ShellWindow(Profile* profile, browser_handles_all_top_level_requests = true; web_contents_->GetRenderViewHost()->SyncRendererPrefs(); + // Block the created RVH from loading anything until the background page + // has had a chance to do any initialization it wants. + SuspendRenderViewHost(web_contents_->GetRenderViewHost()); + + // TODO(jeremya): there's a bug where navigating a web contents to an + // extension URL causes it to create a new RVH and discard the old (perfectly + // usable) one. To work around this, we watch for a RVH_CHANGED message from + // the web contents (which will be sent during LoadURL) and suspend resource + // requests on the new RVH to ensure that we block the new RVH from loading + // anything. It should be okay to remove the NOTIFICATION_RVH_CHANGED + // registration once http://crbug.com/123007 is fixed. + registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED, + content::Source<content::NavigationController>( + &web_contents_->GetController())); web_contents_->GetController().LoadURL( url, content::Referrer(), content::PAGE_TRANSITION_LINK, std::string()); + registrar_.RemoveAll(); + registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, content::Source<Profile>(profile_)); // Close when the browser is exiting. @@ -284,6 +314,15 @@ void ShellWindow::Observe(int type, const content::NotificationSource& source, const content::NotificationDetails& details) { switch (type) { + case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { + // TODO(jeremya): once http://crbug.com/123007 is fixed, we'll no longer + // need to suspend resource requests here (the call in the constructor + // should be enough). + content::Details<std::pair<RenderViewHost*, RenderViewHost*> > + host_details(details); + SuspendRenderViewHost(host_details->second); + break; + } case chrome::NOTIFICATION_EXTENSION_UNLOADED: { const extensions::Extension* unloaded_extension = content::Details<extensions::UnloadedExtensionInfo>( diff --git a/chrome/common/extensions/extension_messages.h b/chrome/common/extensions/extension_messages.h index dfc8df9..9745bf2 100644 --- a/chrome/common/extensions/extension_messages.h +++ b/chrome/common/extensions/extension_messages.h @@ -479,3 +479,6 @@ IPC_MESSAGE_ROUTED0(ExtensionHostMsg_DecrementLazyKeepaliveCount) // browser process. IPC_SYNC_MESSAGE_CONTROL0_1(ExtensionHostMsg_GenerateUniqueID, int /* unique_id */) + +// Resumes resource requests for a newly created app window. +IPC_MESSAGE_CONTROL1(ExtensionHostMsg_ResumeRequests, int /* route_id */) diff --git a/chrome/renderer/extensions/app_window_custom_bindings.cc b/chrome/renderer/extensions/app_window_custom_bindings.cc index 48027a1..4a93595 100644 --- a/chrome/renderer/extensions/app_window_custom_bindings.cc +++ b/chrome/renderer/extensions/app_window_custom_bindings.cc @@ -12,15 +12,16 @@ #include "chrome/common/url_constants.h" #include "chrome/renderer/extensions/extension_dispatcher.h" #include "chrome/renderer/extensions/extension_helper.h" +#include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "grit/renderer_resources.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebNavigationPolicy.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebWindowFeatures.h" -#include "third_party/WebKit/Source/WebKit/chromium/public/WebNavigationPolicy.h" -#include "webkit/glue/webkit_glue.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h" #include "v8/include/v8.h" +#include "webkit/glue/webkit_glue.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/render_view_visitor.h" @@ -92,6 +93,8 @@ v8::Handle<v8::Value> AppWindowCustomBindings::GetView( WebKit::WebFrame* opener = render_view->GetWebView()->mainFrame(); WebKit::WebFrame* frame = view->GetWebView()->mainFrame(); frame->setOpener(opener); + content::RenderThread::Get()->Send( + new ExtensionHostMsg_ResumeRequests(view->GetRoutingID())); v8::Local<v8::Value> window = frame->mainWorldScriptContext()->Global(); return window; diff --git a/chrome/renderer/resources/extensions/app_window_custom_bindings.js b/chrome/renderer/resources/extensions/app_window_custom_bindings.js index e3d71c1..23e7073 100644 --- a/chrome/renderer/resources/extensions/app_window_custom_bindings.js +++ b/chrome/renderer/resources/extensions/app_window_custom_bindings.js @@ -11,10 +11,10 @@ var GetView = appWindowNatives.GetView; chromeHidden.registerCustomHook('appWindow', function(bindingsAPI) { var apiFunctions = bindingsAPI.apiFunctions; - apiFunctions.setCustomCallback('create', function(name, request, view_id) { + apiFunctions.setCustomCallback('create', function(name, request, viewId) { var view = null; - if (view_id) - view = GetView(view_id); + if (viewId) + view = GetView(viewId); if (request.callback) { request.callback(view); delete request.callback; diff --git a/chrome/test/data/extensions/platform_apps/windows_api/test.js b/chrome/test/data/extensions/platform_apps/windows_api/test.js index 0c4b51e..9b8163f 100644 --- a/chrome/test/data/extensions/platform_apps/windows_api/test.js +++ b/chrome/test/data/extensions/platform_apps/windows_api/test.js @@ -9,6 +9,9 @@ chrome.experimental.app.onLaunched.addListener(function() { function testCreateWindow() { chrome.appWindow.create('test.html', {}, callbackPass(function (win) { chrome.test.assertTrue(typeof win.window === 'object'); + chrome.test.assertEq('about:blank', win.location.href); + chrome.test.assertEq('<html><head></head><body></body></html>', + win.document.documentElement.outerHTML); })) }, diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.cc b/content/browser/renderer_host/resource_dispatcher_host_impl.cc index 9514845..692f7f3 100644 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.cc +++ b/content/browser/renderer_host/resource_dispatcher_host_impl.cc @@ -1631,6 +1631,7 @@ void ResourceDispatcherHostImpl::UpdateLoadStates() { void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id, int route_id) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); ProcessRouteIDs key(child_id, route_id); DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) << "BlockRequestsForRoute called multiple time for the same RVH"; diff --git a/content/browser/renderer_host/resource_dispatcher_host_impl.h b/content/browser/renderer_host/resource_dispatcher_host_impl.h index d8fece0..4e1b6aa 100644 --- a/content/browser/renderer_host/resource_dispatcher_host_impl.h +++ b/content/browser/renderer_host/resource_dispatcher_host_impl.h @@ -86,6 +86,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl const DownloadSaveInfo& save_info, const DownloadStartedCallback& started_callback) OVERRIDE; virtual void ClearLoginDelegateForRequest(net::URLRequest* request) OVERRIDE; + virtual void BlockRequestsForRoute(int child_id, int route_id) OVERRIDE; + virtual void ResumeBlockedRequestsForRoute( + int child_id, int route_id) OVERRIDE; // Puts the resource dispatcher host in an inactive state (unable to begin // new requests). Cancels all pending requests. @@ -176,15 +179,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl void RemovePendingRequest(int child_id, int request_id); - // Causes all new requests for the route identified by - // |child_id| and |route_id| to be blocked (not being - // started) until ResumeBlockedRequestsForRoute or - // CancelBlockedRequestsForRoute is called. - void BlockRequestsForRoute(int child_id, int route_id); - - // Resumes any blocked request for the specified route id. - void ResumeBlockedRequestsForRoute(int child_id, int route_id); - // Cancels any blocked request for the specified route id. void CancelBlockedRequestsForRoute(int child_id, int route_id); diff --git a/content/public/browser/resource_dispatcher_host.h b/content/public/browser/resource_dispatcher_host.h index d6f813b..d289366 100644 --- a/content/public/browser/resource_dispatcher_host.h +++ b/content/public/browser/resource_dispatcher_host.h @@ -53,6 +53,14 @@ class CONTENT_EXPORT ResourceDispatcherHost { // Clears the ResourceDispatcherHostLoginDelegate associated with the request. virtual void ClearLoginDelegateForRequest(net::URLRequest* request) = 0; + // Causes all new requests for the route identified by |child_id| and + // |route_id| to be blocked (not being started) until + // ResumeBlockedRequestsForRoute is called. + virtual void BlockRequestsForRoute(int child_id, int route_id) = 0; + + // Resumes any blocked request for the specified route id. + virtual void ResumeBlockedRequestsForRoute(int child_id, int route_id) = 0; + protected: virtual ~ResourceDispatcherHost() {} }; |