diff options
-rw-r--r-- | chrome/browser/renderer_host/resource_dispatcher_host.cc | 18 | ||||
-rw-r--r-- | chrome/browser/renderer_host/resource_request_details.h | 10 | ||||
-rw-r--r-- | chrome/browser/ssl/ssl_browser_tests.cc | 130 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_service.cc | 15 | ||||
-rw-r--r-- | chrome/browser/worker_host/worker_service.h | 5 | ||||
-rw-r--r-- | chrome/common/child_process_host.cc | 6 | ||||
-rw-r--r-- | chrome/test/data/ssl/imported.js | 1 | ||||
-rw-r--r-- | chrome/test/data/ssl/page_with_unsafe_worker.html | 26 | ||||
-rw-r--r-- | chrome/test/data/ssl/unsafe_worker.js | 6 |
9 files changed, 172 insertions, 45 deletions
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc index 9e7af2f..3e01326 100644 --- a/chrome/browser/renderer_host/resource_dispatcher_host.cc +++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc @@ -43,6 +43,7 @@ #include "chrome/browser/renderer_host/sync_resource_handler.h" #include "chrome/browser/ssl/ssl_client_auth_handler.h" #include "chrome/browser/ssl/ssl_manager.h" +#include "chrome/browser/worker_host/worker_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" @@ -1487,8 +1488,21 @@ bool ResourceDispatcherHost::RenderViewForRequest(const URLRequest* request, return false; } - *render_process_host_id = info->child_id(); - *render_view_host_id = info->route_id(); + // If the request is from the worker process, find a tab that owns the worker. + if (info->process_type() == ChildProcessInfo::WORKER_PROCESS) { + const WorkerProcessHost::WorkerInstance* worker_instance = + WorkerService::GetInstance()->FindWorkerInstance(info->child_id()); + if (!worker_instance) { + *render_process_host_id = -1; + *render_view_host_id = -1; + return false; + } + *render_process_host_id = worker_instance->renderer_id; + *render_view_host_id = worker_instance->render_view_route_id; + } else { + *render_process_host_id = info->child_id(); + *render_view_host_id = info->route_id(); + } return true; } diff --git a/chrome/browser/renderer_host/resource_request_details.h b/chrome/browser/renderer_host/resource_request_details.h index e7e1c02..bf84964 100644 --- a/chrome/browser/renderer_host/resource_request_details.h +++ b/chrome/browser/renderer_host/resource_request_details.h @@ -14,6 +14,7 @@ #include "chrome/browser/cert_store.h" #include "chrome/browser/renderer_host/resource_dispatcher_host.h" #include "chrome/browser/renderer_host/resource_dispatcher_host_request_info.h" +#include "chrome/browser/worker_host/worker_service.h" #include "googleurl/src/gurl.h" #include "net/url_request/url_request_status.h" @@ -39,7 +40,14 @@ class ResourceRequestDetails { frame_origin_ = info->frame_origin(); main_frame_origin_ = info->main_frame_origin(); filter_policy_ = info->filter_policy(); - origin_child_id_ = info->child_id(); + + // If request is from the worker process on behalf of a renderer, use + // the renderer process id, since it consumes the notification response + // such as ssl state etc. + const WorkerProcessHost::WorkerInstance* worker_instance = + WorkerService::GetInstance()->FindWorkerInstance(info->child_id()); + origin_child_id_ = + worker_instance ? worker_instance->renderer_id : info->child_id(); } virtual ~ResourceRequestDetails() {} diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc index 84b2cdf..ef1711a 100644 --- a/chrome/browser/ssl/ssl_browser_tests.cc +++ b/chrome/browser/ssl/ssl_browser_tests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/time.h" #include "chrome/browser/browser.h" #include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/interstitial_page.h" @@ -69,6 +70,46 @@ class SSLUITest : public InProcessBrowserTest { EXPECT_FALSE(entry->ssl().has_unsafe_content()); } + void CheckWorkerLoadResult(TabContents* tab, bool expectLoaded) { + // Workers are async and we don't have notifications for them passing + // messages since they do it between renderer and worker processes. + // So have a polling loop, check every 200ms, timeout at 30s. + const int timeout_ms = 200; + base::Time timeToQuit = base::Time::Now() + + base::TimeDelta::FromMilliseconds(30000); + + while(base::Time::Now() < timeToQuit) { + bool workerFinished = false; + ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( + tab->render_view_host(), L"", + L"window.domAutomationController.send(IsWorkerFinished());", + &workerFinished)); + + if (workerFinished) + break; + + // Wait a bit. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, new MessageLoop::QuitTask, timeout_ms); + ui_test_utils::RunMessageLoop(); + } + + bool actuallyLoadedContent = false; + ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( + tab->render_view_host(), L"", + L"window.domAutomationController.send(IsContentLoaded());", + &actuallyLoadedContent)); + EXPECT_EQ(expectLoaded, actuallyLoadedContent); + } + + void ProceedThroughInterstitial(TabContents* tab) { + InterstitialPage* interstitial_page = tab->interstitial_page(); + ASSERT_TRUE(interstitial_page); + interstitial_page->Proceed(); + // Wait for the navigation to be done. + ui_test_utils::WaitForNavigation(&(tab->controller())); + } + private: DISALLOW_COPY_AND_ASSIGN(SSLUITest); }; @@ -124,12 +165,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestHTTPSExpiredCertAndProceed) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing - // Proceed through the interstitial. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false); // No interstitial showing @@ -396,12 +432,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestCNInvalidStickiness) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, true); // Interstitial showing. - // We proceed through the interstitial page. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID, false); // No interstitial showing. @@ -443,11 +474,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestRefNavigation) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false); // No interstitial showing. @@ -516,12 +543,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectBadToGoodHTTPS) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing. - // We proceed through the interstitial page. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); // We have been redirected to the good page. CheckAuthenticatedState(tab, false, false); // No mixed/unsafe content. @@ -542,12 +564,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectGoodToBadHTTPS) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing. - // We proceed through the interstitial page. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false); // No interstitial showing. @@ -589,12 +606,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestRedirectHTTPToBadHTTPS) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing. - // Continue on the interstitial. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - // Wait for the navigation to be done. - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false); // No interstitial showing. @@ -725,11 +737,7 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestBadFrameNavigation) { CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, true); // Interstitial showing - // Continue on the interstitial. - InterstitialPage* interstitial_page = tab->interstitial_page(); - ASSERT_TRUE(interstitial_page); - interstitial_page->Proceed(); - ui_test_utils::WaitForNavigation(&(tab->controller())); + ProceedThroughInterstitial(tab); // Navigate to a good frame. bool success = false; @@ -797,6 +805,48 @@ IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnauthenticatedFrameNavigation) { EXPECT_FALSE(is_content_evil); } +IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContentsInWorkerFiltered) { + scoped_refptr<HTTPSTestServer> good_https_server = GoodCertServer(); + ASSERT_TRUE(good_https_server.get() != NULL); + scoped_refptr<HTTPSTestServer> bad_https_server = BadCertServer(); + ASSERT_TRUE(bad_https_server.get() != NULL); + + // This page will spawn a Worker which will try to load content from + // BadCertServer. + ui_test_utils::NavigateToURL(browser(), good_https_server->TestServerPage( + "files/ssl/page_with_unsafe_worker.html")); + TabContents* tab = browser()->GetSelectedTabContents(); + // Expect Worker not to load mixed content. + CheckWorkerLoadResult(tab, false); + // The bad content is filtered, expect the state to be authenticated. + CheckAuthenticatedState(tab, false, false); +} + +IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContentsInWorker) { + scoped_refptr<HTTPSTestServer> good_https_server = GoodCertServer(); + ASSERT_TRUE(good_https_server.get() != NULL); + scoped_refptr<HTTPSTestServer> bad_https_server = BadCertServer(); + ASSERT_TRUE(bad_https_server.get() != NULL); + + // Navigate to an unsafe site. Proceed with interstitial page to indicate + // the user approves the bad certificate. + ui_test_utils::NavigateToURL(browser(), bad_https_server->TestServerPage( + "files/ssl/blank_page.html")); + TabContents* tab = browser()->GetSelectedTabContents(); + CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, + true); // Interstitial showing + ProceedThroughInterstitial(tab); + CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, + false); // No Interstitial + + // Navigate to safe page that has Worker loading unsafe content. + // Expect content to load but 'mixed' indicators show up. + ui_test_utils::NavigateToURL(browser(), good_https_server->TestServerPage( + "files/ssl/page_with_unsafe_worker.html")); + CheckWorkerLoadResult(tab, true); // Worker loads mixed content + CheckAuthenticatedState(tab, true, false); // Mixed content UI shown. +} + // TODO(jcampan): more tests to do below. // Visit a page over https that contains a frame with a redirect. diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc index a8ce3f0..d37314b 100644 --- a/chrome/browser/worker_host/worker_service.cc +++ b/chrome/browser/worker_host/worker_service.cc @@ -265,3 +265,18 @@ void WorkerService::WorkerProcessDestroyed(WorkerProcessHost* process) { } } } + +const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance( + int worker_process_id) { + for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); + !iter.Done(); ++iter) { + if (iter->id() != worker_process_id) + continue; + + WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); + WorkerProcessHost::Instances::const_iterator instance = + worker->instances().begin(); + return instance == worker->instances().end() ? NULL : &*instance; + } + return NULL; +} diff --git a/chrome/browser/worker_host/worker_service.h b/chrome/browser/worker_host/worker_service.h index 0887b32..a3e71031 100644 --- a/chrome/browser/worker_host/worker_service.h +++ b/chrome/browser/worker_host/worker_service.h @@ -46,6 +46,11 @@ class WorkerService : public NotificationObserver { int next_worker_route_id() { return ++next_worker_route_id_; } + // TODO(dimich): This code assumes there is 1 worker per worker process, which + // is how it is today until V8 can run in separate threads. + const WorkerProcessHost::WorkerInstance* FindWorkerInstance( + int worker_process_id); + // Used when multiple workers can run in the same process. static const int kMaxWorkerProcessesWhenSharing; diff --git a/chrome/common/child_process_host.cc b/chrome/common/child_process_host.cc index 1d48350..7327769 100644 --- a/chrome/common/child_process_host.cc +++ b/chrome/common/child_process_host.cc @@ -250,8 +250,10 @@ ChildProcessHost::Iterator::Iterator() ChildProcessHost::Iterator::Iterator(ProcessType type) : all_(false), type_(type) { - DCHECK(MessageLoop::current() == - ChromeThread::GetMessageLoop(ChromeThread::IO)) << + // IO loop can be NULL in unit tests. + DCHECK(!ChromeThread::GetMessageLoop(ChromeThread::IO) || + MessageLoop::current() == + ChromeThread::GetMessageLoop(ChromeThread::IO)) << "ChildProcessInfo::Iterator must be used on the IO thread."; iterator_ = Singleton<ChildProcessList>::get()->begin(); if (!Done() && (*iterator_)->type() != type_) diff --git a/chrome/test/data/ssl/imported.js b/chrome/test/data/ssl/imported.js new file mode 100644 index 0000000..0d712a1 --- /dev/null +++ b/chrome/test/data/ssl/imported.js @@ -0,0 +1 @@ +message = "loaded"; diff --git a/chrome/test/data/ssl/page_with_unsafe_worker.html b/chrome/test/data/ssl/page_with_unsafe_worker.html new file mode 100644 index 0000000..db8dbfb --- /dev/null +++ b/chrome/test/data/ssl/page_with_unsafe_worker.html @@ -0,0 +1,26 @@ +<html> +<script> + +var isWorkerFinished = false; +var isContentLoaded = false; + +function IsWorkerFinished() { + return isWorkerFinished; +} + +function IsContentLoaded() { + return isContentLoaded; +} + +var worker; +function test() { + worker = new Worker("unsafe_worker.js"); + worker.onmessage = function(e) { + isContentLoaded = (e.data == "loaded"); + isWorkerFinished = true; + }; +} + +</script> +<body onload="test()"></body> +</html> diff --git a/chrome/test/data/ssl/unsafe_worker.js b/chrome/test/data/ssl/unsafe_worker.js new file mode 100644 index 0000000..984223d --- /dev/null +++ b/chrome/test/data/ssl/unsafe_worker.js @@ -0,0 +1,6 @@ +var message = "failed"; +try { + importScripts("https://127.0.0.1:9666/files/ssl/imported.js"); +} catch(ex) { +} +postMessage(message); |