[OOPIF PDF] Create enterprise policy PdfViewerOutOfProcessIframeEnabled

Introduce an enterprise policy that can enable or disable OOPIF PDF.
Note that OOPIF PDF viewer is only enabled when the policy is enabled
and the kPdfOopif feature flag is enabled, otherwise the existing
GuestView PDF viewer will be used.

The policy does not support dynamic_refresh. If it was supported, then
the browser would be able to have instances of GuestView PDF and OOPIF
PDF simultaneously, which could lead to unexpected behavior. They
aren't meant to run at the same time.

If the policy hasn't been set, then by default, the policy will be
enabled. Otherwise, embedders would crash if they didn't set the policy.

Bug: 324637002
Change-Id: I0e0216d1bd5dbdc14f4dd6e3461aa4dc72360c55
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5450113
Reviewed-by: Owen Min <[email protected]>
Reviewed-by: Lei Zhang <[email protected]>
Commit-Queue: Andy Phan <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1290238}
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index ffa723a8e4..c5e9088 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -190,6 +190,7 @@
 #include "net/cookies/cookie_monster.h"
 #include "net/http/http_network_layer.h"
 #include "net/http/http_stream_factory.h"
+#include "pdf/buildflags.h"
 #include "ppapi/buildflags/buildflags.h"
 #include "printing/buildflags/buildflags.h"
 #include "rlz/buildflags/buildflags.h"
@@ -329,6 +330,11 @@
 #include "chrome/browser/printing/printing_init.h"
 #endif
 
+#if BUILDFLAG(ENABLE_PDF)
+#include "chrome/browser/pdf/pdf_pref_names.h"
+#include "pdf/pdf_features.h"
+#endif  // BUILDFLAG(ENABLE_PDF)
+
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/browser/plugins/plugin_prefs.h"
 #endif
@@ -1701,6 +1707,12 @@
   browser_process_->intranet_redirect_detector();
 #endif
 
+#if BUILDFLAG(ENABLE_PDF)
+  chrome_pdf::features::SetIsOopifPdfPolicyEnabled(
+      g_browser_process->local_state()->GetBoolean(
+          prefs::kPdfViewerOutOfProcessIframeEnabled));
+#endif  // BUILDFLAG(ENABLE_PDF)
+
 #if BUILDFLAG(ENABLE_PRINT_PREVIEW) && !defined(OFFICIAL_BUILD)
   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDebugPrint)) {
diff --git a/chrome/browser/pdf/pdf_pref_names.cc b/chrome/browser/pdf/pdf_pref_names.cc
index 6997fb9e..4c0e8b7 100644
--- a/chrome/browser/pdf/pdf_pref_names.cc
+++ b/chrome/browser/pdf/pdf_pref_names.cc
@@ -6,11 +6,15 @@
 
 namespace prefs {
 
-// A list of domains that have access to file:// URLs in PDF Viewer.
+// A list of domains that have access to file:// URLs in the PDF viewer.
 const char kPdfLocalFileAccessAllowedForDomains[] =
     "pdf_local_file_access_allowed_for_domains";
 
-// Boolean pref to control whether to use Skia renderer in the PDF viewer
+// Boolean pref to control whether to use Skia renderer in the PDF viewer.
 const char kPdfUseSkiaRendererEnabled[] = "pdf.enable_skia";
 
+// Boolean pref to control whether to use the OOPIF PDF viewer.
+const char kPdfViewerOutOfProcessIframeEnabled[] =
+    "pdf.enable_out_of_process_iframe_viewer";
+
 }  // namespace prefs
diff --git a/chrome/browser/pdf/pdf_pref_names.h b/chrome/browser/pdf/pdf_pref_names.h
index bc64f89..df28b10 100644
--- a/chrome/browser/pdf/pdf_pref_names.h
+++ b/chrome/browser/pdf/pdf_pref_names.h
@@ -9,6 +9,7 @@
 
 extern const char kPdfLocalFileAccessAllowedForDomains[];
 extern const char kPdfUseSkiaRendererEnabled[];
+extern const char kPdfViewerOutOfProcessIframeEnabled[];
 
 }  // namespace prefs
 
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index c374877..0231d07 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -661,6 +661,9 @@
   { key::kPdfUseSkiaRendererEnabled,
     prefs::kPdfUseSkiaRendererEnabled,
     base::Value::Type::BOOLEAN },
