From: uazo <uazo@users.noreply.github.com>
Date: Sat, 7 Nov 2020 21:59:18 +0000
Subject: Revert the removal of an option to block autoplay

Original License: GPL-2.0-or-later - https://spdx.org/licenses/GPL-2.0-or-later.html
License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
 .../browser_ui/site_settings/android/BUILD.gn |   5 ++++
 .../res/drawable-hdpi/settings_autoplay.png   | Bin 0 -> 456 bytes
 .../res/drawable-mdpi/settings_autoplay.png   | Bin 0 -> 296 bytes
 .../res/drawable-xhdpi/settings_autoplay.png  | Bin 0 -> 551 bytes
 .../res/drawable-xxhdpi/settings_autoplay.png | Bin 0 -> 792 bytes
 .../drawable-xxxhdpi/settings_autoplay.png    | Bin 0 -> 1064 bytes
 .../res/xml/site_settings_preferences.xml     |   4 ++++
 .../ContentSettingsResources.java             |   5 +++-
 .../site_settings/SingleCategorySettings.java |   4 ++++
 .../site_settings/SingleWebsiteSettings.java  |  22 ++++++++++++++++++
 .../site_settings/SiteSettingsCategory.java   |   9 +++++--
 .../browser_ui/site_settings/Website.java     |   9 +++++++
 .../WebsitePermissionsFetcher.java            |   1 +
 .../android/website_preference_bridge.cc      |   1 +
 .../strings/android/site_settings.grdp        |   9 +++++++
 .../core/browser/content_settings_registry.cc |   2 +-
 .../core/browser/content_settings_utils.cc    |   2 ++
 .../core/common/content_settings.cc           |   2 ++
 .../core/common/content_settings.h            |   1 +
 .../core/common/content_settings.mojom        |   1 +
 .../common/content_settings_mojom_traits.cc   |   1 +
 .../common/content_settings_mojom_traits.h    |   5 ++++
 .../renderer/content_settings_agent_impl.cc   |  11 +++++++++
 .../renderer/content_settings_agent_impl.h    |   1 +
 .../android/page_info_controller_android.cc   |   1 +
 components/page_info/page_info.cc             |   6 +++++
 components/page_info/page_info_ui.cc          |   1 +
 components/site_settings_strings.grdp         |   3 +++
 .../platform/web_content_settings_client.h    |   3 +++
 .../core/html/media/autoplay_policy.cc        |  12 ++++++++++
 .../core/html/media/autoplay_policy.h         |   4 ++++
 31 files changed, 121 insertions(+), 4 deletions(-)
 create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-hdpi/settings_autoplay.png
 create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-mdpi/settings_autoplay.png
 create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-xhdpi/settings_autoplay.png
 create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-xxhdpi/settings_autoplay.png
 create mode 100644 components/browser_ui/site_settings/android/java/res/drawable-xxxhdpi/settings_autoplay.png

diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn
--- a/components/browser_ui/site_settings/android/BUILD.gn
+++ b/components/browser_ui/site_settings/android/BUILD.gn
@@ -171,6 +171,11 @@ android_resources("java_resources") {
     "java/res/drawable-mdpi/ic_volume_up_grey600_24dp.png",
     "java/res/drawable-mdpi/permission_background_sync.png",
     "java/res/drawable-mdpi/permission_javascript.png",
+    "java/res/drawable-hdpi/settings_autoplay.png",
+    "java/res/drawable-xhdpi/settings_autoplay.png",
+    "java/res/drawable-xxhdpi/settings_autoplay.png",
+    "java/res/drawable-mdpi/settings_autoplay.png",
+    "java/res/drawable-xxxhdpi/settings_autoplay.png",
     "java/res/drawable-mdpi/permission_popups.png",
     "java/res/drawable-mdpi/permission_protected_media.png",
     "java/res/drawable-mdpi/settings_sensors.png",
diff --git a/components/browser_ui/site_settings/android/java/res/drawable-hdpi/settings_autoplay.png b/components/browser_ui/site_settings/android/java/res/drawable-hdpi/settings_autoplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..a8a9265f14cd8445ad1f55845099e60dc3c4edf1
GIT binary patch
literal 456
zcmV;(0XP1MP)<h;3K|Lk000e1NJLTq001Na001Ni1ONa4O9@aD0004xNkl<Zcmd^>
zv2MaJ5QYmZs7m@68Tt%)0T}7#GcJmh4B69}fh}W`x!sUhd4N1chpY%8u@-es;cQTy
zGbWY1VQ**q%l&uuT^{am%=;qbIaI7>hvTfF;<*Ut{eMAbL!QB&HFUzBXR~2P41Zx8
z)>!6-O>RP(9xN_j-$FSZiy-wPUj)-Jl(4<5Et;Mc!<K5}jwP!>dwn%v3G5VXX+fR6
zfpz3x+Y|Y)K6`aNHVw{qdv4}^DAdl0F;g<cu%;M_QeJHg8RVIajV_AK%qV!0vEmv1
z#vVbjZa-Q+lSd;emiMaVzX)Z*+nGY^7d%tYY9KFz2z6mO9x2+}RepX<5}`zKxo)iR
zz{m)~NhMClXs`4GHM$vG2T_S4KzpqpIGl{BX8{q3sfX5s0TlVSK=Ataj-&0{v9#{N
z{;&j_q`#yfB8jBm<%OhAge7edm84b@`b2QRo9WRKN#xNwD<h5zoBL8ri$BDs;tw$`
y{$1Kp0i#npN<C~x1#L&}8>IV|-Tf!x{>CqV{oZM{Igf1s0000<MNUMnLSTY>m&@A#

literal 0
HcmV?d00001

diff --git a/components/browser_ui/site_settings/android/java/res/drawable-mdpi/settings_autoplay.png b/components/browser_ui/site_settings/android/java/res/drawable-mdpi/settings_autoplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..49fa10d44f4007532d0d03d15fdcb1a715857e96
GIT binary patch
literal 296
zcmV+@0oVSCP)<h;3K|Lk000e1NJLTq000;O000;W1ONa4N`Cco0002*Nkl<Zc-p;F
zu?>ST5R5=Hk+X;yg9#|y{3AI^L4jN_0yR^lp<y0UAY}`bhK9U}6x+c{;s$?XpYHT`
z_WQ8+DiaXc!3Y!8NIOv`U+9>_9hQ%}W9}t45w<H~z#4hQDkf8`VbB=1O|%hcI?jda
zV;k+`LgB0>TQfw*%xg4TCAk}wycg<C;jW}mI*Sz_g!XRC-~-OCu{Db@O*?8?8^Rj&
zS{^N1H6fiLjCAC#fRLNPkP|W*!URjjT!AiQtzvYZ{t%#iA(xXD1Xz-(u@oBGf2}Be
u*BbnAfuj*Re80yVxjo)NA1L&T?!2C$I@?4>V>|Ky0000<MNUMnLSTX*1bI&Y

literal 0
HcmV?d00001

diff --git a/components/browser_ui/site_settings/android/java/res/drawable-xhdpi/settings_autoplay.png b/components/browser_ui/site_settings/android/java/res/drawable-xhdpi/settings_autoplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..5a4128a5e02949de754f9cab2635824eda8c539c
GIT binary patch
literal 551
zcmV+?0@(eDP)<h;3K|Lk000e1NJLTq001xm001xu1ONa4{R=S+0005*Nkl<Zc-rk(
zy>fy;5RRo0wX?Hwh9Zw(#Vgp}9uO@kj!GT?W_XdLp-A4qiidDg@B~=L$xN`2Fo6Ry
zoC`9!!WnNX*>%6WZ+~v@;l6HTnG5Pb03nIUF_Q>F2&iK&{=v0ABR=d&Dwa&+>$CpO
zN8o1rO<Uv$u0HDF9##;Ow3|Q-tE-%+18~W?=HLW7u&HLKOxcVLm1<yTUrsfUGq~xX
zqx<cUyx0DE0A@`^cGeUaIn=iCwjFlbea(GBJf>jQOd%dgDu@oJ0JqvZU3NJ!T~_A+
zw>7k!d)Tk%U1PSM!@i8g3Qx?K@4o3Chv27xSRb|1lL*LZCn{;7NuQNv<q5!Ftw$V!
zc)av3R5$TCJ)+DZDSW^ao>676eW3vl6flwYSMx=l(G+1kL4+N%tlEhfAQy}(nDFWr
zbXw{Z4tCiO1OTTBcDW68nyP>kgahDIfn8VxO;uQ6Yd8Q-71auD*mMx(DnrEqaH<To
z&_)dhyat$p1K?CKh1bGGfX(<C05JbrZN`P>Q#wV`gM2wnZ5*JY22WGzg(js{SktOi
z^lWxu_H1_Y+jaYe^U~wOk$z>$zx3sgE%FC1e02PlFgl8cUvcTd1Q~vNjPEQT-<g7p
p?=l}ClAlmgAAvHTvG;Wo>j%AMEx!+_@2>y=002ovPDHLkV1fY;_gnw~

literal 0
HcmV?d00001

diff --git a/components/browser_ui/site_settings/android/java/res/drawable-xxhdpi/settings_autoplay.png b/components/browser_ui/site_settings/android/java/res/drawable-xxhdpi/settings_autoplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..7fceb8c2b546970a3720e8ab225799aa03895b7f
GIT binary patch
literal 792
zcmV+z1LypSP)<h;3K|Lk000e1NJLTq002k;002k`1ONa4|Kxkj0008tNkl<ZcmeHN
zv2Nl_5Kd(&P^2J2k<wEAFOV*wK{6%nd}~AH7AGB@E1m)cC{TL;PY?@4L47q{DkQ2)
zgu;oFPN%!E!Ny}lw9<LD9oFB@H#0js!$l#56r!s*CDlL=Bg|=u6>VsP6)iEx2tCzs
zN?!=Ys;Vvm+R!dxZSbnPR`u*)=$?G~q+QDONj}}54UDQIpq+dnupUkhrgMXd90~(9
z>D-*sHYV1z%eSyr=BeO3;m5&Ge2@<pO;xiip5YmGMb*%ROFljhg4(L5++aL|o)4Xt
z#%NjP*f=bsMdO23efEqzx#k+Py)EC-cdk<X`U-t|-#g6Ixz21IO!tgFux}-M*tcpx
z+bE=rR*I5^H|s7_BE7>~l(<Z;9NA<MwvEhAv<UAec5h`y4E^$WnI||NFX<&hz9~zC
z>oA;)6G#{m)`C=tNtmpB)?rp!gtK?*J1gwU@xCMXrLcRedOG_Aoa>~>!hiCJ<GzU?
zU4g;RFi3>{ojT&^9q|2A6eswfXXRwNew}jUlw`DpvbTS<8sy~{`pMeAwZ6%yL!Xy$
zN2*G=JTQ;lS${M|)Hzo?si<yxhaM+sazIk*Xq?iqof0qI(UJg?P=^+O4kR2zHF)`D
zl|_IA)LCU-!l_0)@}9u|IUq50<g;J&;sK4Ankxn*pe__Vqj<GBGo&d7B%n^2OnV;x
zfh7Y}69W=Zr)o@h8E>K0Up2cT1|*=)t}wk-{0CUjdxjX0fI83Mf&Ybo(3S(znzB<m
z^)SCv%fntq6%#ah*z2DdwY@s>U#@89zg#sfKk^r7!;A&m>sd-zwDXs+niu)Z|Ao(>
z;TfMn@`obY`5%hfKBYBiHdqh(w`25gSn1i))3E8OQ(Krf&Sz(7oX<QX`)FaR!DvC-
z;R|!`ZTxsjnS4B@Ou=|cg8`miBTkKmz^eW)jLCUb2{*+b2?DrQRj0pNXexyiQpitx
WnED%yq_MdG0000<MNUMnLSTZmtagO}

literal 0
HcmV?d00001

diff --git a/components/browser_ui/site_settings/android/java/res/drawable-xxxhdpi/settings_autoplay.png b/components/browser_ui/site_settings/android/java/res/drawable-xxxhdpi/settings_autoplay.png
new file mode 100644
index 0000000000000000000000000000000000000000..92a315bb00ac1f4dc675e894bf4af3ba7c68bf39
GIT binary patch
literal 1064
zcmV+@1lRkCP)<h;3K|Lk000e1NJLTq003YB003YJ1ONa4NRhv@000B;Nkl<Zc-rk-
zF-Rjp6x}q5UMCS0#3Pl(5mH&l%1Q;{uKI6w6G2RqfI_g2*e8Om;Gwl(ZGDB6<Z@mY
z41!h)DtJW--GhTGoY}a$GqZ^U^QZnZ|INPr^Z%bejuk6btXQ$4Pc|mmBCFCqouNZL
z+*6<WxThXEbVmEE$`&^!KcwMX<5*@*wCR=nknxH(Yhrn8{DYY8r>Mvd@I-#RfhTrA
zML#uC<7*jKp)UCfqsuC_%t(wck71K;$=5J$u~{A)viWQYSLEv(xME8~Gk$Frr{wD&
zI9;0^#@?^uf&63!9@uK4#y8Tm7iz{GPOt-V=gT=S+ekOkUbdWb=Rw%P3EhS2?={j1
znNJh=@$S+WRQC#g>V2o{6{t=Z?|z3LG~wtMZ-y=hF8Pd>n~yV_n@0=J13_GRGrG;6
z!}Wm09<l3XrRL0HmmUXf$+b79b@vCEkE8V|m6_M4a5NCYj5h8ElLt5Mf{yv!1>6J^
zi6*pop5R{>=jCZ_r}{L`gMViY9x2#y;<%R48&%;r*r_TXTLH$uVB1MRu#FdSHKn7?
z`-}(CeD>8zNbpUBfCq&DBPizKc3=Bf2#S%UBhDc1I|)nBzrdE{;{7Yp^VBj!$TQBx
zU|S+zz^3T;B^;-eQx(qzY{qtLVzw3S*uwXXPwGdTn6<_H_N*cX4be2o$8UU5g&+nP
ztP-!%(B(t6s4>q!uz#qm24H<k2=lrzDi~B0_J233?tcwcDq&ZkQ87A!4)}QA%f<zu
zN+mDL=L_s0dX?>oQ*Am<Tmb4+LW?hjMXctzD}w*YO8`)&lA9OoSdl_b7mgzXK%Gi_
z?u=G6wV#{`bvXd)RH8aJPdie9oUbr@1vvofRPqXZWjjJ~o-Oiq9zP`qK%Gi{imxNF
z#ZV>GxMfcqM;3rOm2koVsD>M`&n>zm4?vwt*x~f|!wop&79@E9>Qn-8+GpV^zc}AJ
zFAqSSO71+T*$FqG_g1BxlLw$qrE-qb>xHV|o^zsEc>wBE^0J)HeYgSrw<?XaJOFhn
zHPW0;|APTQNjCuVDP;an+!=-&MJXXSYW_iHekj4JNd|K$X%6Ph52wvfXhcC<e@cl`
zVkxC4tod=0da3dbmbI2u4)v8)uq;{FLQA%=g_7RFmf@vE<BPjPEU%+9qVl@=7aZzW
zOoyYnVlw}dPjsfExn`|pg0EQ(zvwo+)xh{>55wDS3~zX{EoY-``m=49hBUsaw;r=*
z+}2~(e82VBHh+(@{oX!+2n#ThdxByg0maD|^ghF~58(`dil|N~cLlAek3rFLSGLCO
ib6hJ{tXQ#P#rX?0El=KlH_u1_0000<MNUMnLSTX(y!wd%

literal 0
HcmV?d00001

diff --git a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
--- a/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
+++ b/components/browser_ui/site_settings/android/java/res/xml/site_settings_preferences.xml
@@ -67,6 +67,10 @@ found in the LICENSE file.
     <org.chromium.components.browser_ui.settings.ChromeBasePreference
         android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
         android:key="protected_content" />
+    <!-- Autoplay -->
+    <org.chromium.components.browser_ui.settings.ChromeBasePreference
+        android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
+        android:key="autoplay" />
     <!-- Sound -->
     <org.chromium.components.browser_ui.settings.ChromeBasePreference
         android:fragment="org.chromium.components.browser_ui.site_settings.SingleCategorySettings"
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/ContentSettingsResources.java
@@ -105,7 +105,10 @@ public class ContentSettingsResources {
                 return new ResourceItem(R.drawable.infobar_downloading,
                         R.string.automatic_downloads_permission_title, ContentSettingValues.ASK,
                         ContentSettingValues.BLOCK, R.string.website_settings_category_ask, 0);
-
+            case ContentSettingsType.AUTOPLAY:
+                return new ResourceItem(R.drawable.settings_autoplay, R.string.autoplay_title,
+                            ContentSettingValues.ALLOW, ContentSettingValues.BLOCK,
+                            R.string.website_settings_category_autoplay_allowed, 0);
             case ContentSettingsType.AUTO_DARK_WEB_CONTENT:
                 return new ResourceItem(R.drawable.ic_brightness_medium_24dp,
                         R.string.auto_dark_web_content_title, ContentSettingValues.ALLOW,
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -623,6 +623,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
         int resource = 0;
         if (mCategory.getType() == SiteSettingsCategory.Type.AUTOMATIC_DOWNLOADS) {
             resource = R.string.website_settings_add_site_description_automatic_downloads;
+        } else if (mCategory.getType() == SiteSettingsCategory.Type.AUTOPLAY) {
+            resource = R.string.website_settings_add_site_description_autoplay;
         } else if (mCategory.getType() == SiteSettingsCategory.Type.BACKGROUND_SYNC) {
             resource = R.string.website_settings_add_site_description_background_sync;
         } else if (mCategory.getType() == SiteSettingsCategory.Type.JAVASCRIPT) {
@@ -755,6 +757,8 @@ public class SingleCategorySettings extends SiteSettingsPreferenceFragment
         boolean allowSpecifyingExceptions = false;
         if (mCategory.getType() == SiteSettingsCategory.Type.SOUND) {
             allowSpecifyingExceptions = true;
+        } else if (mCategory.getType() == SiteSettingsCategory.Type.AUTOPLAY) {
+            allowSpecifyingExceptions = true;
         } else if (mCategory.getType() == SiteSettingsCategory.Type.JAVASCRIPT) {
             allowSpecifyingExceptions = true;
         } else if (mCategory.getType() == SiteSettingsCategory.Type.COOKIES) {
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -130,6 +130,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
                 return "cookies_permission_list";
             case ContentSettingsType.FEDERATED_IDENTITY_API:
                 return "federated_identity_api_list";
+            case ContentSettingsType.AUTOPLAY:
+                return "autoplay_permission_list";
             case ContentSettingsType.IDLE_DETECTION:
                 return "idle_detection_permission_list";
             case ContentSettingsType.JAVASCRIPT:
@@ -504,6 +506,8 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
 
             if (type == ContentSettingsType.ADS) {
                 setUpAdsPreference(preference);
+            } else if (type == ContentSettingsType.AUTOPLAY) {
+               setUpAutoplayPreference(preference);
             } else if (type == ContentSettingsType.SOUND) {
                 setUpSoundPreference(preference);
             } else if (type == ContentSettingsType.JAVASCRIPT) {
@@ -1020,6 +1024,24 @@ public class SingleWebsiteSettings extends SiteSettingsPreferenceFragment
         setupContentSettingsPreference(preference, currentValue, false /* isEmbargoed */);
     }
 
+    private void setUpAutoplayPreference(Preference preference) {
+        @ContentSettingValues
+        @Nullable
+        Integer currentValue = mSite.getContentSetting(
+            getSiteSettingsDelegate().getBrowserContextHandle(), ContentSettingsType.AUTOPLAY);
+        // In order to always show the autoplay permission, set it up with the default value if it
+        // doesn't have a current value.
+        if (currentValue == null) {
+            currentValue = WebsitePreferenceBridge.isCategoryEnabled(
+                                   getSiteSettingsDelegate().getBrowserContextHandle(),
+                                   ContentSettingsType.AUTOPLAY)
+                    ? ContentSettingValues.ALLOW
+                    : ContentSettingValues.BLOCK;
+        }
+        // Not possible to embargo AUTOPLAY.
+        setupContentSettingsPreference(preference, currentValue, false /* isEmbargoed */);
+    }
+
     private void setUpJavascriptPreference(Preference preference) {
         BrowserContextHandle browserContextHandle =
                 getSiteSettingsDelegate().getBrowserContextHandle();
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsCategory.java
@@ -43,7 +43,7 @@ public class SiteSettingsCategory {
             Type.JAVASCRIPT, Type.MICROPHONE, Type.NFC, Type.NOTIFICATIONS, Type.POPUPS,
             Type.PROTECTED_MEDIA, Type.SENSORS, Type.SOUND, Type.USB, Type.VIRTUAL_REALITY,
             Type.USE_STORAGE, Type.AUTO_DARK_WEB_CONTENT, Type.REQUEST_DESKTOP_SITE,
-            Type.FEDERATED_IDENTITY_API, Type.TIMEZONE_OVERRIDE})
+            Type.FEDERATED_IDENTITY_API, Type.TIMEZONE_OVERRIDE, Type.AUTOPLAY})
     @Retention(RetentionPolicy.SOURCE)
     public @interface Type {
         // All updates here must also be reflected in {@link #preferenceKey(int)
@@ -75,10 +75,11 @@ public class SiteSettingsCategory {
         int REQUEST_DESKTOP_SITE = 24;
         int FEDERATED_IDENTITY_API = 25;
         int TIMEZONE_OVERRIDE = 26;
+        int AUTOPLAY = 27;
         /**
          * Number of handled categories used for calculating array sizes.
          */
-        int NUM_ENTRIES = 27;
+        int NUM_ENTRIES = 28;
     }
 
     private final BrowserContextHandle mBrowserContextHandle;
@@ -191,6 +192,8 @@ public class SiteSettingsCategory {
                 return ContentSettingsType.NFC;
             case Type.NOTIFICATIONS:
                 return ContentSettingsType.NOTIFICATIONS;
+            case Type.AUTOPLAY:
+                return ContentSettingsType.AUTOPLAY;
             case Type.POPUPS:
                 return ContentSettingsType.POPUPS;
             case Type.PROTECTED_MEDIA:
@@ -271,6 +274,8 @@ public class SiteSettingsCategory {
                 return "nfc";
             case Type.NOTIFICATIONS:
                 return "notifications";
+            case Type.AUTOPLAY:
+                return "autoplay";
             case Type.POPUPS:
                 return "popups";
             case Type.PROTECTED_MEDIA:
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/Website.java
@@ -230,6 +230,15 @@ public final class Website implements WebsiteEntry {
             } else {
                 RecordUserAction.record("JavascriptContentSetting.DisableBy.SiteSettings");
             }
+        } else if (type == ContentSettingsType.AUTOPLAY) {
+            // It is possible to set the permission without having an existing exception,
+            // because we always show the autoplay permission in Site Settings.
+            if (exception == null) {
+                exception = new ContentSettingException(
+                        ContentSettingsType.AUTOPLAY, getAddress().getHost(), value, "",
+                        /*isEmbargoed=*/false);
+                setContentSettingException(type, exception);
+            }
         } else if (type == ContentSettingsType.SOUND) {
             // It is possible to set the permission without having an existing exception,
             // because we always show the sound permission in Site Settings.
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePermissionsFetcher.java
@@ -64,6 +64,7 @@ public class WebsitePermissionsFetcher {
             case ContentSettingsType.AUTOMATIC_DOWNLOADS:
             case ContentSettingsType.BACKGROUND_SYNC:
             case ContentSettingsType.BLUETOOTH_SCANNING:
+            case ContentSettingsType.AUTOPLAY:
             case ContentSettingsType.COOKIES:
             case ContentSettingsType.FEDERATED_IDENTITY_API:
             case ContentSettingsType.JAVASCRIPT:
diff --git a/components/browser_ui/site_settings/android/website_preference_bridge.cc b/components/browser_ui/site_settings/android/website_preference_bridge.cc
--- a/components/browser_ui/site_settings/android/website_preference_bridge.cc
+++ b/components/browser_ui/site_settings/android/website_preference_bridge.cc
@@ -825,6 +825,7 @@ static void JNI_WebsitePreferenceBridge_SetContentSettingEnabled(
       case ContentSettingsType::REQUEST_DESKTOP_SITE:
       case ContentSettingsType::SENSORS:
       case ContentSettingsType::SOUND:
+      case ContentSettingsType::AUTOPLAY:
         value = CONTENT_SETTING_ALLOW;
         break;
       default:
diff --git a/components/browser_ui/strings/android/site_settings.grdp b/components/browser_ui/strings/android/site_settings.grdp
--- a/components/browser_ui/strings/android/site_settings.grdp
+++ b/components/browser_ui/strings/android/site_settings.grdp
@@ -12,6 +12,15 @@
   <message name="IDS_ADS_PERMISSION_TITLE" desc="Title for the ads permission [CHAR_LIMIT=32]">
     Ads
   </message>
+  <message name="IDS_AUTOPLAY_TITLE" desc='Title for the Autoplay settings screen [CHAR-LIMIT=32]'>
+    Autoplay
+  </message>
+  <message name="IDS_WEBSITE_SETTINGS_ADD_SITE_DESCRIPTION_AUTOPLAY" desc="The description for the allow autoplay of muted videos for website dialog.">
+    Allow autoplay of muted videos for a specific site.
+  </message>
+  <message name="IDS_WEBSITE_SETTINGS_CATEGORY_AUTOPLAY_ALLOWED" desc="Summary text explaining that sites are allowed to automatically play muted videos and that it is the recommended setting.">
+    Allow sites to automatically play muted videos (recommended)
+  </message>
   <message name="IDS_AR_PERMISSION_TITLE" desc="Title of the permission to use Augmented Reality [CHAR_LIMIT=32]">
     Augmented reality
   </message>
diff --git a/components/content_settings/core/browser/content_settings_registry.cc b/components/content_settings/core/browser/content_settings_registry.cc
--- a/components/content_settings/core/browser/content_settings_registry.cc
+++ b/components/content_settings/core/browser/content_settings_registry.cc
@@ -318,7 +318,7 @@ void ContentSettingsRegistry::Init() {
            ContentSettingsInfo::PERSISTENT,
            ContentSettingsInfo::EXCEPTIONS_ON_SECURE_ORIGINS_ONLY);
 
-  Register(ContentSettingsType::AUTOPLAY, "autoplay", CONTENT_SETTING_ALLOW,
+  Register(ContentSettingsType::AUTOPLAY, "autoplay", CONTENT_SETTING_BLOCK,
            WebsiteSettingsInfo::UNSYNCABLE, AllowlistedSchemes(),
            ValidSettings(CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK),
            WebsiteSettingsInfo::TOP_ORIGIN_ONLY_SCOPE,
diff --git a/components/content_settings/core/browser/content_settings_utils.cc b/components/content_settings/core/browser/content_settings_utils.cc
--- a/components/content_settings/core/browser/content_settings_utils.cc
+++ b/components/content_settings/core/browser/content_settings_utils.cc
@@ -149,6 +149,8 @@ void GetRendererContentSettingRules(const HostContentSettingsMap* map,
 #endif
   map->GetSettingsForOneType(ContentSettingsType::JAVASCRIPT,
                              &(rules->script_rules));
+  map->GetSettingsForOneType(ContentSettingsType::AUTOPLAY,
+                             &(rules->autoplay_rules));
   map->GetSettingsForOneType(ContentSettingsType::POPUPS,
                              &(rules->popup_redirect_rules));
 
diff --git a/components/content_settings/core/common/content_settings.cc b/components/content_settings/core/common/content_settings.cc
--- a/components/content_settings/core/common/content_settings.cc
+++ b/components/content_settings/core/common/content_settings.cc
@@ -203,6 +203,7 @@ bool RendererContentSettingRules::IsRendererContentSetting(
   return content_type == ContentSettingsType::IMAGES ||
          content_type == ContentSettingsType::JAVASCRIPT ||
          content_type == ContentSettingsType::POPUPS ||
+         content_type == ContentSettingsType::AUTOPLAY ||
          content_type == ContentSettingsType::MIXEDSCRIPT ||
          content_type == ContentSettingsType::AUTO_DARK_WEB_CONTENT ||
          content_type == ContentSettingsType::TIMEZONE_OVERRIDE;
@@ -216,6 +217,7 @@ void RendererContentSettingRules::FilterRulesByOutermostMainFrameURL(
   FilterRulesForType(mixed_content_rules, outermost_main_frame_url);
   FilterRulesForType(auto_dark_content_rules, outermost_main_frame_url);
   FilterRulesForType(timezone_override_rules, outermost_main_frame_url);
+  FilterRulesForType(autoplay_rules, outermost_main_frame_url);
 }
 
 RendererContentSettingRules::RendererContentSettingRules() = default;
diff --git a/components/content_settings/core/common/content_settings.h b/components/content_settings/core/common/content_settings.h
--- a/components/content_settings/core/common/content_settings.h
+++ b/components/content_settings/core/common/content_settings.h
@@ -90,6 +90,7 @@ struct RendererContentSettingRules {
 
   ContentSettingsForOneType image_rules;
   ContentSettingsForOneType script_rules;
+  ContentSettingsForOneType autoplay_rules;
   ContentSettingsForOneType popup_redirect_rules;
   ContentSettingsForOneType mixed_content_rules;
   ContentSettingsForOneType auto_dark_content_rules;
diff --git a/components/content_settings/core/common/content_settings.mojom b/components/content_settings/core/common/content_settings.mojom
--- a/components/content_settings/core/common/content_settings.mojom
+++ b/components/content_settings/core/common/content_settings.mojom
@@ -75,6 +75,7 @@ struct ContentSettingPatternSource {
 struct RendererContentSettingRules {
   array<ContentSettingPatternSource> image_rules;
   array<ContentSettingPatternSource> script_rules;
+  array<ContentSettingPatternSource> autoplay_rules;
   array<ContentSettingPatternSource> popup_redirect_rules;
   array<ContentSettingPatternSource> mixed_content_rules;
   array<ContentSettingPatternSource> auto_dark_content_rules;
diff --git a/components/content_settings/core/common/content_settings_mojom_traits.cc b/components/content_settings/core/common/content_settings_mojom_traits.cc
--- a/components/content_settings/core/common/content_settings_mojom_traits.cc
+++ b/components/content_settings/core/common/content_settings_mojom_traits.cc
@@ -100,6 +100,7 @@ bool StructTraits<content_settings::mojom::RendererContentSettingRulesDataView,
          RendererContentSettingRules* out) {
   return data.ReadImageRules(&out->image_rules) &&
          data.ReadScriptRules(&out->script_rules) &&
+         data.ReadAutoplayRules(&out->autoplay_rules) &&
          data.ReadPopupRedirectRules(&out->popup_redirect_rules) &&
          data.ReadMixedContentRules(&out->mixed_content_rules) &&
          data.ReadAutoDarkContentRules(&out->auto_dark_content_rules) &&
diff --git a/components/content_settings/core/common/content_settings_mojom_traits.h b/components/content_settings/core/common/content_settings_mojom_traits.h
--- a/components/content_settings/core/common/content_settings_mojom_traits.h
+++ b/components/content_settings/core/common/content_settings_mojom_traits.h
@@ -135,6 +135,11 @@ struct StructTraits<
     return r.script_rules;
   }
 
+  static const std::vector<ContentSettingPatternSource>& autoplay_rules(
+      const RendererContentSettingRules& r) {
+    return r.autoplay_rules;
+  }
+
   static const std::vector<ContentSettingPatternSource>& popup_redirect_rules(
       const RendererContentSettingRules& r) {
     return r.popup_redirect_rules;
diff --git a/components/content_settings/renderer/content_settings_agent_impl.cc b/components/content_settings/renderer/content_settings_agent_impl.cc
--- a/components/content_settings/renderer/content_settings_agent_impl.cc
+++ b/components/content_settings/renderer/content_settings_agent_impl.cc
@@ -396,6 +396,17 @@ bool ContentSettingsAgentImpl::AllowRunningInsecureContent(
   return false;
 }
 
+bool ContentSettingsAgentImpl::AllowAutoplay(bool default_value) {
+  if (!content_setting_rules_)
+    return default_value;
+
+  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
+  return GetContentSettingFromRules(
+             content_setting_rules_->autoplay_rules,
+             url::Origin(frame->GetDocument().GetSecurityOrigin()).GetURL()) ==
+         CONTENT_SETTING_ALLOW;
+}
+
 bool ContentSettingsAgentImpl::AllowPopupsAndRedirects(bool default_value) {
   if (!content_setting_rules_)
     return default_value;
diff --git a/components/content_settings/renderer/content_settings_agent_impl.h b/components/content_settings/renderer/content_settings_agent_impl.h
--- a/components/content_settings/renderer/content_settings_agent_impl.h
+++ b/components/content_settings/renderer/content_settings_agent_impl.h
@@ -96,6 +96,7 @@ class ContentSettingsAgentImpl
   void DidNotAllowScript() override;
   bool AllowRunningInsecureContent(bool allowed_per_settings,
                                    const blink::WebURL& url) override;
+  bool AllowAutoplay(bool default_value) override;
   bool AllowPopupsAndRedirects(bool default_value) override;
   bool ShouldAutoupgradeMixedContent() override;
 
diff --git a/components/page_info/android/page_info_controller_android.cc b/components/page_info/android/page_info_controller_android.cc
--- a/components/page_info/android/page_info_controller_android.cc
+++ b/components/page_info/android/page_info_controller_android.cc
@@ -145,6 +145,7 @@ void PageInfoControllerAndroid::SetPermissionInfo(
   permissions_to_display.push_back(ContentSettingsType::ADS);
   permissions_to_display.push_back(
       ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER);
+  permissions_to_display.push_back(ContentSettingsType::AUTOPLAY);
   permissions_to_display.push_back(ContentSettingsType::SOUND);
   if (base::FeatureList::IsEnabled(features::kWebNfc))
     permissions_to_display.push_back(ContentSettingsType::NFC);
diff --git a/components/page_info/page_info.cc b/components/page_info/page_info.cc
--- a/components/page_info/page_info.cc
+++ b/components/page_info/page_info.cc
@@ -102,6 +102,7 @@ ContentSettingsType kPermissionType[] = {
     ContentSettingsType::ADS,
     ContentSettingsType::BACKGROUND_SYNC,
     ContentSettingsType::SOUND,
+    ContentSettingsType::AUTOPLAY,
     ContentSettingsType::AUTOMATIC_DOWNLOADS,
 #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
     ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER,
@@ -145,6 +146,11 @@ bool ShouldShowPermission(const PageInfo::PermissionInfo& info,
     return is_subresource_filter_activated;
   }
 
+  // Always show autoplay when it has a site-specific override
+  if (info.type == ContentSettingsType::AUTOPLAY) {
+     return true;
+  }
+
   if (info.type == ContentSettingsType::SOUND) {
     // The sound content setting should always show up when the tab has played
     // audio.
diff --git a/components/page_info/page_info_ui.cc b/components/page_info/page_info_ui.cc
--- a/components/page_info/page_info_ui.cc
+++ b/components/page_info/page_info_ui.cc
@@ -161,6 +161,7 @@ base::span<const PageInfoUI::PermissionUIInfo> GetContentSettingsUIInfo() {
 #endif
     {ContentSettingsType::ADS, IDS_SITE_SETTINGS_TYPE_ADS,
      IDS_SITE_SETTINGS_TYPE_ADS_MID_SENTENCE},
+    {ContentSettingsType::AUTOPLAY, IDS_SITE_SETTINGS_TYPE_AUTOPLAY},
     {ContentSettingsType::SOUND, IDS_SITE_SETTINGS_TYPE_SOUND,
      IDS_SITE_SETTINGS_TYPE_SOUND_MID_SENTENCE},
     {ContentSettingsType::CLIPBOARD_READ_WRITE,
diff --git a/components/site_settings_strings.grdp b/components/site_settings_strings.grdp
--- a/components/site_settings_strings.grdp
+++ b/components/site_settings_strings.grdp
@@ -136,6 +136,9 @@
   <message name="IDS_SITE_SETTINGS_TYPE_SOUND" desc="The label used for the sound site settings controls.">
     Sound
   </message>
+  <message name="IDS_SITE_SETTINGS_TYPE_AUTOPLAY" desc="The label used for the autoplay permission controls in the Page Info popup.">
+    Autoplay
+  </message>
   <message name="IDS_SITE_SETTINGS_TYPE_SOUND_MID_SENTENCE" desc="The label used for the sound site settings controls when used mid-sentence.">
     sound
   </message>
diff --git a/third_party/blink/public/platform/web_content_settings_client.h b/third_party/blink/public/platform/web_content_settings_client.h
--- a/third_party/blink/public/platform/web_content_settings_client.h
+++ b/third_party/blink/public/platform/web_content_settings_client.h
@@ -92,6 +92,9 @@ class WebContentSettingsClient {
   // interface.
   virtual bool AllowMutationEvents(bool default_value) { return default_value; }
 
+  // Controls whether autoplay is allowed for this frame.
+  virtual bool AllowAutoplay(bool default_value) { return default_value; }
+
   virtual bool AllowPopupsAndRedirects(bool default_value) {
     return default_value;
   }
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom-blink.h"
 #include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h"
 #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom-blink.h"
+#include "third_party/blink/public/platform/web_content_settings_client.h"
 #include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/public/web/web_local_frame.h"
 #include "third_party/blink/public/web/web_local_frame_client.h"
@@ -310,6 +311,8 @@ void AutoplayPolicy::TryUnlockingUserGesture() {
 }
 
 bool AutoplayPolicy::IsGestureNeededForPlayback() const {
+  if (!IsAutoplayAllowedPerSettings())
+    return true;
   if (!IsLockedPendingUserGesture())
     return false;
 
@@ -408,6 +411,15 @@ void AutoplayPolicy::MaybeSetAutoplayInitiated() {
   }
 }
 
+bool AutoplayPolicy::IsAutoplayAllowedPerSettings() const {
+  LocalFrame* frame = element_->GetDocument().GetFrame();
+  if (!frame)
+    return false;
+  if (auto* settings_client = frame->GetContentSettingsClient())
+    return settings_client->AllowAutoplay(false /* default_value */);
+  return true;
+}
+
 bool AutoplayPolicy::ShouldAutoplay() {
   if (!element_->GetExecutionContext() ||
       element_->GetExecutionContext()->IsSandboxed(
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.h b/third_party/blink/renderer/core/html/media/autoplay_policy.h
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.h
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.h
@@ -133,6 +133,10 @@ class CORE_EXPORT AutoplayPolicy final
   // should use, if checking to see if an action is allowed.
   bool IsLockedPendingUserGesture() const;
 
+  // Return true if and only if the settings allow autoplay of media on this
+  // frame.
+  bool IsAutoplayAllowedPerSettings() const;
+
   bool IsAutoplayingMutedInternal(bool muted) const;
   bool IsOrWillBeAutoplayingMutedInternal(bool muted) const;
 
--
2.25.1
