diff options
Diffstat (limited to 'chrome/test/media_router')
-rw-r--r-- | chrome/test/media_router/OWNERS | 1 | ||||
-rw-r--r-- | chrome/test/media_router/e2e_tests.gyp | 25 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_base_browsertest.cc | 128 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_base_browsertest.h | 82 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_e2e_browsertest.cc | 156 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_e2e_browsertest.h | 73 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_integration_browsertest.cc | 97 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_integration_browsertest.h | 40 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_tests.gypi | 32 | ||||
-rw-r--r-- | chrome/test/media_router/media_router_tests.isolate | 46 | ||||
-rw-r--r-- | chrome/test/media_router/resources/basic_test.html | 10 | ||||
-rw-r--r-- | chrome/test/media_router/resources/common.js | 79 | ||||
-rw-r--r-- | chrome/test/media_router/test_media_sinks_observer.cc | 29 | ||||
-rw-r--r-- | chrome/test/media_router/test_media_sinks_observer.h | 34 |
14 files changed, 832 insertions, 0 deletions
diff --git a/chrome/test/media_router/OWNERS b/chrome/test/media_router/OWNERS index a138b5a..f30a0b6 100644 --- a/chrome/test/media_router/OWNERS +++ b/chrome/test/media_router/OWNERS @@ -7,3 +7,4 @@ wez@chromium.org apacible@chromium.org haibinlu@chromium.org imcheng@chromium.org +leilei@chromium.org diff --git a/chrome/test/media_router/e2e_tests.gyp b/chrome/test/media_router/e2e_tests.gyp new file mode 100644 index 0000000..56aad73 --- /dev/null +++ b/chrome/test/media_router/e2e_tests.gyp @@ -0,0 +1,25 @@ +# Copyright (c) 2015 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. + +{ + 'conditions': [ + ['archive_media_router_tests==1', { + 'targets': [ + { + 'target_name': 'media_router_e2e_tests_run', + 'type': 'none', + 'dependencies': [ + '../../chrome.gyp:browser_tests', + ], + 'includes': [ + '../../../build/isolate.gypi', + ], + 'sources': [ + 'media_router_tests.isolate', + ], + }, # target_name: 'media_router_e2e_tests_run' + ], + }], + ], +}
\ No newline at end of file diff --git a/chrome/test/media_router/media_router_base_browsertest.cc b/chrome/test/media_router/media_router_base_browsertest.cc new file mode 100644 index 0000000..a78c5ce --- /dev/null +++ b/chrome/test/media_router/media_router_base_browsertest.cc @@ -0,0 +1,128 @@ +// Copyright 2015 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 "chrome/test/media_router/media_router_base_browsertest.h" + +#include "base/bind.h" +#include "base/command_line.h" +#include "base/path_service.h" +#include "base/timer/elapsed_timer.h" +#include "chrome/browser/extensions/unpacked_installer.h" +#include "chrome/common/chrome_switches.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/common/content_switches.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/process_manager.h" + +namespace { +// Command line argument to specify CRX extension location. +const char kExtensionCrx[] = "extension-crx"; +// Command line argument to specify unpacked extension location. +const char kExtensionUnpacked[] = "extension-unpacked"; +} // namespace + +namespace media_router { + +MediaRouterBaseBrowserTest::MediaRouterBaseBrowserTest() + : extension_load_event_(false, false), extension_host_created_(false) { + base::CommandLine::ForCurrentProcess()->AppendSwitch( + switches::kEnableMediaRouter); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kEnableBlinkFeatures, "Presentation"); +} + +MediaRouterBaseBrowserTest::~MediaRouterBaseBrowserTest() { +} + +void MediaRouterBaseBrowserTest::SetUp() { + ParseCommandLine(); + ExtensionBrowserTest::SetUp(); +} + +void MediaRouterBaseBrowserTest::TearDown() { + ExtensionBrowserTest::TearDown(); +} + +void MediaRouterBaseBrowserTest::SetUpOnMainThread() { + extensions::ProcessManager* process_manager = + extensions::ProcessManager::Get(browser()->profile()); + DCHECK(process_manager); + process_manager->AddObserver(this); + InstallAndEnableMRExtension(); + extension_load_event_.Wait(); +} + +void MediaRouterBaseBrowserTest::TearDownOnMainThread() { + UninstallMRExtension(); + extensions::ProcessManager* process_manager = + extensions::ProcessManager::Get(browser()->profile()); + DCHECK(process_manager); + process_manager->RemoveObserver(this); +} + +void MediaRouterBaseBrowserTest::InstallAndEnableMRExtension() { + if (is_unpacked()) { + const extensions::Extension* extension = LoadExtension(extension_unpacked_); + extension_id_ = extension->id(); + } else { + NOTIMPLEMENTED(); + } +} + +void MediaRouterBaseBrowserTest::UninstallMRExtension() { + if (!extension_id_.empty()) { + UninstallExtension(extension_id_); + } +} + +void MediaRouterBaseBrowserTest::ConditionalWait( + base::TimeDelta timeout, + base::TimeDelta interval, + const base::Callback<bool(void)>& callback) { + base::ElapsedTimer timer; + while (!callback.Run() && timer.Elapsed() < timeout) { + base::RunLoop run_loop; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), interval); + run_loop.Run(); + } +} + +void MediaRouterBaseBrowserTest::Wait(base::TimeDelta timeout) { + base::RunLoop run_loop; + base::MessageLoop::current()->PostDelayedTask( + FROM_HERE, run_loop.QuitClosure(), timeout); + run_loop.Run(); +} + +void MediaRouterBaseBrowserTest::OnBackgroundHostCreated( + extensions::ExtensionHost* host) { + extension_host_created_ = true; + DVLOG(0) << "Host created"; + extension_load_event_.Signal(); +} + +void MediaRouterBaseBrowserTest::ParseCommandLine() { + DVLOG(0) << "ParseCommandLine"; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + extension_crx_ = command_line->GetSwitchValuePath(kExtensionCrx); + extension_unpacked_ = command_line->GetSwitchValuePath(kExtensionUnpacked); + + // Check if there is mr_extension folder under PRODUCT_DIR folder. + if (extension_crx_.empty() && extension_unpacked_.empty()) { + base::FilePath base_dir; + ASSERT_TRUE(PathService::Get(base::DIR_EXE, &base_dir)); + base::FilePath extension_path = + base_dir.Append(FILE_PATH_LITERAL("mr_extension/")); + if (PathExists(extension_path)) { + extension_unpacked_ = extension_path; + } + } + + // Exactly one of these two arguments should be provided. + ASSERT_NE(extension_crx_.empty(), extension_unpacked_.empty()); +} + +} // namespace media_router diff --git a/chrome/test/media_router/media_router_base_browsertest.h b/chrome/test/media_router/media_router_base_browsertest.h new file mode 100644 index 0000000..e1d29c4 --- /dev/null +++ b/chrome/test/media_router/media_router_base_browsertest.h @@ -0,0 +1,82 @@ +// Copyright 2015 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. + +#ifndef CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_BASE_BROWSERTEST_H_ +#define CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_BASE_BROWSERTEST_H_ + +#include <string> + +#include "base/callback.h" +#include "base/synchronization/waitable_event.h" +#include "base/timer/timer.h" +#include "chrome/browser/extensions/extension_apitest.h" +#include "extensions/browser/process_manager_observer.h" + +namespace media_router { + +class MediaRouter; + +/** + * Base class for media router browser test. + * + * It provides the basic functions for integration and e2e browser tests, + * including install unpacked or packed extension at beginning of the test, + * uninstall the extension at the end of the test. + * + * This class accepts two flags to specify the location of MR extension: + * 1. "--extension-crx" flag to specify the packed extension location + * 2. "--extension-unpacked" flag to specify the unpacked extension location + * Only one of them should be passed when run browser tests. + */ +class MediaRouterBaseBrowserTest : public ExtensionBrowserTest, + public extensions::ProcessManagerObserver { + public: + MediaRouterBaseBrowserTest(); + ~MediaRouterBaseBrowserTest() override; + + // InProcessBrowserTest Overrides + void SetUp() override; + void TearDown() override; + + protected: + // InProcessBrowserTest Overrides + void SetUpOnMainThread() override; + void TearDownOnMainThread() override; + + void InstallAndEnableMRExtension(); + void UninstallMRExtension(); + + virtual void ParseCommandLine(); + + // extensions::ProcessManagerObserver Overrides + void OnBackgroundHostCreated(extensions::ExtensionHost* host) override; + + // Wait until get the successful callback or timeout. + // TODO(leilei): Replace this method with WaitableEvent class. + void ConditionalWait(base::TimeDelta timeout, + base::TimeDelta interval, + const base::Callback<bool(void)>& callback); + + // Wait for a specific time. + void Wait(base::TimeDelta timeout); + + bool is_unpacked() const { return !extension_unpacked_.empty(); } + + bool is_extension_host_created() const { return extension_host_created_; } + + // These values are initialized via flags. + base::FilePath extension_crx_; + base::FilePath extension_unpacked_; + + base::WaitableEvent extension_load_event_; + std::string extension_id_; + bool extension_host_created_; + + private: + DISALLOW_COPY_AND_ASSIGN(MediaRouterBaseBrowserTest); +}; + +} // namespace media_router + +#endif // CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_BASE_BROWSERTEST_H_ diff --git a/chrome/test/media_router/media_router_e2e_browsertest.cc b/chrome/test/media_router/media_router_e2e_browsertest.cc new file mode 100644 index 0000000..24f6767 --- /dev/null +++ b/chrome/test/media_router/media_router_e2e_browsertest.cc @@ -0,0 +1,156 @@ +// Copyright 2015 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 "chrome/test/media_router/media_router_e2e_browsertest.h" + +#include "base/command_line.h" +#include "base/stl_util.h" +#include "chrome/browser/media/router/media_router.h" +#include "chrome/browser/media/router/media_router_mojo_impl.h" +#include "chrome/browser/media/router/media_router_mojo_impl_factory.h" +#include "chrome/browser/media/router/media_source.h" +#include "chrome/browser/media/router/media_source_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/sessions/session_tab_helper.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +// Use the following command to run e2e browser tests: +// ./out/Debug/browser_tests --user-data-dir=<empty user data dir> +// --extension-unpacked=<mr extension dir> +// --receiver=<chromecast device name> +// --enable-pixel-output-in-tests --run-manual +// --gtest_filter=MediaRouterE2EBrowserTest.<test case name> +// --enable-logging=stderr +// --whitelisted-extension-id=enhhojjnijigcajfphajepfemndkmdlo +// --ui-test-action-timeout=200000 +// --enable-media-router + +namespace { +// Command line argument to specify receiver, +const char kReceiver[] = "receiver"; +// URL to launch Castv2Player_Staging app on Chromecast +const char kCastAppPresentationUrl[] = + "https://google.com/cast#__castAppId__=BE6E4473"; +} // namespace + +namespace media_router { + +MediaRouterE2EBrowserTest::MediaRouterE2EBrowserTest() + : media_router_(nullptr) { +} + +MediaRouterE2EBrowserTest::~MediaRouterE2EBrowserTest() { +} + +void MediaRouterE2EBrowserTest::SetUpOnMainThread() { + MediaRouterBaseBrowserTest::SetUpOnMainThread(); + media_router_ = + MediaRouterMojoImplFactory::GetApiForBrowserContext(browser()->profile()); + DCHECK(media_router_); +} + +void MediaRouterE2EBrowserTest::TearDownOnMainThread() { + MediaRouterBaseBrowserTest::TearDownOnMainThread(); + media_router_ = nullptr; +} + +void MediaRouterE2EBrowserTest::OnRouteResponseReceived( + scoped_ptr<MediaRoute> route, + const std::string& error) { + ASSERT_TRUE(route.get()); + route_id_ = route->media_route_id(); +} + +void MediaRouterE2EBrowserTest::CreateMediaRoute(const MediaSource& source, + const GURL& origin, + int tab_id) { + DCHECK(media_router_); + observer_.reset(new TestMediaSinksObserver(media_router_, source)); + + DVLOG(1) << "Receiver name: " << receiver_; + // Wait for MediaSinks compatible with |source| to be discovered. + ConditionalWait(base::TimeDelta::FromSeconds(30), + base::TimeDelta::FromSeconds(1), + base::Bind(&MediaRouterE2EBrowserTest::IsSinkDiscovered, + base::Unretained(this))); + + const auto& sink_map = observer_->sink_map; + const auto it = sink_map.find(receiver_); + const MediaSink& sink = it->second; + + // The callback will set route_id_ when invoked. + media_router_->CreateRoute( + source.id(), sink.id(), origin, tab_id, + base::Bind(&MediaRouterE2EBrowserTest::OnRouteResponseReceived, + base::Unretained(this))); + + // Wait for the route request to be fulfilled (and route to be started). + ConditionalWait(base::TimeDelta::FromSeconds(30), + base::TimeDelta::FromSeconds(1), + base::Bind(&MediaRouterE2EBrowserTest::IsRouteCreated, + base::Unretained(this))); +} + +void MediaRouterE2EBrowserTest::StopMediaRoute() { + ASSERT_FALSE(route_id_.empty()); + + media_router_->CloseRoute(route_id_); + + observer_.reset(); + route_id_.clear(); +} + +void MediaRouterE2EBrowserTest::ParseCommandLine() { + MediaRouterBaseBrowserTest::ParseCommandLine(); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + receiver_ = command_line->GetSwitchValueASCII(kReceiver); + ASSERT_FALSE(receiver_.empty()); +} + +bool MediaRouterE2EBrowserTest::IsSinkDiscovered() const { + return ContainsKey(observer_->sink_map, receiver_); +} + +bool MediaRouterE2EBrowserTest::IsRouteCreated() const { + return !route_id_.empty(); +} + +// Test cases + +IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_TabMirroring) { + EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); + + ui_test_utils::NavigateToURLBlockUntilNavigationsComplete( + browser(), GURL("about:blank"), 1); + int tab_id = SessionTabHelper::IdForTab( + browser()->tab_strip_model()->GetActiveWebContents()); + + // Wait for 30 seconds to make sure the route is stable. + CreateMediaRoute(MediaSourceForTab(tab_id), GURL("http://origin/"), tab_id); + Wait(base::TimeDelta::FromSeconds(30)); + + // Wait for 10 seconds to make sure route has been stopped. + StopMediaRoute(); + Wait(base::TimeDelta::FromSeconds(10)); +} + +IN_PROC_BROWSER_TEST_F(MediaRouterE2EBrowserTest, MANUAL_CastApp) { + // Wait for 30 seconds to make sure the route is stable. + CreateMediaRoute(MediaSourceForPresentationUrl(kCastAppPresentationUrl), + GURL("http://origin/"), kInvalidTabId); + Wait(base::TimeDelta::FromSeconds(30)); + + // Wait for 10 seconds to make sure route has been stopped. + StopMediaRoute(); + Wait(base::TimeDelta::FromSeconds(10)); +} + +} // namespace media_router diff --git a/chrome/test/media_router/media_router_e2e_browsertest.h b/chrome/test/media_router/media_router_e2e_browsertest.h new file mode 100644 index 0000000..e88f56c --- /dev/null +++ b/chrome/test/media_router/media_router_e2e_browsertest.h @@ -0,0 +1,73 @@ +// Copyright 2015 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. + +#ifndef CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_E2E_BROWSERTEST_H_ +#define CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_E2E_BROWSERTEST_H_ + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "chrome/browser/media/router/media_route.h" +#include "chrome/browser/media/router/media_router.h" +#include "chrome/test/media_router/media_router_base_browsertest.h" +#include "chrome/test/media_router/test_media_sinks_observer.h" + +namespace media_router { + +class MediaRouter; + +class MediaRouterE2EBrowserTest : public MediaRouterBaseBrowserTest { + public: + MediaRouterE2EBrowserTest(); + ~MediaRouterE2EBrowserTest() override; + + protected: + // InProcessBrowserTest Overrides + void SetUpOnMainThread() override; + void TearDownOnMainThread() override; + + // MediaRouterBaseBrowserTest Overrides + void ParseCommandLine() override; + + // Callback from MediaRouter when a response to a media route request is + // received. + void OnRouteResponseReceived(scoped_ptr<MediaRoute> route, + const std::string& error); + + // Initializes |observer_| to listen for sinks compatible with |source|, + // finds sink with name matching receiver_, and establishes media + // route between the source and sink. + // |observer_| and |route_id_| will be initialized. + // |origin| is the URL of requestor's page. + // |tab_id| is the ID of the tab in which the request was made. + // |origin| and |tab_id| are used for enforcing same-origin and/or same-tab + // scope for JoinRoute() requests. (e.g., if enforced, the page + // requesting JoinRoute() must have the same origin as the page that requested + // CreateRoute()). + void CreateMediaRoute(const MediaSource& source, + const GURL& origin, + int tab_id); + + // Stops the established media route and unregisters |observer_|. + // Note that the route may not be stopped immediately, as it makes an + // async call to the Media Route Provider. + // |observer_| and |route_id_| will be reset. + void StopMediaRoute(); + + std::string receiver() const { return receiver_; } + + bool IsSinkDiscovered() const; + bool IsRouteCreated() const; + + private: + std::string receiver_; + + MediaRouter* media_router_; + scoped_ptr<TestMediaSinksObserver> observer_; + MediaRoute::Id route_id_; +}; + +} // namespace media_router + +#endif // CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_E2E_BROWSERTEST_H_ diff --git a/chrome/test/media_router/media_router_integration_browsertest.cc b/chrome/test/media_router/media_router_integration_browsertest.cc new file mode 100644 index 0000000..9e5ddea --- /dev/null +++ b/chrome/test/media_router/media_router_integration_browsertest.cc @@ -0,0 +1,97 @@ +// Copyright 2015 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 "chrome/test/media_router/media_router_integration_browsertest.h" + +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/path_service.h" +#include "base/strings/stringprintf.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/webui/media_router/media_router_dialog_controller.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_navigation_observer.h" +#include "content/public/test/test_utils.h" +#include "net/base/filename_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media_router { + +MediaRouterIntegrationBrowserTest::MediaRouterIntegrationBrowserTest() { +} + +MediaRouterIntegrationBrowserTest::~MediaRouterIntegrationBrowserTest() { +} + +void MediaRouterIntegrationBrowserTest::ExecuteJavaScriptAPI( + content::WebContents* web_contents, + const std::string& script) { + std::string result; + + ASSERT_TRUE( + content::ExecuteScriptAndExtractString(web_contents, script, &result)); + + // Read the test result, the test result set by javascript is a + // JSON string with the following format: + // {"passed": "<true/false>", "errorMessage": "<error_message>"} + scoped_ptr<base::Value> value = + base::JSONReader::Read(result, base::JSON_ALLOW_TRAILING_COMMAS); + + // Convert to dictionary. + base::DictionaryValue* dict_value = nullptr; + ASSERT_TRUE(value->GetAsDictionary(&dict_value)); + + // Extract the fields. + bool passed = false; + ASSERT_TRUE(dict_value->GetBoolean("passed", &passed)); + std::string error_message; + ASSERT_TRUE(dict_value->GetString("errorMessage", &error_message)); + + EXPECT_TRUE(passed) << error_message; +} + +void MediaRouterIntegrationBrowserTest::OpenTestPage( + base::FilePath::StringPieceType file_name) { + base::FilePath base_dir; + ASSERT_TRUE(PathService::Get(base::DIR_EXE, &base_dir)); + base::FilePath full_path = + base_dir.Append(FILE_PATH_LITERAL("media_router/browser_test_resources/")) + .Append(file_name); + ASSERT_TRUE(PathExists(full_path)); + ui_test_utils::NavigateToURL(browser(), net::FilePathToFileURL(full_path)); +} + +void MediaRouterIntegrationBrowserTest::ChooseSink( + content::WebContents* web_contents, + const std::string& sink_id) { + MediaRouterDialogController* controller = + MediaRouterDialogController::GetOrCreateForWebContents(web_contents); + content::WebContents* dialog_contents = controller->GetMediaRouterDialog(); + ASSERT_TRUE(dialog_contents); + std::string script = base::StringPrintf( + "window.document.getElementById('media-router-container')." + "showOrCreateRoute_({'id': '%s', 'name': ''}, null)", + sink_id.c_str()); + ASSERT_TRUE(content::ExecuteScript(dialog_contents, script)); +} + +IN_PROC_BROWSER_TEST_F(MediaRouterIntegrationBrowserTest, MANUAL_Basic) { + OpenTestPage(FILE_PATH_LITERAL("basic_test.html")); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(web_contents); + content::TestNavigationObserver test_navigation_observer(web_contents, 1); + test_navigation_observer.StartWatchingNewWebContents(); + ExecuteJavaScriptAPI(web_contents, "startSession();"); + test_navigation_observer.Wait(); + ChooseSink(web_contents, "id1"); + ExecuteJavaScriptAPI(web_contents, "checkSession();"); + Wait(base::TimeDelta::FromSeconds(5)); + ExecuteJavaScriptAPI(web_contents, "stopSession();"); +} + +} // namespace media_router diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h new file mode 100644 index 0000000..23c2a5f --- /dev/null +++ b/chrome/test/media_router/media_router_integration_browsertest.h @@ -0,0 +1,40 @@ +// Copyright 2015 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. + +#ifndef CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_INTEGRATION_BROWSERTEST_H_ +#define CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_INTEGRATION_BROWSERTEST_H_ + +#include <string> + +#include "base/debug/stack_trace.h" +#include "base/files/file_path.h" +#include "chrome/test/media_router/media_router_base_browsertest.h" + +namespace media_router { + +class MediaRouter; + +class MediaRouterIntegrationBrowserTest : public MediaRouterBaseBrowserTest { + public: + MediaRouterIntegrationBrowserTest(); + ~MediaRouterIntegrationBrowserTest() override; + + protected: + // Simulate user action to choose one sink in the popup dialog. + // |web_contents|: The web contents of the test page which invokes the popup + // dialog. + // |sink_id|: The sink id. + void ChooseSink(content::WebContents* web_contents, + const std::string& sink_id); + + // Execute javascript and check the return value. + void ExecuteJavaScriptAPI(content::WebContents* web_contents, + const std::string& script); + + void OpenTestPage(base::FilePath::StringPieceType file); +}; + +} // namespace media_router + +#endif // CHROME_TEST_MEDIA_ROUTER_MEDIA_ROUTER_INTEGRATION_BROWSERTEST_H_ diff --git a/chrome/test/media_router/media_router_tests.gypi b/chrome/test/media_router/media_router_tests.gypi new file mode 100644 index 0000000..c46a9e8 --- /dev/null +++ b/chrome/test/media_router/media_router_tests.gypi @@ -0,0 +1,32 @@ +# Copyright 2015 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. + +{ + 'variables': { + 'media_router_integration_test_resources': [ + 'resources/basic_test.html', + 'resources/common.js' + ], + }, # end of variables + 'targets': [ + { + 'target_name': 'media_router_integration_test_files', + 'type': 'none', + 'variables': { + 'output_dir': '<(PRODUCT_DIR)/media_router/browser_test_resources', + 'resource_files': [ + '<@(media_router_integration_test_resources)', + ] + }, + 'copies': [ + { + 'destination': '<(output_dir)', + 'files': [ + '<@(resource_files)', + ], + }, + ], + }, # end of target 'media_router_integration_test_files' + ], # end of targets +}
\ No newline at end of file diff --git a/chrome/test/media_router/media_router_tests.isolate b/chrome/test/media_router/media_router_tests.isolate new file mode 100644 index 0000000..8759728 --- /dev/null +++ b/chrome/test/media_router/media_router_tests.isolate @@ -0,0 +1,46 @@ +# Copyright (c) 2014 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. +{ + 'conditions': [ + ['OS=="linux"', { + 'variables': { + 'command': [ + 'media_router_tests.py', + '--extension', + '<(PRODUCT_DIR)/mr_extension/', + '--prod_dir', + '<(PRODUCT_DIR)', + ], + 'files': [ + 'media_router_tests.py', + '<(PRODUCT_DIR)/browser_tests<(EXECUTABLE_SUFFIX)', + '<(PRODUCT_DIR)/chrome_100_percent.pak', + '<(PRODUCT_DIR)/chrome_200_percent.pak', + '<(PRODUCT_DIR)/libosmesa.so', + '<(PRODUCT_DIR)/locales/en-US.pak', + '<(PRODUCT_DIR)/mr_extension/', + '<(PRODUCT_DIR)/nacl_helper', + '<(PRODUCT_DIR)/nacl_helper_bootstrap', + '<(PRODUCT_DIR)/nacl_irt_x86_64.nexe', + '<(PRODUCT_DIR)/natives_blob.bin', + '<(PRODUCT_DIR)/pnacl/', + '<(PRODUCT_DIR)/resources.pak', + '<(PRODUCT_DIR)/snapshot_blob.bin', + '<(PRODUCT_DIR)/xdisplaycheck<(EXECUTABLE_SUFFIX)', + ], + }, + }], + ['OS=="linux" and component=="shared_library"', { + 'variables': { + 'files': [ + '<(PRODUCT_DIR)/lib/', + '<(PRODUCT_DIR)/lib64/', + ], + }, + }], + ], + 'includes': [ + '../../../base/base.isolate', + ], +}
\ No newline at end of file diff --git a/chrome/test/media_router/resources/basic_test.html b/chrome/test/media_router/resources/basic_test.html new file mode 100644 index 0000000..7d4666f --- /dev/null +++ b/chrome/test/media_router/resources/basic_test.html @@ -0,0 +1,10 @@ +<!DOCTYPE HTML> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <title>MR Integration Basic Test</title> + <link href="https://www.google.com/cast?__testprovider__=true" rel="default-presentation"> + <script type="text/javascript" src="common.js"></script> + </head> + <body> + </body> +</html>
\ No newline at end of file diff --git a/chrome/test/media_router/resources/common.js b/chrome/test/media_router/resources/common.js new file mode 100644 index 0000000..c03ed2c --- /dev/null +++ b/chrome/test/media_router/resources/common.js @@ -0,0 +1,79 @@ +/** + * Copyright 2015 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. + * + * @fileoverview Common APIs for presentation integration tests. + * + */ + +var startSessionPromise = null; +var currentSession = null; +var presentation = window.navigator.presentation; + + +/** + * Waits until one device is available then starts session. + */ +function startSession() { + presentation.onavailablechange = function (e) { + console.log('onavailablechange ' + e.available + '\n'); + if (!e.available) { + sendResult(false, 'device unavailable'); + } else { + var presId = Math.random().toFixed(6).substr(2); + // Start new session + startSessionPromise = presentation.startSession( + "http://www.google.com/#__testprovider__=true", presId) + sendResult(true, ''); + } + }; +} + +/** + * Checks if the session has been started successfully. + */ +function checkSession() { + if (!startSessionPromise) { + sendResult(false, 'Failed to start session'); + } else { + startSessionPromise.then(function (currentSession) { + if(!currentSession) { + sendResult(false, 'Failed to start session'); + } else { + // set the new session + currentSession = currentSession; + sendResult(true, ''); + } + }).catch(function() { + // close old session if exists + currentSession && currentSession.close(); + sendResult(false, 'Failed to start session'); + }) + } +} + + +/** + * Stops current session. + */ +function stopSession() { + if (currentSession) { + currentSession.close(); + } + sendResult(true, ''); +} + + +/** + * Sends the test result back to browser test. + * @param passed true if test passes, otherwise false. + * @param errorMessage empty string if test passes, error message if test + * fails. + */ +function sendResult(passed, errorMessage) { + window.domAutomationController.send(JSON.stringify({ + passed: passed, + errorMessage: errorMessage + })); +}
\ No newline at end of file diff --git a/chrome/test/media_router/test_media_sinks_observer.cc b/chrome/test/media_router/test_media_sinks_observer.cc new file mode 100644 index 0000000..c4a9fce --- /dev/null +++ b/chrome/test/media_router/test_media_sinks_observer.cc @@ -0,0 +1,29 @@ +// Copyright 2015 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 <string> +#include <utility> + +#include "chrome/browser/media/router/media_router.h" +#include "chrome/test/media_router/test_media_sinks_observer.h" + +namespace media_router { + +TestMediaSinksObserver::TestMediaSinksObserver(MediaRouter* router, + const MediaSource& source) + : MediaSinksObserver(router, source) { +} + +TestMediaSinksObserver::~TestMediaSinksObserver() { +} + +void TestMediaSinksObserver::OnSinksReceived( + const std::vector<MediaSink>& result) { + sink_map.clear(); + for (const MediaSink& sink : result) { + sink_map.insert(std::make_pair(sink.name(), sink)); + } +} + +} // namespace media_router diff --git a/chrome/test/media_router/test_media_sinks_observer.h b/chrome/test/media_router/test_media_sinks_observer.h new file mode 100644 index 0000000..d4607d8 --- /dev/null +++ b/chrome/test/media_router/test_media_sinks_observer.h @@ -0,0 +1,34 @@ +// Copyright 2015 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 <map> +#include <string> +#include <vector> + +#include "chrome/browser/media/router/media_sinks_observer.h" + +#ifndef CHROME_TEST_MEDIA_ROUTER_TEST_MEDIA_SINKS_OBSERVER_H_ +#define CHROME_TEST_MEDIA_ROUTER_TEST_MEDIA_SINKS_OBSERVER_H_ + +namespace media_router { + +class MediaRouter; + +// Test class to implement MediaSinksObserver that receives SinkQueryResults +// from Media Router and is used for verification. +class TestMediaSinksObserver : public MediaSinksObserver { + public: + TestMediaSinksObserver(MediaRouter* router, const MediaSource& source); + ~TestMediaSinksObserver() override; + + // MediaSinksObserver implementation. + void OnSinksReceived(const std::vector<MediaSink>& result) override; + + // Map of <sink_name, media_sink_object> + std::map<std::string, const MediaSink> sink_map; +}; + +} // namespace media_router + +#endif // CHROME_TEST_MEDIA_ROUTER_TEST_MEDIA_SINKS_OBSERVER_H_ |