+  { key::kPdfViewerOutOfProcessIframeEnabled,
+    prefs::kPdfViewerOutOfProcessIframeEnabled,
+    base::Value::Type::BOOLEAN },
 #endif  // BUILDFLAG(ENABLE_PDF)
   { key::kPolicyRefreshRate,
     policy_prefs::kUserPolicyRefreshRate,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index f9c4452..1e6aed1 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -1789,6 +1789,11 @@
   registry->RegisterBooleanPref(prefs::kOopPrintDriversAllowedByPolicy, true);
 #endif
 
+#if BUILDFLAG(ENABLE_PDF)
+  registry->RegisterBooleanPref(prefs::kPdfViewerOutOfProcessIframeEnabled,
+                                true);
+#endif  // BUILDFLAG(ENABLE_PDF)
+
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
   registry->RegisterBooleanPref(prefs::kChromeForTestingAllowed, true);
 #endif
diff --git a/components/policy/resources/templates/policies.yaml b/components/policy/resources/templates/policies.yaml
index 6ae9536..889dd50 100644
--- a/components/policy/resources/templates/policies.yaml
+++ b/components/policy/resources/templates/policies.yaml
@@ -1254,6 +1254,7 @@
   1253: ChromeDataRegionSetting
   1254: ContextualGoogleIntegrationsEnabled
   1255: ContextualGoogleIntegrationsConfiguration
+  1256: PdfViewerOutOfProcessIframeEnabled
 atomic_groups:
   1: Homepage
   2: RemoteAccess
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/PdfViewerOutOfProcessIframeEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/PdfViewerOutOfProcessIframeEnabled.yaml
new file mode 100644
index 0000000..d463b77
--- /dev/null
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/PdfViewerOutOfProcessIframeEnabled.yaml
@@ -0,0 +1,30 @@
+caption: Use out-of-process iframe PDF Viewer
+default: true
+desc: |-
+  Controls whether the PDF viewer in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> uses an out-of-process iframe (OOPIF). This will be the new PDF viewer architecture in the future, as it is simpler and makes adding new features easier. The existing GuestView PDF viewer is an outdated, complex architecture that is being deprecated.
+
+  When this policy is set to Enabled or not set, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will be able to use the OOPIF PDF viewer architecture. Once Enabled or not set, the default behavior will be decided by <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.
+
+  When this policy is set to Disabled, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> will strictly use the existing GuestView PDF viewer. It embeds a web page with a separate frame tree into another web page.
+
+  This policy will be removed in the future, after the OOPIF PDF viewer feature has fully rolled out.
+example_value: true
+features:
+  dynamic_refresh: false
+  per_profile: true
+future_on:
+- chrome_os
+items:
+- caption: PDF viewer uses the OOPIF architecture.
+  value: true
+- caption: PDF viewer uses the GuestView architecture.
+  value: false
+owners:
+- [email protected]
+- file://pdf/OWNERS
+schema:
+  type: boolean
+supported_on:
+- chrome.*:126-
+tags: []
+type: main
\ No newline at end of file
diff --git a/components/policy/test/data/pref_mapping/PdfViewerOutOfProcessIframeEnabled.json b/components/policy/test/data/pref_mapping/PdfViewerOutOfProcessIframeEnabled.json
new file mode 100644
index 0000000..69c7139
--- /dev/null
+++ b/components/policy/test/data/pref_mapping/PdfViewerOutOfProcessIframeEnabled.json
@@ -0,0 +1,20 @@
+[
+  {
+    "os": [
+      "chromeos_ash",
+      "chromeos_lacros",
+      "linux",
+      "mac",
+      "win"
+    ],
+    "simple_policy_pref_mapping_test": {
+      "pref_name": "pdf.enable_out_of_process_iframe_viewer",
+      "pref_location": "local_state",
+      "default_value": true,
+      "values_to_test": [
+        true,
+        false
+      ]
+    }
+  }
+]
diff --git a/pdf/pdf_features.cc b/pdf/pdf_features.cc
index c211833..d821b57 100644
--- a/pdf/pdf_features.cc
+++ b/pdf/pdf_features.cc
@@ -9,6 +9,10 @@
 
 namespace chrome_pdf::features {
 
+namespace {
+bool g_is_oopif_pdf_policy_enabled = true;
+}  // namespace
+
 BASE_FEATURE(kAccessiblePDFForm,
              "AccessiblePDFForm",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -42,8 +46,13 @@
 BASE_FEATURE(kPdfInk2, "PdfInk2", base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
+void SetIsOopifPdfPolicyEnabled(bool is_oopif_pdf_policy_enabled) {
+  g_is_oopif_pdf_policy_enabled = is_oopif_pdf_policy_enabled;
+}
+
 bool IsOopifPdfEnabled() {
-  return base::FeatureList::IsEnabled(kPdfOopif);
+  return g_is_oopif_pdf_policy_enabled &&
+         base::FeatureList::IsEnabled(kPdfOopif);
 }
 
 }  // namespace chrome_pdf::features
diff --git a/pdf/pdf_features.h b/pdf/pdf_features.h
index 594084d..75eed09 100644
--- a/pdf/pdf_features.h
+++ b/pdf/pdf_features.h
@@ -27,6 +27,10 @@
 BASE_DECLARE_FEATURE(kPdfInk2);
 #endif
 
+// Sets whether the OOPIF PDF policy enables the OOPIF PDF viewer. Otherwise,
+// GuestView PDF viewer will be used. The policy is enabled by default.
+void SetIsOopifPdfPolicyEnabled(bool is_oopif_pdf_policy_enabled);
+
 // Returns whether the OOPIF PDF viewer should be used, otherwise the GuestView
 // PDF viewer should be used.
 bool IsOopifPdfEnabled();
diff --git a/tools/metrics/histograms/metadata/enterprise/enums.xml b/tools/metrics/histograms/metadata/enterprise/enums.xml
index 4b2ee8f..09c9489 100644
--- a/tools/metrics/histograms/metadata/enterprise/enums.xml
+++ b/tools/metrics/histograms/metadata/enterprise/enums.xml
@@ -2132,6 +2132,7 @@
   <int value="1253" label="ChromeDataRegionSetting"/>
   <int value="1254" label="ContextualGoogleIntegrationsEnabled"/>
   <int value="1255" label="ContextualGoogleIntegrationsConfiguration"/>
+  <int value="1256" label="PdfViewerOutOfProcessIframeEnabled"/>
 </enum>
 
 <enum name="EnterprisePoliciesSources">