Autoplay/PWA: set web_app_scope preference on desktop.

This will make desktop PWA have autoplay privileges in their scope.

Bug: 923910, 794874
Change-Id: Ie9895140c7892d8cace1f09054f527aba6858f09
Reviewed-on: https://chromium-review.googlesource.com/c/1436574
Commit-Queue: Mounir Lamouri <mlamouri@chromium.org>
Reviewed-by: Dominick Ng <dominickn@chromium.org>
Reviewed-by: Nasko Oskov <nasko@chromium.org>
Auto-Submit: Mounir Lamouri <mlamouri@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#628013}(cherry picked from commit 6926107f34d236e430df08ea5dc9a5327c17ed41)
Reviewed-on: https://chromium-review.googlesource.com/c/1450455
Reviewed-by: Mounir Lamouri <mlamouri@chromium.org>
Cr-Commit-Position: refs/branch-heads/3683@{#132}
Cr-Branched-From: e51029943e0a38dd794b73caaf6373d5496ae783-refs/heads/master@{#625896}
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 81c2d0f..2b21cbe 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -490,6 +490,8 @@
 #include "chrome/browser/extensions/bookmark_app_navigation_throttle.h"
 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
+#include "chrome/browser/extensions/convert_web_app.h"
+#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/user_script_listener.h"
 #include "chrome/browser/media/cast_transport_host_filter.h"
 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
@@ -3191,13 +3193,38 @@
       web_prefs->embedded_media_experience_enabled =
           tab_android->ShouldEnableEmbeddedMediaExperience();
 
-      web_prefs->web_app_scope = tab_android->GetWebappManifestScope();
-
       web_prefs->picture_in_picture_enabled =
           tab_android->IsPictureInPictureEnabled();
     }
 #endif  // defined(OS_ANDROID)
 
+    // web_app_scope value is platform specific.
+#if defined(OS_ANDROID)
+    if (tab_android)
+      web_prefs->web_app_scope = tab_android->GetWebappManifestScope();
+#elif BUILDFLAG(ENABLE_EXTENSIONS)
+    {
+      const extensions::Extension* extension = nullptr;
+      Browser* browser = chrome::FindBrowserWithWebContents(contents);
+      if (base::FeatureList::IsEnabled(features::kDesktopPWAWindowing) &&
+          browser && browser->hosted_app_controller() &&
+          browser->hosted_app_controller()->created_for_installed_pwa()) {
+        // When a new window is created to host a PWA, this method will return
+        // the scope of the given PWA. It will stay the same for the PWA as
+        // scopes never change after the window was created. It is not
+        // guaranteed that this method will be called on every navigation but
+        // this is not required for things to work, we only need it to be called
+        // at the window creation time.
+        extension = extensions::util::GetInstalledPwaForUrl(
+            contents->GetBrowserContext(), contents->GetLastCommittedURL());
+      }
+
+      web_prefs->web_app_scope =
+          extension ? extensions::GetScopeURLFromBookmarkApp(extension)
+                    : GURL();
+    }
+#endif
+
 #if BUILDFLAG(ENABLE_EXTENSIONS)
     Browser* browser = chrome::FindBrowserWithWebContents(contents);
     if (browser && browser->hosted_app_controller() &&
diff --git a/chrome/browser/media/unified_autoplay_browsertest.cc b/chrome/browser/media/unified_autoplay_browsertest.cc
index 6877beb..78c22c4d 100644
--- a/chrome/browser/media/unified_autoplay_browsertest.cc
+++ b/chrome/browser/media/unified_autoplay_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/test/scoped_feature_list.h"
+#include "chrome/browser/chrome_content_browser_client.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -11,7 +12,9 @@
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/web_preferences.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_frame_navigation_observer.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -27,6 +30,27 @@
 
 static constexpr char const kTestPagePath[] = "/media/unified_autoplay.html";
 
+class ChromeContentBrowserClientOverrideWebAppScope
+    : public ChromeContentBrowserClient {
+ public:
+  ChromeContentBrowserClientOverrideWebAppScope() = default;
+  ~ChromeContentBrowserClientOverrideWebAppScope() override = default;
+
+  void OverrideWebkitPrefs(content::RenderViewHost* rvh,
+                           content::WebPreferences* web_prefs) override {
+    ChromeContentBrowserClient::OverrideWebkitPrefs(rvh, web_prefs);
+
+    web_prefs->web_app_scope = web_app_scope_;
+  }
+
+  void set_web_app_scope(const GURL& web_app_scope) {
+    web_app_scope_ = web_app_scope;
+  }
+
+ private:
+  GURL web_app_scope_;
+};
+
 }  // anonymous namespace
 
 // Integration tests for the unified autoplay policy that require the //chrome
@@ -325,6 +349,69 @@
   EXPECT_FALSE(AttemptPlay(GetWebContents()));
 }
 
