| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| |
| #include "base/functional/callback.h" |
| #include "chrome/browser/apps/app_service/app_service_proxy.h" |
| #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" |
| #include "chrome/browser/apps/platform_apps/app_browsertest_util.h" |
| #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" |
| #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ssl/https_upgrades_util.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h" |
| #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" |
| #include "chrome/browser/ui/web_applications/web_app_browsertest_base.h" |
| #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" |
| #include "chrome/browser/web_applications/test/web_app_test_observers.h" |
| #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "components/app_constants/constants.h" |
| #include "content/public/browser/browser_task_traits.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/test/browser_test.h" |
| #include "extensions/common/extension.h" |
| #include "third_party/blink/public/common/mediastream/media_stream_request.h" |
| #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" |
| |
| using extensions::Extension; |
| |
| namespace { |
| |
| bool AccessingCamera(Profile* profile, const std::string& app_id) { |
| std::optional<bool> accessing_camera; |
| auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); |
| proxy->AppCapabilityAccessCache().ForOneApp( |
| app_id, [&accessing_camera](const apps::CapabilityAccessUpdate& update) { |
| accessing_camera = update.Camera(); |
| }); |
| return accessing_camera.value_or(false); |
| } |
| |
| bool AccessingMicrophone(Profile* profile, const std::string& app_id) { |
| std::optional<bool> accessing_microphone; |
| auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); |
| proxy->AppCapabilityAccessCache().ForOneApp( |
| app_id, |
| [&accessing_microphone](const apps::CapabilityAccessUpdate& update) { |
| accessing_microphone = update.Microphone(); |
| }); |
| return accessing_microphone.value_or(false); |
| } |
| |
| // Adds a fake media device with the specified `stream_type` and starts |
| // capturing. Returns a closure to stop the capturing. |
| base::OnceClosure StartMediaCapture(content::WebContents* web_contents, |
| blink::mojom::MediaStreamType stream_type) { |
| blink::mojom::StreamDevices fake_devices; |
| blink::MediaStreamDevice device(stream_type, "fake_device", "fake_device"); |
| |
| if (stream_type == blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE || |
| stream_type == blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE) { |
| device.display_media_info = media::mojom::DisplayMediaInformation::New( |
| media::mojom::DisplayCaptureSurfaceType::WINDOW, |
| /*logical_surface=*/true, media::mojom::CursorCaptureType::NEVER, |
| /*capture_handle=*/nullptr, |
| /*initial_zoom_level=*/100); |
| } |
| |
| if (blink::IsAudioInputMediaType(stream_type)) { |
| fake_devices.audio_device = device; |
| } else { |
| fake_devices.video_device = device; |
| } |
| |
| std::unique_ptr<content::MediaStreamUI> ui = |
| MediaCaptureDevicesDispatcher::GetInstance() |
| ->GetMediaStreamCaptureIndicator() |
| ->RegisterMediaStream(web_contents, fake_devices); |
| |
| ui->OnStarted(base::RepeatingClosure(), |
| content::MediaStreamUI::SourceCallback(), |
| /*label=*/std::string(), /*screen_capture_ids=*/{}, |
| content::MediaStreamUI::StateChangeCallback()); |
| |
| return base::BindOnce( |
| [](std::unique_ptr<content::MediaStreamUI> ui) { ui.reset(); }, |
| std::move(ui)); |
| } |
| |
| } // namespace |
| |
| class MediaAccessExtensionAppsTest : public extensions::PlatformAppBrowserTest { |
| public: |
| void SetUpOnMainThread() override { |
| extensions::PlatformAppBrowserTest::SetUpOnMainThread(); |
| |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| } |
| |
| void UninstallApp(const std::string& app_id) { |
| auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile()); |
| proxy->UninstallSilently(app_id, apps::UninstallSource::kAppList); |
| } |
| |
| GURL GetUrl1() { |
| return embedded_test_server()->GetURL("app.com", "/ssl/google.html"); |
| } |
| |
| GURL GetUrl2() { |
| return embedded_test_server()->GetURL("app.com", "/google/google.html"); |
| } |
| |
| content::WebContents* GetWebContents() { |
| return browser()->tab_strip_model()->GetActiveWebContents(); |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessExtensionAppsTest, |
| RequestAccessingForChromeInTabs) { |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl1())); |
| |
| content::WebContents* web_content1 = GetWebContents(); |
| // Request accessing the camera for |web_content1|. |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| AddBlankTabAndShow(browser()); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl2())); |
| content::WebContents* web_content2 = GetWebContents(); |
| // Request accessing the microphone for |web_content2|. |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Stop accessing the camera for |web_content1|. |
| std::move(video_closure1).Run(); |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Stop accessing the microphone for |web_content2|. |
| std::move(audio_closure1).Run(); |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessExtensionAppsTest, |
| RequestAccessingForChromeInNewBrowsers) { |
| Browser* browser1 = |
| Browser::Create(Browser::CreateParams(browser()->profile(), true)); |
| ASSERT_TRUE(browser1); |
| ASSERT_NE(browser(), browser1); |
| |
| AddBlankTabAndShow(browser1); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser1, GetUrl1())); |
| content::WebContents* web_content1 = |
| browser1->tab_strip_model()->GetActiveWebContents(); |
| // Request accessing the camera and the microphone for |web_content1|. |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| AddBlankTabAndShow(browser1); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser1, GetUrl2())); |
| content::WebContents* web_content2 = |
| browser1->tab_strip_model()->GetActiveWebContents(); |
| // Request accessing the camera and the microphone for |web_content2|. |
| base::OnceClosure video_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| base::OnceClosure audio_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Close the tab for |web_content2|. |
| browser1->tab_strip_model()->CloseSelectedTabs(); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| std::move(video_closure2).Run(); |
| std::move(audio_closure2).Run(); |
| |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_TRUE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Close the tab for |web_content1|. |
| browser1->tab_strip_model()->CloseSelectedTabs(); |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| std::move(video_closure1).Run(); |
| std::move(audio_closure1).Run(); |
| |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessExtensionAppsTest, |
| RequestAccessingForPlatformApp) { |
| const Extension* extension = |
| LoadAndLaunchPlatformApp("context_menu", "Launched"); |
| ASSERT_TRUE(extension); |
| |
| content::WebContents* web_contents = GetFirstAppWindowWebContents(); |
| ASSERT_TRUE(web_contents); |
| |
| // Request accessing the camera for |web_contents|. |
| base::OnceClosure video_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), extension->id())); |
| |
| // Request accessing the microphone for |web_contents|. |
| base::OnceClosure audio_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), extension->id())); |
| |
| // Stop accessing the microphone for |web_contents|. |
| std::move(audio_closure).Run(); |
| |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), extension->id())); |
| |
| // Stop accessing the camera for |web_contents|. |
| std::move(video_closure).Run(); |
| |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), extension->id())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessExtensionAppsTest, |
| RequestAccessingForHostApp) { |
| ScopedAllowHttpForHostnamesForTesting allow_http({"www.example.com"}, |
| profile()->GetPrefs()); |
| |
| const Extension* extension = |
| LoadExtension(test_data_dir_.AppendASCII("app1")); |
| ASSERT_TRUE(extension); |
| |
| // Navigate to the app's launch URL. |
| auto url = extensions::AppLaunchInfo::GetLaunchWebURL(extension); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); |
| |
| content::WebContents* web_content1 = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(web_content1); |
| |
| // Request accessing the camera and microphone for |web_contents|. |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), extension->id())); |
| |
| AddBlankTabAndShow(browser()); |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl1())); |
| content::WebContents* web_content2 = GetWebContents(); |
| |
| // Request accessing the camera for |web_content2|. |
| base::OnceClosure video_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), extension->id())); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), extension->id())); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Uninstall the app. |
| std::string app_id = extension->id(); |
| UninstallApp(app_id); |
| |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Stop accessing the camera for |web_content2|. |
| std::move(video_closure2).Run(); |
| |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessExtensionAppsTest, |
| RequestAccessingStreamTypesForChromeInTabs) { |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl1())); |
| |
| content::WebContents* web_contents = GetWebContents(); |
| // Request DEVICE_VIDEO_CAPTURE accessing the camera for |web_contents|. |
| base::OnceClosure video_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Request GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |web_contents|. |
| base::OnceClosure desktop_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Stop GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |web_contents|. |
| std::move(desktop_closure).Run(); |
| EXPECT_TRUE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| |
| // Stop DEVICE_VIDEO_CAPTURE accessing the camera for |web_contents|. |
| std::move(video_closure).Run(); |
| EXPECT_FALSE( |
| AccessingCamera(browser()->profile(), app_constants::kChromeAppId)); |
| EXPECT_FALSE( |
| AccessingMicrophone(browser()->profile(), app_constants::kChromeAppId)); |
| } |
| |
| class MediaAccessWebAppsTest : public web_app::WebAppBrowserTestBase { |
| public: |
| MediaAccessWebAppsTest() = default; |
| ~MediaAccessWebAppsTest() override = default; |
| |
| std::string CreateWebApp(const GURL& url) const { |
| auto web_app_info = |
| web_app::WebAppInstallInfo::CreateWithStartUrlForTesting(url); |
| web_app_info->scope = url; |
| return web_app::test::InstallWebApp(browser()->profile(), |
| std::move(web_app_info)); |
| } |
| |
| void UninstallWebApp(const std::string& app_id) const { |
| web_app::WebAppTestUninstallObserver app_listener(browser()->profile()); |
| app_listener.BeginListening(); |
| web_app::test::UninstallWebApp(browser()->profile(), app_id); |
| app_listener.Wait(); |
| } |
| |
| GURL GetUrl1() { |
| return https_server()->GetURL("app.com", "/ssl/google.html"); |
| } |
| |
| GURL GetUrl2() { |
| return https_server()->GetURL("app.com", "/google/google.html"); |
| } |
| |
| content::WebContents* GetWebContents() { |
| return browser()->tab_strip_model()->GetActiveWebContents(); |
| } |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, RequestAccessingCamera) { |
| std::string app_id = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request accessing the camera for |app_id| in the new tab. |
| content::WebContents* web_content1 = GetWebContents(); |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Launch |app_id| in a new window. |
| content::WebContents* web_content2 = OpenApplication(app_id); |
| BrowserWindowInterface* const app_browser = |
| GetLastActiveBrowserWindowInterfaceWithAnyProfile(); |
| ASSERT_TRUE(app_browser); |
| ASSERT_NE(browser(), app_browser); |
| |
| // Request accessing the camera for |app_id| in the new window. |
| base::OnceClosure video_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop accessing the camera for |app_id| in the tab. |
| std::move(video_closure1).Run(); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop accessing the camera for |app_id| in the window. |
| std::move(video_closure2).Run(); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| |
| web_app::CloseAndWait(app_browser); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| web_app::CloseAndWait(browser()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, RequestAccessingMicrophone) { |
| std::string app_id = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request accessing the microphone for |app_id| in the new tab. |
| content::WebContents* web_content1 = GetWebContents(); |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id)); |
| |
| // Launch |app_id| in a new window. |
| content::WebContents* web_content2 = OpenApplication(app_id); |
| BrowserWindowInterface* const app_browser = |
| GetLastActiveBrowserWindowInterfaceWithAnyProfile(); |
| ASSERT_TRUE(app_browser); |
| ASSERT_NE(browser(), app_browser); |
| |
| // Request accessing the microphone for |app_id| in the new window. |
| base::OnceClosure audio_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id)); |
| |
| // Close browsers. |
| web_app::CloseAndWait(app_browser); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id)); |
| |
| // Stop accessing the microphone for |app_id| in the tab. |
| std::move(audio_closure1).Run(); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| |
| // Stop accessing the microphone for |app_id| in the window. |
| std::move(audio_closure2).Run(); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, RemoveApp) { |
| std::string app_id = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request accessing the camera and the microphone for |app_id| in the new |
| // tab. |
| content::WebContents* web_content1 = GetWebContents(); |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Launch |app_id| in a new window. |
| content::WebContents* web_content2 = OpenApplication(app_id); |
| BrowserWindowInterface* const app_browser = |
| GetLastActiveBrowserWindowInterfaceWithAnyProfile(); |
| ASSERT_TRUE(app_browser); |
| ASSERT_NE(browser(), app_browser); |
| |
| // Request accessing the camera and the microphone for |app_id| in the new |
| // window. |
| base::OnceClosure audio_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| UninstallWebApp(app_id); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| |
| CreateWebApp(GetUrl1()); |
| |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, TwoApps) { |
| std::string app_id1 = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id1| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id1); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request accessing the camera and the microphone for |app_id1| in the new |
| // tab. |
| content::WebContents* web_content1 = GetWebContents(); |
| base::OnceClosure audio_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure1 = StartMediaCapture( |
| web_content1, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id1)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id1)); |
| |
| std::string app_id2 = CreateWebApp(GetUrl2()); |
| |
| // Launch |app_id2| in a new window. |
| content::WebContents* web_content2 = OpenApplication(app_id2); |
| BrowserWindowInterface* const app_browser = |
| GetLastActiveBrowserWindowInterfaceWithAnyProfile(); |
| ASSERT_TRUE(app_browser); |
| ASSERT_NE(browser(), app_browser); |
| |
| // Request accessing the camera and the microphone for |app_id2| in the new |
| // window. |
| base::OnceClosure audio_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure2 = StartMediaCapture( |
| web_content2, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id2)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id2)); |
| |
| UninstallWebApp(app_id1); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id1)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id1)); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id2)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id2)); |
| std::move(audio_closure1).Run(); |
| std::move(video_closure1).Run(); |
| |
| // Stop accessing the camera and the microphone for |app_id2|. |
| std::move(audio_closure2).Run(); |
| std::move(video_closure2).Run(); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id2)); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id2)); |
| |
| // Navigate to Url1, and check |app_id1| is not accessing the camera or the |
| // microphone, because it has been removed. |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl1())); |
| auto* web_content3 = GetWebContents(); |
| base::OnceClosure audio_closure3 = StartMediaCapture( |
| web_content3, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure3 = StartMediaCapture( |
| web_content3, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id1)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id1)); |
| std::move(audio_closure3).Run(); |
| std::move(video_closure3).Run(); |
| |
| // Navigate to Url2, and check |app_id2| is accessing the camera and the |
| // microphone. |
| ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl2())); |
| auto* web_content4 = GetWebContents(); |
| base::OnceClosure audio_closure4 = StartMediaCapture( |
| web_content4, blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE); |
| base::OnceClosure video_closure4 = StartMediaCapture( |
| web_content4, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingMicrophone(browser()->profile(), app_id2)); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id2)); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id1)); |
| EXPECT_FALSE(AccessingMicrophone(browser()->profile(), app_id1)); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, |
| RequestAccessingCamera_DesktopCaptureAfter) { |
| std::string app_id = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request DEVICE_VIDEO_CAPTURE accessing the camera for |app_id| in the new |
| // tab. |
| content::WebContents* web_contents = GetWebContents(); |
| base::OnceClosure video_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Request GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |app_id| in the |
| // new tab. |
| base::OnceClosure desktop_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop DEVICE_VIDEO_CAPTURE accessing the camera for |app_id| in the tab. |
| std::move(video_closure).Run(); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |app_id| in the |
| // tab. |
| std::move(desktop_closure).Run(); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| |
| web_app::CloseAndWait(browser()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(MediaAccessWebAppsTest, |
| RequestAccessingCamera_DesktopCaptureBefore) { |
| std::string app_id = CreateWebApp(GetUrl1()); |
| |
| // Launch |app_id| in a new tab. |
| web_app::LaunchWebAppBrowser(browser()->profile(), app_id); |
| web_app::NavigateViaLinkClickToURLAndWait(browser(), GetUrl1()); |
| |
| // Request GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |app_id| in the |
| // new tab. |
| content::WebContents* web_contents = GetWebContents(); |
| base::OnceClosure desktop_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Request DEVICE_VIDEO_CAPTURE accessing the camera for |app_id| in the new |
| // tab. |
| base::OnceClosure video_closure = StartMediaCapture( |
| web_contents, blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop GUM_DESKTOP_VIDEO_CAPTURE accessing the camera for |app_id| in the |
| // tab. |
| std::move(desktop_closure).Run(); |
| EXPECT_TRUE(AccessingCamera(browser()->profile(), app_id)); |
| |
| // Stop DEVICE_VIDEO_CAPTURE accessing the camera for |app_id| in the tab. |
| std::move(video_closure).Run(); |
| EXPECT_FALSE(AccessingCamera(browser()->profile(), app_id)); |
| |
| web_app::CloseAndWait(browser()); |
| } |