summaryrefslogtreecommitdiffstats
path: root/chrome/browser/apps/web_view_browsertest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/apps/web_view_browsertest.cc')
-rw-r--r--chrome/browser/apps/web_view_browsertest.cc1474
1 files changed, 1474 insertions, 0 deletions
diff --git a/chrome/browser/apps/web_view_browsertest.cc b/chrome/browser/apps/web_view_browsertest.cc
new file mode 100644
index 0000000..b16d3bd
--- /dev/null
+++ b/chrome/browser/apps/web_view_browsertest.cc
@@ -0,0 +1,1474 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/apps/app_browsertest_util.h"
+#include "chrome/browser/automation/automation_util.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/prerender/prerender_link_manager.h"
+#include "chrome/browser/prerender/prerender_link_manager_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/fake_speech_recognition_manager.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
+#include "net/test/embedded_test_server/http_response.h"
+#include "ui/gl/gl_switches.h"
+
+// For fine-grained suppression on flaky tests.
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
+using prerender::PrerenderLinkManager;
+using prerender::PrerenderLinkManagerFactory;
+
+namespace {
+ const char kEmptyResponsePath[] = "/close-socket";
+ const char kRedirectResponsePath[] = "/server-redirect";
+ const char kRedirectResponseFullPath[] =
+ "/extensions/platform_apps/web_view/shim/guest_redirect.html";
+
+ class EmptyHttpResponse : public net::test_server::HttpResponse {
+ public:
+ virtual std::string ToResponseString() const OVERRIDE {
+ return std::string();
+ }
+ };
+} // namespace
+
+// This class intercepts media access request from the embedder. The request
+// should be triggered only if the embedder API (from tests) allows the request
+// in Javascript.
+// We do not issue the actual media request; the fact that the request reached
+// embedder's WebContents is good enough for our tests. This is also to make
+// the test run successfully on trybots.
+class MockWebContentsDelegate : public content::WebContentsDelegate {
+ public:
+ MockWebContentsDelegate() : requested_(false) {}
+ virtual ~MockWebContentsDelegate() {}
+
+ virtual void RequestMediaAccessPermission(
+ content::WebContents* web_contents,
+ const content::MediaStreamRequest& request,
+ const content::MediaResponseCallback& callback) OVERRIDE {
+ requested_ = true;
+ if (message_loop_runner_.get())
+ message_loop_runner_->Quit();
+ }
+
+ void WaitForSetMediaPermission() {
+ if (requested_)
+ return;
+ message_loop_runner_ = new content::MessageLoopRunner;
+ message_loop_runner_->Run();
+ }
+
+ private:
+ bool requested_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockWebContentsDelegate);
+};
+
+// This class intercepts download request from the guest.
+class MockDownloadWebContentsDelegate : public content::WebContentsDelegate {
+ public:
+ explicit MockDownloadWebContentsDelegate(
+ content::WebContentsDelegate* orig_delegate)
+ : orig_delegate_(orig_delegate),
+ waiting_for_decision_(false),
+ expect_allow_(false),
+ decision_made_(false),
+ last_download_allowed_(false) {}
+ virtual ~MockDownloadWebContentsDelegate() {}
+
+ virtual void CanDownload(
+ content::RenderViewHost* render_view_host,
+ int request_id,
+ const std::string& request_method,
+ const base::Callback<void(bool)>& callback) OVERRIDE {
+ orig_delegate_->CanDownload(
+ render_view_host, request_id, request_method,
+ base::Bind(&MockDownloadWebContentsDelegate::DownloadDecided,
+ base::Unretained(this)));
+ }
+
+ void WaitForCanDownload(bool expect_allow) {
+ EXPECT_FALSE(waiting_for_decision_);
+ waiting_for_decision_ = true;
+
+ if (decision_made_) {
+ EXPECT_EQ(expect_allow, last_download_allowed_);
+ return;
+ }
+
+ expect_allow_ = expect_allow;
+ message_loop_runner_ = new content::MessageLoopRunner;
+ message_loop_runner_->Run();
+ }
+
+ void DownloadDecided(bool allow) {
+ EXPECT_FALSE(decision_made_);
+ decision_made_ = true;
+
+ if (waiting_for_decision_) {
+ EXPECT_EQ(expect_allow_, allow);
+ if (message_loop_runner_.get())
+ message_loop_runner_->Quit();
+ return;
+ }
+ last_download_allowed_ = allow;
+ }
+
+ void Reset() {
+ waiting_for_decision_ = false;
+ decision_made_ = false;
+ }
+
+ private:
+ content::WebContentsDelegate* orig_delegate_;
+ bool waiting_for_decision_;
+ bool expect_allow_;
+ bool decision_made_;
+ bool last_download_allowed_;
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockDownloadWebContentsDelegate);
+};
+
+class WebViewTest : public extensions::PlatformAppBrowserTest {
+ protected:
+ virtual void SetUp() OVERRIDE {
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+
+ // SpeechRecognition test specific SetUp.
+ if (!strcmp(test_info->name(), "SpeechRecognition")) {
+ fake_speech_recognition_manager_.reset(
+ new content::FakeSpeechRecognitionManager());
+ fake_speech_recognition_manager_->set_should_send_fake_response(true);
+ // Inject the fake manager factory so that the test result is returned to
+ // the web page.
+ content::SpeechRecognitionManager::SetManagerForTests(
+ fake_speech_recognition_manager_.get());
+ }
+
+ extensions::PlatformAppBrowserTest::SetUp();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ // SpeechRecognition test specific TearDown.
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+ if (!strcmp(test_info->name(), "SpeechRecognition"))
+ content::SpeechRecognitionManager::SetManagerForTests(NULL);
+
+ extensions::PlatformAppBrowserTest::TearDown();
+ }
+
+ virtual void SetUpOnMainThread() OVERRIDE {
+ const testing::TestInfo* const test_info =
+ testing::UnitTest::GetInstance()->current_test_info();
+ // Mock out geolocation for geolocation specific tests.
+ if (!strncmp(test_info->name(), "GeolocationAPI",
+ strlen("GeolocationAPI"))) {
+ ui_test_utils::OverrideGeolocation(10, 20);
+ }
+ }
+
+ // This method is responsible for initializing a packaged app, which contains
+ // multiple webview tags. The tags have different partition identifiers and
+ // their WebContent objects are returned as output. The method also verifies
+ // the expected process allocation and storage partition assignment.
+ // The |navigate_to_url| parameter is used to navigate the main browser
+ // window.
+ //
+ // TODO(ajwong): This function is getting to be too large. Either refactor it
+ // so the test can specify a configuration of WebView tags that we will
+ // dynamically inject JS to generate, or move this test wholesale into
+ // something that RunPlatformAppTest() can execute purely in Javascript. This
+ // won't let us do a white-box examination of the StoragePartition equivalence
+ // directly, but we will be able to view the black box effects which is good
+ // enough. http://crbug.com/160361
+ void NavigateAndOpenAppForIsolation(
+ GURL navigate_to_url,
+ content::WebContents** default_tag_contents1,
+ content::WebContents** default_tag_contents2,
+ content::WebContents** named_partition_contents1,
+ content::WebContents** named_partition_contents2,
+ content::WebContents** persistent_partition_contents1,
+ content::WebContents** persistent_partition_contents2,
+ content::WebContents** persistent_partition_contents3) {
+ GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+
+ navigate_to_url = navigate_to_url.ReplaceComponents(replace_host);
+
+ GURL tag_url1 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/cookie.html");
+ tag_url1 = tag_url1.ReplaceComponents(replace_host);
+ GURL tag_url2 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/cookie2.html");
+ tag_url2 = tag_url2.ReplaceComponents(replace_host);
+ GURL tag_url3 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/storage1.html");
+ tag_url3 = tag_url3.ReplaceComponents(replace_host);
+ GURL tag_url4 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/storage2.html");
+ tag_url4 = tag_url4.ReplaceComponents(replace_host);
+ GURL tag_url5 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/storage1.html#p1");
+ tag_url5 = tag_url5.ReplaceComponents(replace_host);
+ GURL tag_url6 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/storage1.html#p2");
+ tag_url6 = tag_url6.ReplaceComponents(replace_host);
+ GURL tag_url7 = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/web_view/isolation/storage1.html#p3");
+ tag_url7 = tag_url7.ReplaceComponents(replace_host);
+
+ ui_test_utils::NavigateToURLWithDisposition(
+ browser(), navigate_to_url, CURRENT_TAB,
+ ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+ ui_test_utils::UrlLoadObserver observer1(
+ tag_url1, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer2(
+ tag_url2, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer3(
+ tag_url3, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer4(
+ tag_url4, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer5(
+ tag_url5, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer6(
+ tag_url6, content::NotificationService::AllSources());
+ ui_test_utils::UrlLoadObserver observer7(
+ tag_url7, content::NotificationService::AllSources());
+ LoadAndLaunchPlatformApp("web_view/isolation");
+ observer1.Wait();
+ observer2.Wait();
+ observer3.Wait();
+ observer4.Wait();
+ observer5.Wait();
+ observer6.Wait();
+ observer7.Wait();
+
+ content::Source<content::NavigationController> source1 = observer1.source();
+ EXPECT_TRUE(source1->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source2 = observer2.source();
+ EXPECT_TRUE(source2->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source3 = observer3.source();
+ EXPECT_TRUE(source3->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source4 = observer4.source();
+ EXPECT_TRUE(source4->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source5 = observer5.source();
+ EXPECT_TRUE(source5->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source6 = observer6.source();
+ EXPECT_TRUE(source6->GetWebContents()->GetRenderProcessHost()->IsGuest());
+ content::Source<content::NavigationController> source7 = observer7.source();
+ EXPECT_TRUE(source7->GetWebContents()->GetRenderProcessHost()->IsGuest());
+
+ // Check that the first two tags use the same process and it is different
+ // than the process used by the other two.
+ EXPECT_EQ(source1->GetWebContents()->GetRenderProcessHost()->GetID(),
+ source2->GetWebContents()->GetRenderProcessHost()->GetID());
+ EXPECT_EQ(source3->GetWebContents()->GetRenderProcessHost()->GetID(),
+ source4->GetWebContents()->GetRenderProcessHost()->GetID());
+ EXPECT_NE(source1->GetWebContents()->GetRenderProcessHost()->GetID(),
+ source3->GetWebContents()->GetRenderProcessHost()->GetID());
+
+ // The two sets of tags should also be isolated from the main browser.
+ EXPECT_NE(source1->GetWebContents()->GetRenderProcessHost()->GetID(),
+ browser()->tab_strip_model()->GetWebContentsAt(0)->
+ GetRenderProcessHost()->GetID());
+ EXPECT_NE(source3->GetWebContents()->GetRenderProcessHost()->GetID(),
+ browser()->tab_strip_model()->GetWebContentsAt(0)->
+ GetRenderProcessHost()->GetID());
+
+ // Check that the storage partitions of the first two tags match and are
+ // different than the other two.
+ EXPECT_EQ(
+ source1->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source2->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+ EXPECT_EQ(
+ source3->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source4->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+ EXPECT_NE(
+ source1->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source3->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+
+ // Ensure the persistent storage partitions are different.
+ EXPECT_EQ(
+ source5->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source6->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+ EXPECT_NE(
+ source5->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source7->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+ EXPECT_NE(
+ source1->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source5->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+ EXPECT_NE(
+ source1->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition(),
+ source7->GetWebContents()->GetRenderProcessHost()->
+ GetStoragePartition());
+
+ *default_tag_contents1 = source1->GetWebContents();
+ *default_tag_contents2 = source2->GetWebContents();
+ *named_partition_contents1 = source3->GetWebContents();
+ *named_partition_contents2 = source4->GetWebContents();
+ if (persistent_partition_contents1) {
+ *persistent_partition_contents1 = source5->GetWebContents();
+ }
+ if (persistent_partition_contents2) {
+ *persistent_partition_contents2 = source6->GetWebContents();
+ }
+ if (persistent_partition_contents3) {
+ *persistent_partition_contents3 = source7->GetWebContents();
+ }
+ }
+
+ void ExecuteScriptWaitForTitle(content::WebContents* web_contents,
+ const char* script,
+ const char* title) {
+ string16 expected_title(ASCIIToUTF16(title));
+ string16 error_title(ASCIIToUTF16("error"));
+
+ content::TitleWatcher title_watcher(web_contents, expected_title);
+ title_watcher.AlsoWaitForTitle(error_title);
+ EXPECT_TRUE(content::ExecuteScript(web_contents, script));
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+ }
+
+ // Handles |request| by serving a redirect response.
+ static scoped_ptr<net::test_server::HttpResponse> RedirectResponseHandler(
+ const std::string& path,
+ const GURL& redirect_target,
+ const net::test_server::HttpRequest& request) {
+ if (!StartsWithASCII(path, request.relative_url, true))
+ return scoped_ptr<net::test_server::HttpResponse>();
+
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse);
+ http_response->set_code(net::HTTP_MOVED_PERMANENTLY);
+ http_response->AddCustomHeader("Location", redirect_target.spec());
+ return http_response.PassAs<net::test_server::HttpResponse>();
+ }
+
+ // Handles |request| by serving an empty response.
+ static scoped_ptr<net::test_server::HttpResponse> EmptyResponseHandler(
+ const std::string& path,
+ const net::test_server::HttpRequest& request) {
+ if (StartsWithASCII(path, request.relative_url, true)) {
+ return scoped_ptr<net::test_server::HttpResponse>(
+ new EmptyHttpResponse);
+ }
+
+ return scoped_ptr<net::test_server::HttpResponse>();
+ }
+
+ void TestHelper(const std::string& test_name,
+ const std::string& test_passed_msg,
+ const std::string& test_failed_msg,
+ const std::string& app_location) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ LoadAndLaunchPlatformApp(app_location.c_str());
+ ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
+
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&WebViewTest::RedirectResponseHandler,
+ kRedirectResponsePath,
+ embedded_test_server()->GetURL(kRedirectResponseFullPath)));
+
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&WebViewTest::EmptyResponseHandler, kEmptyResponsePath));
+
+ content::WebContents* embedder_web_contents =
+ GetFirstShellWindowWebContents();
+ ASSERT_TRUE(embedder_web_contents);
+
+ ExtensionTestMessageListener done_listener(test_passed_msg, false);
+ done_listener.AlsoListenForFailureMessage(test_failed_msg);
+ EXPECT_TRUE(content::ExecuteScript(
+ embedder_web_contents,
+ base::StringPrintf("runTest('%s')", test_name.c_str())));
+ ASSERT_TRUE(done_listener.WaitUntilSatisfied());
+ }
+
+ content::WebContents* LoadGuest(const std::string& guest_path,
+ const std::string& app_path) {
+ GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+
+ GURL guest_url = embedded_test_server()->GetURL(guest_path);
+ guest_url = guest_url.ReplaceComponents(replace_host);
+
+ ui_test_utils::UrlLoadObserver guest_observer(
+ guest_url, content::NotificationService::AllSources());
+
+ ExtensionTestMessageListener guest_loaded_listener("guest-loaded", false);
+ LoadAndLaunchPlatformApp(app_path.c_str());
+ guest_observer.Wait();
+
+ content::Source<content::NavigationController> source =
+ guest_observer.source();
+ EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->IsGuest());
+
+ bool satisfied = guest_loaded_listener.WaitUntilSatisfied();
+ if (!satisfied)
+ return NULL;
+
+ content::WebContents* guest_web_contents = source->GetWebContents();
+ return guest_web_contents;
+ }
+
+ // Runs media_access/allow tests.
+ void MediaAccessAPIAllowTestHelper(const std::string& test_name);
+
+ // Runs media_access/deny tests, each of them are run separately otherwise
+ // they timeout (mostly on Windows).
+ void MediaAccessAPIDenyTestHelper(const std::string& test_name) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ExtensionTestMessageListener loaded_listener("loaded", false);
+ LoadAndLaunchPlatformApp("web_view/media_access/deny");
+ ASSERT_TRUE(loaded_listener.WaitUntilSatisfied());
+
+ content::WebContents* embedder_web_contents =
+ GetFirstShellWindowWebContents();
+ ASSERT_TRUE(embedder_web_contents);
+
+ ExtensionTestMessageListener test_run_listener("PASSED", false);
+ test_run_listener.AlsoListenForFailureMessage("FAILED");
+ EXPECT_TRUE(
+ content::ExecuteScript(
+ embedder_web_contents,
+ base::StringPrintf("startDenyTest('%s')", test_name.c_str())));
+ ASSERT_TRUE(test_run_listener.WaitUntilSatisfied());
+ }
+
+ private:
+ scoped_ptr<content::FakeSpeechRecognitionManager>
+ fake_speech_recognition_manager_;
+};
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestSize) {
+ TestHelper("testSize",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeAfterNavigation) {
+ TestHelper("testAutosizeAfterNavigation",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeBeforeNavigation) {
+ TestHelper("testAutosizeBeforeNavigation",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeRemoveAttributes) {
+ TestHelper("testAutosizeRemoveAttributes",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAutosizeWithPartialAttributes) {
+ TestHelper("testAutosizeWithPartialAttributes",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAPIMethodExistence) {
+ TestHelper("testAPIMethodExistence",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+// Tests the existence of WebRequest API event objects on the request
+// object, on the webview element, and hanging directly off webview.
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestWebRequestAPIExistence) {
+ TestHelper("testWebRequestAPIExistence",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestEventName) {
+ TestHelper("testEventName",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+// WebViewTest.Shim_TestDestroyOnEventListener is flaky, so disable it.
+// http://crbug.com/255106
+IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_Shim_TestDestroyOnEventListener) {
+ TestHelper("testDestroyOnEventListener",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestCannotMutateEventName) {
+ TestHelper("testCannotMutateEventName",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestPartitionRaisesException) {
+#if defined(OS_WIN)
+ // Flaky on XP bot http://crbug.com/267304
+ if (base::win::GetVersion() <= base::win::VERSION_XP)
+ return;
+#endif
+
+ TestHelper("testPartitionRaisesException",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestExecuteScriptFail) {
+#if defined(OS_WIN)
+ // Flaky on XP bot http://crbug.com/266185
+ if (base::win::GetVersion() <= base::win::VERSION_XP)
+ return;
+#endif
+
+ TestHelper("testExecuteScriptFail",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestExecuteScript) {
+ TestHelper("testExecuteScript",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestTerminateAfterExit) {
+ TestHelper("testTerminateAfterExit",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestAssignSrcAfterCrash) {
+ TestHelper("testAssignSrcAfterCrash",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestRemoveSrcAttribute) {
+ TestHelper("testRemoveSrcAttribute",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestBrowserPluginNotAllowed) {
+#if defined(OS_WIN)
+ // Flaky on XP bots. http://crbug.com/267300
+ if (base::win::GetVersion() <= base::win::VERSION_XP)
+ return;
+#endif
+
+ TestHelper("testBrowserPluginNotAllowed",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindow) {
+ TestHelper("testNewWindow",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowTwoListeners) {
+ TestHelper("testNewWindowTwoListeners",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowNoPreventDefault) {
+ TestHelper("testNewWindowNoPreventDefault",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestNewWindowNoReferrerLink) {
+ TestHelper("testNewWindowNoReferrerLink",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestContentLoadEvent) {
+ TestHelper("testContentLoadEvent",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestWebRequestAPI) {
+ TestHelper("testWebRequestAPI",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadStartLoadRedirect) {
+ TestHelper("testLoadStartLoadRedirect",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadAbortEmptyResponse) {
+ TestHelper("testLoadAbortEmptyResponse",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadAbortIllegalChromeURL) {
+ TestHelper("testLoadAbortIllegalChromeURL",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestLoadAbortIllegalFileURL) {
+ TestHelper("testLoadAbortIllegalFileURL",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestReload) {
+ TestHelper("testReload",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestGetProcessId) {
+ TestHelper("testGetProcessId",
+ "DoneShimTest.PASSED",
+ "DoneShimTest.FAILED",
+ "web_view/shim");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestRemoveWebviewOnExit) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+
+ // Launch the app and wait until it's ready to load a test.
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ LoadAndLaunchPlatformApp("web_view/shim");
+ ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
+
+ content::WebContents* embedder_web_contents =
+ GetFirstShellWindowWebContents();
+ ASSERT_TRUE(embedder_web_contents);
+
+ GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+
+ std::string guest_path(
+ "/extensions/platform_apps/web_view/shim/empty_guest.html");
+ GURL guest_url = embedded_test_server()->GetURL(guest_path);
+ guest_url = guest_url.ReplaceComponents(replace_host);
+
+ ui_test_utils::UrlLoadObserver guest_observer(
+ guest_url, content::NotificationService::AllSources());
+
+ // Run the test and wait until the guest WebContents is available and has
+ // finished loading.
+ ExtensionTestMessageListener guest_loaded_listener("guest-loaded", false);
+ EXPECT_TRUE(content::ExecuteScript(
+ embedder_web_contents,
+ "runTest('testRemoveWebviewOnExit')"));
+ guest_observer.Wait();
+
+ content::Source<content::NavigationController> source =
+ guest_observer.source();
+ EXPECT_TRUE(source->GetWebContents()->GetRenderProcessHost()->IsGuest());
+
+ ASSERT_TRUE(guest_loaded_listener.WaitUntilSatisfied());
+
+ content::WindowedNotificationObserver observer(
+ content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
+ content::Source<content::WebContents>(source->GetWebContents()));
+
+ // Tell the embedder to kill the guest.
+ EXPECT_TRUE(content::ExecuteScript(
+ embedder_web_contents,
+ "removeWebviewOnExitDoCrash();"));
+
+ // Wait until the guest WebContents is destroyed.
+ observer.Wait();
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, ShimSrcAttribute) {
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/src_attribute"))
+ << message_;
+}
+
+// This test verifies that prerendering has been disabled inside <webview>.
+// This test is here rather than in PrerenderBrowserTest for testing convenience
+// only. If it breaks then this is a bug in the prerenderer.
+IN_PROC_BROWSER_TEST_F(WebViewTest, NoPrerenderer) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ content::WebContents* guest_web_contents =
+ LoadGuest(
+ "/extensions/platform_apps/web_view/noprerenderer/guest.html",
+ "web_view/noprerenderer");
+ ASSERT_TRUE(guest_web_contents != NULL);
+
+ PrerenderLinkManager* prerender_link_manager =
+ PrerenderLinkManagerFactory::GetForProfile(
+ Profile::FromBrowserContext(guest_web_contents->GetBrowserContext()));
+ ASSERT_TRUE(prerender_link_manager != NULL);
+ EXPECT_TRUE(prerender_link_manager->IsEmpty());
+}
+
+// This tests cookie isolation for packaged apps with webview tags. It navigates
+// the main browser window to a page that sets a cookie and loads an app with
+// multiple webview tags. Each tag sets a cookie and the test checks the proper
+// storage isolation is enforced.
+IN_PROC_BROWSER_TEST_F(WebViewTest, CookieIsolation) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ const std::string kExpire =
+ "var expire = new Date(Date.now() + 24 * 60 * 60 * 1000);";
+ std::string cookie_script1(kExpire);
+ cookie_script1.append(
+ "document.cookie = 'guest1=true; path=/; expires=' + expire + ';';");
+ std::string cookie_script2(kExpire);
+ cookie_script2.append(
+ "document.cookie = 'guest2=true; path=/; expires=' + expire + ';';");
+
+ GURL::Replacements replace_host;
+ std::string host_str("localhost"); // Must stay in scope with replace_host.
+ replace_host.SetHostStr(host_str);
+
+ GURL set_cookie_url = embedded_test_server()->GetURL(
+ "/extensions/platform_apps/isolation/set_cookie.html");
+ set_cookie_url = set_cookie_url.ReplaceComponents(replace_host);
+
+ // The first two partitions will be used to set cookies and ensure they are
+ // shared. The named partition is used to ensure that cookies are isolated
+ // between partitions within the same app.
+ content::WebContents* cookie_contents1;
+ content::WebContents* cookie_contents2;
+ content::WebContents* named_partition_contents1;
+ content::WebContents* named_partition_contents2;
+
+ NavigateAndOpenAppForIsolation(set_cookie_url, &cookie_contents1,
+ &cookie_contents2, &named_partition_contents1,
+ &named_partition_contents2, NULL, NULL, NULL);
+
+ EXPECT_TRUE(content::ExecuteScript(cookie_contents1, cookie_script1));
+ EXPECT_TRUE(content::ExecuteScript(cookie_contents2, cookie_script2));
+
+ int cookie_size;
+ std::string cookie_value;
+
+ // Test the regular browser context to ensure we have only one cookie.
+ automation_util::GetCookies(GURL("http://localhost"),
+ browser()->tab_strip_model()->GetWebContentsAt(0),
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("testCookie=1", cookie_value);
+
+ // The default behavior is to combine webview tags with no explicit partition
+ // declaration into the same in-memory partition. Test the webview tags to
+ // ensure we have properly set the cookies and we have both cookies in both
+ // tags.
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("guest1=true; guest2=true", cookie_value);
+
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("guest1=true; guest2=true", cookie_value);
+
+ // The third tag should not have any cookies as it is in a separate partition.
+ automation_util::GetCookies(GURL("http://localhost"),
+ named_partition_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("", cookie_value);
+}
+
+// This tests that in-memory storage partitions are reset on browser restart,
+// but persistent ones maintain state for cookies and HTML5 storage.
+IN_PROC_BROWSER_TEST_F(WebViewTest, PRE_StoragePersistence) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ const std::string kExpire =
+ "var expire = new Date(Date.now() + 24 * 60 * 60 * 1000);";
+ std::string cookie_script1(kExpire);
+ cookie_script1.append(
+ "document.cookie = 'inmemory=true; path=/; expires=' + expire + ';';");
+ std::string cookie_script2(kExpire);
+ cookie_script2.append(
+ "document.cookie = 'persist1=true; path=/; expires=' + expire + ';';");
+ std::string cookie_script3(kExpire);
+ cookie_script3.append(
+ "document.cookie = 'persist2=true; path=/; expires=' + expire + ';';");
+
+ // We don't care where the main browser is on this test.
+ GURL blank_url("about:blank");
+
+ // The first two partitions will be used to set cookies and ensure they are
+ // shared. The named partition is used to ensure that cookies are isolated
+ // between partitions within the same app.
+ content::WebContents* cookie_contents1;
+ content::WebContents* cookie_contents2;
+ content::WebContents* named_partition_contents1;
+ content::WebContents* named_partition_contents2;
+ content::WebContents* persistent_partition_contents1;
+ content::WebContents* persistent_partition_contents2;
+ content::WebContents* persistent_partition_contents3;
+ NavigateAndOpenAppForIsolation(blank_url, &cookie_contents1,
+ &cookie_contents2, &named_partition_contents1,
+ &named_partition_contents2,
+ &persistent_partition_contents1,
+ &persistent_partition_contents2,
+ &persistent_partition_contents3);
+
+ // Set the inmemory=true cookie for tags with inmemory partitions.
+ EXPECT_TRUE(content::ExecuteScript(cookie_contents1, cookie_script1));
+ EXPECT_TRUE(content::ExecuteScript(named_partition_contents1,
+ cookie_script1));
+
+ // For the two different persistent storage partitions, set the
+ // two different cookies so we can check that they aren't comingled below.
+ EXPECT_TRUE(content::ExecuteScript(persistent_partition_contents1,
+ cookie_script2));
+
+ EXPECT_TRUE(content::ExecuteScript(persistent_partition_contents3,
+ cookie_script3));
+
+ int cookie_size;
+ std::string cookie_value;
+
+ // Check that all in-memory partitions have a cookie set.
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("inmemory=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("inmemory=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ named_partition_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("inmemory=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ named_partition_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("inmemory=true", cookie_value);
+
+ // Check that all persistent partitions kept their state.
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist1=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist1=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents3,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist2=true", cookie_value);
+}
+
+// This is the post-reset portion of the StoragePersistence test. See
+// PRE_StoragePersistence for main comment.
+IN_PROC_BROWSER_TEST_F(WebViewTest, DISABLED_StoragePersistence) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+
+ // We don't care where the main browser is on this test.
+ GURL blank_url("about:blank");
+
+ // The first two partitions will be used to set cookies and ensure they are
+ // shared. The named partition is used to ensure that cookies are isolated
+ // between partitions within the same app.
+ content::WebContents* cookie_contents1;
+ content::WebContents* cookie_contents2;
+ content::WebContents* named_partition_contents1;
+ content::WebContents* named_partition_contents2;
+ content::WebContents* persistent_partition_contents1;
+ content::WebContents* persistent_partition_contents2;
+ content::WebContents* persistent_partition_contents3;
+ NavigateAndOpenAppForIsolation(blank_url, &cookie_contents1,
+ &cookie_contents2, &named_partition_contents1,
+ &named_partition_contents2,
+ &persistent_partition_contents1,
+ &persistent_partition_contents2,
+ &persistent_partition_contents3);
+
+ int cookie_size;
+ std::string cookie_value;
+
+ // Check that all in-memory partitions lost their state.
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ cookie_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ named_partition_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ named_partition_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("", cookie_value);
+
+ // Check that all persistent partitions kept their state.
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents1,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist1=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents2,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist1=true", cookie_value);
+ automation_util::GetCookies(GURL("http://localhost"),
+ persistent_partition_contents3,
+ &cookie_size, &cookie_value);
+ EXPECT_EQ("persist2=true", cookie_value);
+}
+
+#if defined(OS_WIN)
+// This test is very flaky on Win Aura, Win XP, Win 7. http://crbug.com/248873
+#define MAYBE_DOMStorageIsolation DISABLED_DOMStorageIsolation
+#else
+#define MAYBE_DOMStorageIsolation DOMStorageIsolation
+#endif
+
+// This tests DOM storage isolation for packaged apps with webview tags. It
+// loads an app with multiple webview tags and each tag sets DOM storage
+// entries, which the test checks to ensure proper storage isolation is
+// enforced.
+IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_DOMStorageIsolation) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ GURL regular_url = embedded_test_server()->GetURL("/title1.html");
+
+ std::string output;
+ std::string get_local_storage("window.domAutomationController.send("
+ "window.localStorage.getItem('foo') || 'badval')");
+ std::string get_session_storage("window.domAutomationController.send("
+ "window.sessionStorage.getItem('bar') || 'badval')");
+
+ content::WebContents* default_tag_contents1;
+ content::WebContents* default_tag_contents2;
+ content::WebContents* storage_contents1;
+ content::WebContents* storage_contents2;
+
+ NavigateAndOpenAppForIsolation(regular_url, &default_tag_contents1,
+ &default_tag_contents2, &storage_contents1,
+ &storage_contents2, NULL, NULL, NULL);
+
+ // Initialize the storage for the first of the two tags that share a storage
+ // partition.
+ EXPECT_TRUE(content::ExecuteScript(storage_contents1,
+ "initDomStorage('page1')"));
+
+ // Let's test that the expected values are present in the first tag, as they
+ // will be overwritten once we call the initDomStorage on the second tag.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_local_storage.c_str(),
+ &output));
+ EXPECT_STREQ("local-page1", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_session_storage.c_str(),
+ &output));
+ EXPECT_STREQ("session-page1", output.c_str());
+
+ // Now, init the storage in the second tag in the same storage partition,
+ // which will overwrite the shared localStorage.
+ EXPECT_TRUE(content::ExecuteScript(storage_contents2,
+ "initDomStorage('page2')"));
+
+ // The localStorage value now should reflect the one written through the
+ // second tag.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_local_storage.c_str(),
+ &output));
+ EXPECT_STREQ("local-page2", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents2,
+ get_local_storage.c_str(),
+ &output));
+ EXPECT_STREQ("local-page2", output.c_str());
+
+ // Session storage is not shared though, as each webview tag has separate
+ // instance, even if they are in the same storage partition.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_session_storage.c_str(),
+ &output));
+ EXPECT_STREQ("session-page1", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents2,
+ get_session_storage.c_str(),
+ &output));
+ EXPECT_STREQ("session-page2", output.c_str());
+
+ // Also, let's check that the main browser and another tag that doesn't share
+ // the same partition don't have those values stored.
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ browser()->tab_strip_model()->GetWebContentsAt(0),
+ get_local_storage.c_str(),
+ &output));
+ EXPECT_STREQ("badval", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ browser()->tab_strip_model()->GetWebContentsAt(0),
+ get_session_storage.c_str(),
+ &output));
+ EXPECT_STREQ("badval", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(default_tag_contents1,
+ get_local_storage.c_str(),
+ &output));
+ EXPECT_STREQ("badval", output.c_str());
+ EXPECT_TRUE(ExecuteScriptAndExtractString(default_tag_contents1,
+ get_session_storage.c_str(),
+ &output));
+ EXPECT_STREQ("badval", output.c_str());
+}
+
+// See crbug.com/248500
+#if defined(OS_WIN)
+#define MAYBE_IndexedDBIsolation DISABLED_IndexedDBIsolation
+#else
+#define MAYBE_IndexedDBIsolation IndexedDBIsolation
+#endif
+
+// This tests IndexedDB isolation for packaged apps with webview tags. It loads
+// an app with multiple webview tags and each tag creates an IndexedDB record,
+// which the test checks to ensure proper storage isolation is enforced.
+IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_IndexedDBIsolation) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ GURL regular_url = embedded_test_server()->GetURL("/title1.html");
+
+ content::WebContents* default_tag_contents1;
+ content::WebContents* default_tag_contents2;
+ content::WebContents* storage_contents1;
+ content::WebContents* storage_contents2;
+
+ NavigateAndOpenAppForIsolation(regular_url, &default_tag_contents1,
+ &default_tag_contents2, &storage_contents1,
+ &storage_contents2, NULL, NULL, NULL);
+
+ // Initialize the storage for the first of the two tags that share a storage
+ // partition.
+ ExecuteScriptWaitForTitle(storage_contents1, "initIDB()", "idb created");
+ ExecuteScriptWaitForTitle(storage_contents1, "addItemIDB(7, 'page1')",
+ "addItemIDB complete");
+ ExecuteScriptWaitForTitle(storage_contents1, "readItemIDB(7)",
+ "readItemIDB complete");
+
+ std::string output;
+ std::string get_value(
+ "window.domAutomationController.send(getValueIDB() || 'badval')");
+
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_value.c_str(), &output));
+ EXPECT_STREQ("page1", output.c_str());
+
+ // Initialize the db in the second tag.
+ ExecuteScriptWaitForTitle(storage_contents2, "initIDB()", "idb open");
+
+ // Since we share a partition, reading the value should return the existing
+ // one.
+ ExecuteScriptWaitForTitle(storage_contents2, "readItemIDB(7)",
+ "readItemIDB complete");
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents2,
+ get_value.c_str(), &output));
+ EXPECT_STREQ("page1", output.c_str());
+
+ // Now write through the second tag and read it back.
+ ExecuteScriptWaitForTitle(storage_contents2, "addItemIDB(7, 'page2')",
+ "addItemIDB complete");
+ ExecuteScriptWaitForTitle(storage_contents2, "readItemIDB(7)",
+ "readItemIDB complete");
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents2,
+ get_value.c_str(), &output));
+ EXPECT_STREQ("page2", output.c_str());
+
+ // Reset the document title, otherwise the next call will not see a change and
+ // will hang waiting for it.
+ EXPECT_TRUE(content::ExecuteScript(storage_contents1,
+ "document.title = 'foo'"));
+
+ // Read through the first tag to ensure we have the second value.
+ ExecuteScriptWaitForTitle(storage_contents1, "readItemIDB(7)",
+ "readItemIDB complete");
+ EXPECT_TRUE(ExecuteScriptAndExtractString(storage_contents1,
+ get_value.c_str(), &output));
+ EXPECT_STREQ("page2", output.c_str());
+
+ // Now, let's confirm there is no database in the main browser and another
+ // tag that doesn't share the same partition. Due to the IndexedDB API design,
+ // open will succeed, but the version will be 1, since it creates the database
+ // if it is not found. The two tags use database version 3, so we avoid
+ // ambiguity.
+ const char* script =
+ "indexedDB.open('isolation').onsuccess = function(e) {"
+ " if (e.target.result.version == 1)"
+ " document.title = 'db not found';"
+ " else "
+ " document.title = 'error';"
+ "}";
+ ExecuteScriptWaitForTitle(browser()->tab_strip_model()->GetWebContentsAt(0),
+ script, "db not found");
+ ExecuteScriptWaitForTitle(default_tag_contents1, script, "db not found");
+}
+
+// This test ensures that closing app window on 'loadcommit' does not crash.
+// The test launches an app with guest and closes the window on loadcommit. It
+// then launches the app window again. The process is repeated 3 times.
+IN_PROC_BROWSER_TEST_F(WebViewTest, CloseOnLoadcommit) {
+ ExtensionTestMessageListener done_test_listener(
+ "done-close-on-loadcommit", false);
+ LoadAndLaunchPlatformApp("web_view/close_on_loadcommit");
+ ASSERT_TRUE(done_test_listener.WaitUntilSatisfied());
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, MediaAccessAPIDeny_TestDeny) {
+ MediaAccessAPIDenyTestHelper("testDeny");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest,
+ MediaAccessAPIDeny_TestDenyThenAllowThrows) {
+ MediaAccessAPIDenyTestHelper("testDenyThenAllowThrows");
+
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest,
+ MediaAccessAPIDeny_TestDenyWithPreventDefault) {
+ MediaAccessAPIDenyTestHelper("testDenyWithPreventDefault");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest,
+ MediaAccessAPIDeny_TestNoListenersImplyDeny) {
+ MediaAccessAPIDenyTestHelper("testNoListenersImplyDeny");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest,
+ MediaAccessAPIDeny_TestNoPreventDefaultImpliesDeny) {
+ MediaAccessAPIDenyTestHelper("testNoPreventDefaultImpliesDeny");
+}
+
+void WebViewTest::MediaAccessAPIAllowTestHelper(const std::string& test_name) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ LoadAndLaunchPlatformApp("web_view/media_access/allow");
+ ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
+
+ content::WebContents* embedder_web_contents =
+ GetFirstShellWindowWebContents();
+ ASSERT_TRUE(embedder_web_contents);
+ MockWebContentsDelegate* mock = new MockWebContentsDelegate;
+ embedder_web_contents->SetDelegate(mock);
+
+ ExtensionTestMessageListener done_listener("DoneMediaTest.PASSED", false);
+ done_listener.AlsoListenForFailureMessage("DoneMediaTest.FAILED");
+ EXPECT_TRUE(
+ content::ExecuteScript(
+ embedder_web_contents,
+ base::StringPrintf("startAllowTest('%s')",
+ test_name.c_str())));
+ ASSERT_TRUE(done_listener.WaitUntilSatisfied());
+
+ mock->WaitForSetMediaPermission();
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, MediaAccessAPIAllow_TestAllow) {
+ MediaAccessAPIAllowTestHelper("testAllow");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, MediaAccessAPIAllow_TestAllowAndThenDeny) {
+ MediaAccessAPIAllowTestHelper("testAllowAndThenDeny");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, MediaAccessAPIAllow_TestAllowTwice) {
+ MediaAccessAPIAllowTestHelper("testAllowTwice");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, MediaAccessAPIAllow_TestAllowAsync) {
+ MediaAccessAPIAllowTestHelper("testAllowAsync");
+}
+
+// Checks that window.screenX/screenY/screenLeft/screenTop works correctly for
+// guests.
+IN_PROC_BROWSER_TEST_F(WebViewTest, ScreenCoordinates) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTestWithArg(
+ "platform_apps/web_view/common", "screen_coordinates"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, SpeechRecognition) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ content::WebContents* guest_web_contents = LoadGuest(
+ "/extensions/platform_apps/web_view/speech/guest.html",
+ "web_view/speech");
+ ASSERT_TRUE(guest_web_contents);
+
+ // Click on the guest (center of the WebContents), the guest is rendered in a
+ // way that this will trigger clicking on speech recognition input mic.
+ SimulateMouseClick(guest_web_contents, 0, WebKit::WebMouseEvent::ButtonLeft);
+
+ string16 expected_title(ASCIIToUTF16("PASSED"));
+ string16 error_title(ASCIIToUTF16("FAILED"));
+ content::TitleWatcher title_watcher(guest_web_contents, expected_title);
+ title_watcher.AlsoWaitForTitle(error_title);
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, TearDownTest) {
+ ExtensionTestMessageListener first_loaded_listener("guest-loaded", false);
+ const extensions::Extension* extension =
+ LoadAndLaunchPlatformApp("web_view/teardown");
+ ASSERT_TRUE(first_loaded_listener.WaitUntilSatisfied());
+ apps::ShellWindow* window = NULL;
+ if (!GetShellWindowCount())
+ window = CreateShellWindow(extension);
+ else
+ window = GetFirstShellWindow();
+ CloseShellWindow(window);
+
+ // Load the app again.
+ ExtensionTestMessageListener second_loaded_listener("guest-loaded", false);
+ LoadAndLaunchPlatformApp("web_view/teardown");
+ ASSERT_TRUE(second_loaded_listener.WaitUntilSatisfied());
+}
+
+// In following GeolocationAPIEmbedderHasNoAccess* tests, embedder (i.e. the
+// platform app) does not have geolocation permission for this test.
+// No matter what the API does, geolocation permission would be denied.
+// Note that the test name prefix must be "GeolocationAPI".
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasNoAccessAllow) {
+ TestHelper("testDenyDenies",
+ "DoneGeolocationTest.PASSED",
+ "DoneGeolocationTest.FAILED",
+ "web_view/geolocation/embedder_has_no_permission");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasNoAccessDeny) {
+ TestHelper("testDenyDenies",
+ "DoneGeolocationTest.PASSED",
+ "DoneGeolocationTest.FAILED",
+ "web_view/geolocation/embedder_has_no_permission");
+}
+
+// In following GeolocationAPIEmbedderHasAccess* tests, embedder (i.e. the
+// platform app) has geolocation permission
+//
+// Note that these test names must be "GeolocationAPI" prefixed (b/c we mock out
+// geolocation in this case).
+//
+// Also note that these are run separately because OverrideGeolocation() doesn't
+// mock out geolocation for multiple navigator.geolocation calls properly and
+// the tests become flaky.
+// GeolocationAPI* test 1 of 3.
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasAccessAllow) {
+ TestHelper("testAllow",
+ "DoneGeolocationTest.PASSED",
+ "DoneGeolocationTest.FAILED",
+ "web_view/geolocation/embedder_has_permission");
+}
+
+// GeolocationAPI* test 2 of 3.
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPIEmbedderHasAccessDeny) {
+ TestHelper("testDeny",
+ "DoneGeolocationTest.PASSED",
+ "DoneGeolocationTest.FAILED",
+ "web_view/geolocation/embedder_has_permission");
+}
+
+// GeolocationAPI* test 3 of 3.
+IN_PROC_BROWSER_TEST_F(WebViewTest,
+ GeolocationAPIEmbedderHasAccessMultipleBridgeIdAllow) {
+ TestHelper("testMultipleBridgeIdAllow",
+ "DoneGeolocationTest.PASSED",
+ "DoneGeolocationTest.FAILED",
+ "web_view/geolocation/embedder_has_permission");
+}
+
+// Tests that
+// BrowserPluginGeolocationPermissionContext::CancelGeolocationPermissionRequest
+// is handled correctly (and does not crash).
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationAPICancelGeolocation) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTest(
+ "platform_apps/web_view/geolocation/cancel_request")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, GeolocationRequestGone) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTest(
+ "platform_apps/web_view/geolocation/geolocation_request_gone"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, ConsoleMessage) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ ASSERT_TRUE(RunPlatformAppTestWithArg(
+ "platform_apps/web_view/common", "console_messages"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, DownloadPermission) {
+ ASSERT_TRUE(StartEmbeddedTestServer()); // For serving guest pages.
+ content::WebContents* guest_web_contents =
+ LoadGuest("/extensions/platform_apps/web_view/download/guest.html",
+ "web_view/download");
+ ASSERT_TRUE(guest_web_contents);
+
+ // Replace WebContentsDelegate with mock version so we can intercept download
+ // requests.
+ content::WebContentsDelegate* delegate = guest_web_contents->GetDelegate();
+ MockDownloadWebContentsDelegate* mock_delegate =
+ new MockDownloadWebContentsDelegate(delegate);
+ guest_web_contents->SetDelegate(mock_delegate);
+
+ // Start test.
+ // 1. Guest requests a download that its embedder denies.
+ EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
+ "startDownload('download-link-1')"));
+ mock_delegate->WaitForCanDownload(false); // Expect to not allow.
+ mock_delegate->Reset();
+
+ // 2. Guest requests a download that its embedder allows.
+ EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
+ "startDownload('download-link-2')"));
+ mock_delegate->WaitForCanDownload(true); // Expect to allow.
+ mock_delegate->Reset();
+
+ // 3. Guest requests a download that its embedder ignores, this implies deny.
+ EXPECT_TRUE(content::ExecuteScript(guest_web_contents,
+ "startDownload('download-link-3')"));
+ mock_delegate->WaitForCanDownload(false); // Expect to not allow.
+}
+
+// This test makes sure loading <webview> does not crash when there is an
+// extension which has content script whitelisted/forced.
+IN_PROC_BROWSER_TEST_F(WebViewTest, WhitelistedContentScript) {
+ // Whitelist the extension for running content script we are going to load.
+ extensions::Extension::ScriptingWhitelist whitelist;
+ const std::string extension_id = "imeongpbjoodlnmlakaldhlcmijmhpbb";
+ whitelist.push_back(extension_id);
+ extensions::Extension::SetScriptingWhitelist(whitelist);
+
+ // Load the extension.
+ const extensions::Extension* content_script_whitelisted_extension =
+ LoadExtension(test_data_dir_.AppendASCII(
+ "platform_apps/web_view/legacy/content_script"));
+ ASSERT_TRUE(content_script_whitelisted_extension);
+ ASSERT_EQ(extension_id, content_script_whitelisted_extension->id());
+
+ // Now load an app with <webview>.
+ ExtensionTestMessageListener done_listener("DoneTest", false);
+ LoadAndLaunchPlatformApp("web_view/content_script_whitelisted");
+ ASSERT_TRUE(done_listener.WaitUntilSatisfied());
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, SetPropertyOnDocumentReady) {
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/document_ready"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, SetPropertyOnDocumentInteractive) {
+ ASSERT_TRUE(RunPlatformAppTest("platform_apps/web_view/document_interactive"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestAlertDialog) {
+ TestHelper("testAlertDialog",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialog) {
+ TestHelper("testConfirmDialog",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogCancel) {
+ TestHelper("testConfirmDialogCancel",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogDefaultCancel) {
+ TestHelper("testConfirmDialogDefaultCancel",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestConfirmDialogDefaultGCCancel) {
+ TestHelper("testConfirmDialogDefaultGCCancel",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}
+
+IN_PROC_BROWSER_TEST_F(WebViewTest, Dialog_TestPromptDialog) {
+ TestHelper("testPromptDialog",
+ "DoneDialogTest.PASSED",
+ "DoneDialogTest.FAILED",
+ "web_view/dialog");
+}