+IN_PROC_BROWSER_TEST_F(UnifiedAutoplayBrowserTest,
+                       MatchingWebAppScopeAllowsAutoplay_Origin) {
+  GURL kTestPageUrl(
+      embedded_test_server()->GetURL("example.com", kTestPagePath));
+
+  ChromeContentBrowserClientOverrideWebAppScope browser_client;
+  browser_client.set_web_app_scope(kTestPageUrl.GetOrigin());
+
+  content::ContentBrowserClient* old_browser_client =
+      content::SetBrowserClientForTesting(&browser_client);
+
+  GetWebContents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+
+  ui_test_utils::NavigateToURL(browser(), kTestPageUrl);
+  content::WaitForLoadStop(GetWebContents());
+
+  EXPECT_TRUE(AttemptPlay(GetWebContents()));
+
+  content::SetBrowserClientForTesting(old_browser_client);
+}
+
+IN_PROC_BROWSER_TEST_F(UnifiedAutoplayBrowserTest,
+                       MatchingWebAppScopeAllowsAutoplay_Path) {
+  GURL kTestPageUrl(
+      embedded_test_server()->GetURL("example.com", kTestPagePath));
+
+  ChromeContentBrowserClientOverrideWebAppScope browser_client;
+  browser_client.set_web_app_scope(kTestPageUrl.GetWithoutFilename());
+
+  content::ContentBrowserClient* old_browser_client =
+      content::SetBrowserClientForTesting(&browser_client);
+
+  GetWebContents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+
+  ui_test_utils::NavigateToURL(browser(), kTestPageUrl);
+  content::WaitForLoadStop(GetWebContents());
+
+  EXPECT_TRUE(AttemptPlay(GetWebContents()));
+
+  content::SetBrowserClientForTesting(old_browser_client);
+}
+
+IN_PROC_BROWSER_TEST_F(UnifiedAutoplayBrowserTest,
+                       NotMatchingWebAppScopeDoesNotAllowAutoplay) {
+  GURL kTestPageUrl(
+      embedded_test_server()->GetURL("example.com", kTestPagePath));
+
+  ChromeContentBrowserClientOverrideWebAppScope browser_client;
+  browser_client.set_web_app_scope(GURL("http://www.foobar.com"));
+
+  content::ContentBrowserClient* old_browser_client =
+      content::SetBrowserClientForTesting(&browser_client);
+
+  GetWebContents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+
+  ui_test_utils::NavigateToURL(browser(), kTestPageUrl);
+  content::WaitForLoadStop(GetWebContents());
+
+  EXPECT_FALSE(AttemptPlay(GetWebContents()));
+
+  content::SetBrowserClientForTesting(old_browser_client);
+}
+
 // Integration tests for the new unified autoplay sound settings UI.
 
 class UnifiedAutoplaySettingBrowserTest : public UnifiedAutoplayBrowserTest {
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index 72972fd..c97cf26 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -201,12 +201,12 @@
   IPC_STRUCT_TRAITS_MEMBER(text_track_text_color)
   IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
   IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
+  IPC_STRUCT_TRAITS_MEMBER(web_app_scope)
 #if defined(OS_ANDROID)
   IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
   IPC_STRUCT_TRAITS_MEMBER(device_scale_adjustment)
   IPC_STRUCT_TRAITS_MEMBER(force_enable_zoom)
   IPC_STRUCT_TRAITS_MEMBER(fullscreen_supported)
-  IPC_STRUCT_TRAITS_MEMBER(web_app_scope)
   IPC_STRUCT_TRAITS_MEMBER(default_video_poster_url)
   IPC_STRUCT_TRAITS_MEMBER(support_deprecated_target_density_dpi)
   IPC_STRUCT_TRAITS_MEMBER(use_legacy_background_size_shorthand_behavior)
diff --git a/content/public/common/web_preferences.h b/content/public/common/web_preferences.h
index 579c086..52edd1a 100644
--- a/content/public/common/web_preferences.h
+++ b/content/public/common/web_preferences.h
@@ -226,12 +226,14 @@
 
   bool text_autosizing_enabled;
 
+  // Representation of the Web App Manifest scope if any.
+  GURL web_app_scope;
+
 #if defined(OS_ANDROID)
   float font_scale_factor;
   float device_scale_adjustment;
   bool force_enable_zoom;
   bool fullscreen_supported;
-  GURL web_app_scope;
   GURL default_video_poster_url;
   bool support_deprecated_target_density_dpi;
   bool use_legacy_background_size_shorthand_behavior;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index dd4a028..676b344 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -822,6 +822,8 @@
       static_cast<blink::WebEffectiveConnectionType>(
           prefs.network_quality_estimator_web_holdback));
 
+  settings->SetWebAppScope(WebString::FromASCII(prefs.web_app_scope.spec()));
+
 #if defined(OS_ANDROID)
   settings->SetAllowCustomScrollbarInMainFrame(false);
   settings->SetAccessibilityFontScaleFactor(prefs.font_scale_factor);
@@ -829,7 +831,6 @@
   settings->SetFullscreenSupported(prefs.fullscreen_supported);
   web_view->SetIgnoreViewportTagScaleLimits(prefs.force_enable_zoom);
   settings->SetAutoZoomFocusedNodeToLegibleScale(true);
-  settings->SetWebAppScope(WebString::FromASCII(prefs.web_app_scope.spec()));
   settings->SetDefaultVideoPosterURL(
       WebString::FromASCII(prefs.default_video_poster_url.spec()));
   settings->SetSupportDeprecatedTargetDensityDPI(