[Lens] Add a policy to control Lens camera assisted search for enterprise

- the flag is enabled by default


Change-Id: Iad4f604460b15526b6bc5df66de9dd09c87e20f9
Bug: 1099982
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2749539
Commit-Queue: Yu Su <[email protected]>
Reviewed-by: Owen Min <[email protected]>
Reviewed-by: Wenyu Fu <[email protected]>
Reviewed-by: Ben Goldberger <[email protected]>
Reviewed-by: Brandon Wylie <[email protected]>
Reviewed-by: Filip Gorski <[email protected]>
Cr-Commit-Position: refs/heads/master@{#872710}
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 716557d..9374d22 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -875,8 +875,8 @@
     "//chrome/browser/image_editor/public:java",
     "//chrome/browser/image_fetcher:java",
     "//chrome/browser/incognito/interstitial/android:junit",
-    "//chrome/browser/lens:java",
     "//chrome/browser/lens:delegate_public_impl_java",
+    "//chrome/browser/lens:java",
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/optimization_guide/android:java",
     "//chrome/browser/page_annotations/test/android:junit",
@@ -3479,6 +3479,7 @@
     "java/src/org/chromium/chrome/browser/init/NativeStartupBridge.java",
     "java/src/org/chromium/chrome/browser/instantapps/InstantAppsSettings.java",
     "java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java",
+    "java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java",
     "java/src/org/chromium/chrome/browser/locale/LocaleManager.java",
     "java/src/org/chromium/chrome/browser/locale/LocaleTemplateUrlLoader.java",
     "java/src/org/chromium/chrome/browser/login/ChromeHttpAuthHandler.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 8cc73a7c..eb45de4 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -731,6 +731,7 @@
   "java/src/org/chromium/chrome/browser/invalidation/SessionsInvalidationManager.java",
   "java/src/org/chromium/chrome/browser/javascript/WebContextFetcher.java",
   "java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java",
+  "java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java",
   "java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java",
   "java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java",
   "java/src/org/chromium/chrome/browser/locale/LocaleChangedBroadcastReceiver.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java
new file mode 100644
index 0000000..875ad92
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/lens/LensPolicyUtils.java
@@ -0,0 +1,33 @@
+// Copyright 2021 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.
+
+package org.chromium.chrome.browser.lens;
+
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.components.policy.PolicyCache;
+
+/**
+ * Provides Lens policy utility functions.
+ */
+public class LensPolicyUtils {
+    private static final String LENS_CAMERA_ASSISTED_SEARCH_ENABLED_POLICY_NAME =
+            "policy.lens_camera_assisted_search_enabled";
+    /**
+     * @return Whether the Lens camera assisted search should be enabled for the enterprise user.
+     */
+    public static boolean getLensCameraAssistedSearchEnabledForEnterprise() {
+        // Read from policy cache before the native library is ready.
+        if (PolicyCache.get().isReadable()) {
+            return Boolean.FALSE.equals(PolicyCache.get().getBooleanValue(
+                    LENS_CAMERA_ASSISTED_SEARCH_ENABLED_POLICY_NAME));
+        }
+
+        return LensPolicyUtilsJni.get().getLensCameraAssistedSearchEnabled();
+    }
+
+    @NativeMethods
+    public interface Natives {
+        boolean getLensCameraAssistedSearchEnabled();
+    }
+}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d06dde8..efa2f99 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2998,6 +2998,9 @@
       "installable/installed_webapp_provider.cc",
       "installable/installed_webapp_provider.h",
       "installable/quality_enforcer.cc",
+      "lens/android/lens_policy_utils.cc",
+      "lens/android/lens_prefs.cc",
+      "lens/android/lens_prefs.h",
       "lifetime/application_lifetime_android.cc",
       "lifetime/application_lifetime_android.h",
       "long_screenshots/long_screenshots_tab_service_factory.cc",
diff --git a/chrome/browser/lens/android/lens_policy_utils.cc b/chrome/browser/lens/android/lens_policy_utils.cc
new file mode 100644
index 0000000..faf09332
--- /dev/null
+++ b/chrome/browser/lens/android/lens_policy_utils.cc
@@ -0,0 +1,17 @@
+// Copyright 2021 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 <jni.h>
+
+#include "chrome/android/chrome_jni_headers/LensPolicyUtils_jni.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/lens/android/lens_prefs.h"
+#include "components/policy/core/common/policy_pref_names.h"
+#include "components/prefs/pref_service.h"
+
+static jboolean JNI_LensPolicyUtils_GetLensCameraAssistedSearchEnabled(
+    JNIEnv* env) {
+  return g_browser_process->local_state()->GetBoolean(
+      lens::kLensCameraAssistedSearchEnabled);
+}
diff --git a/chrome/browser/lens/android/lens_prefs.cc b/chrome/browser/lens/android/lens_prefs.cc
new file mode 100644
index 0000000..dad93fd
--- /dev/null
+++ b/chrome/browser/lens/android/lens_prefs.cc
@@ -0,0 +1,13 @@
+// Copyright 2021 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/browser/lens/android/lens_prefs.h"
+
+namespace lens {
+
+// Whether the Lens camera assisted search is enabled.
+const char kLensCameraAssistedSearchEnabled[] =
+    "policy.lens_camera_assisted_search_enabled";
+
+}  // namespace lens
diff --git a/chrome/browser/lens/android/lens_prefs.h b/chrome/browser/lens/android/lens_prefs.h
new file mode 100644
index 0000000..6581de18
--- /dev/null
+++ b/chrome/browser/lens/android/lens_prefs.h
@@ -0,0 +1,14 @@
+// Copyright 2021 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_BROWSER_LENS_ANDROID_LENS_PREFS_H_
+#define CHROME_BROWSER_LENS_ANDROID_LENS_PREFS_H_
+
+namespace lens {
+
+extern const char kLensCameraAssistedSearchEnabled[];
+
+}  // namespace lens
+
+#endif  // CHROME_BROWSER_LENS_ANDROID_LENS_PREFS_H_
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensUma.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensUma.java
index 8b551fa..cceddf5 100644
--- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensUma.java
+++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensUma.java
@@ -24,7 +24,7 @@
             LensSupportStatus.LENS_SHOP_AND_SEARCH_SUPPORTED,
             LensSupportStatus.CAMERA_NOT_AVAILABLE, LensSupportStatus.DISABLED_ON_LOW_END_DEVICE,
             LensSupportStatus.AGSA_VERSION_NOT_SUPPORTED, LensSupportStatus.DISABLED_ON_INCOGNITO,
-            LensSupportStatus.DISABLED_ON_TABLET})
+            LensSupportStatus.DISABLED_ON_TABLET, LensSupportStatus.DISABLED_FOR_ENTERPRISE_USER})
     @Retention(RetentionPolicy.SOURCE)
     public static @interface LensSupportStatus {
         int LENS_SEARCH_SUPPORTED = 0;
@@ -41,7 +41,8 @@
         int AGSA_VERSION_NOT_SUPPORTED = 11;
         int DISABLED_ON_INCOGNITO = 12;
         int DISABLED_ON_TABLET = 13;
-        int NUM_ENTRIES = 14;
+        int DISABLED_FOR_ENTERPRISE_USER = 14;
+        int NUM_ENTRIES = 15;
     }
 
     public static void recordLensSupportStatus(
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index ec7e0662..b7f92ac 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -102,6 +102,7 @@
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/first_run/android/first_run_prefs.h"
+#include "chrome/browser/lens/android/lens_prefs.h"
 #include "chrome/browser/search/contextual_search_policy_handler_android.h"
 #else  // defined(OS_ANDROID)
 #include "chrome/browser/download/default_download_dir_policy_handler.h"
@@ -662,6 +663,15 @@
   { key::kBackForwardCacheEnabled,
     prefs::kMixedFormsWarningsEnabled,
     base::Value::Type::BOOLEAN },
+  { key::kTosDialogBehavior,
+    first_run::kTosDialogBehavior,
+    base::Value::Type::INTEGER },
+  { key::kLensCameraAssistedSearchEnabled,
+    lens::kLensCameraAssistedSearchEnabled,
+    base::Value::Type::BOOLEAN },
+  { key::kWebXRImmersiveArEnabled,
+    prefs::kWebXRImmersiveArEnabled,
+    base::Value::Type::BOOLEAN },
 #else  // defined(OS_ANDROID)
   { key::kDefaultInsecureContentSetting,
     prefs::kManagedDefaultInsecureContentSetting,
@@ -1359,24 +1369,12 @@
     policy::policy_prefs::kTargetBlankImpliesNoOpener,
     base::Value::Type::BOOLEAN },
 
-#if defined(OS_ANDROID)
-  { key::kTosDialogBehavior,
-    first_run::kTosDialogBehavior,
-    base::Value::Type::INTEGER },
-#endif  // defined(OS_ANDROID)
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   { key::kLacrosAllowed,
     prefs::kLacrosAllowed,
     base::Value::Type::BOOLEAN },
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if defined(OS_ANDROID)
-  { key::kWebXRImmersiveArEnabled,
-    prefs::kWebXRImmersiveArEnabled,
-    base::Value::Type::BOOLEAN },
-#endif  // defined(OS_ANDROID)
-
 #if !defined(OS_ANDROID)
   { key::kFetchKeepaliveDurationSecondsOnShutdown,
     prefs::kFetchKeepaliveDurationOnShutdown,
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index e2fc1baa..6df5cd9 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -212,6 +212,7 @@
 #include "chrome/browser/android/preferences/browser_prefs_android.h"
 #include "chrome/browser/android/usage_stats/usage_stats_bridge.h"
 #include "chrome/browser/first_run/android/first_run_prefs.h"
+#include "chrome/browser/lens/android/lens_prefs.h"
 #include "chrome/browser/media/android/cdm/media_drm_origin_id_manager.h"
 #include "chrome/browser/ssl/known_interception_disclosure_infobar_delegate.h"
 #include "chrome/browser/video_tutorials/prefs.h"
@@ -756,6 +757,7 @@
   ::android::RegisterPrefs(registry);
 
   registry->RegisterIntegerPref(first_run::kTosDialogBehavior, 0);
+  registry->RegisterBooleanPref(lens::kLensCameraAssistedSearchEnabled, true);
 #else  // defined(OS_ANDROID)
   enterprise_reporting::RegisterLocalStatePrefs(registry);
   gcm::RegisterPrefs(registry);
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index a3c52f27..4246a89 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8266,6 +8266,15 @@
       }
     ]
   },
+  "LensCameraAssistedSearchEnabled" : {
+    "os": ["android"],
+    "policy_pref_mapping_tests": [
+      {
+        "policies": { "LensCameraAssistedSearchEnabled": true },
+        "prefs": { "policy.lens_camera_assisted_search_enabled": { "location": "local_state" } }
+      }
+    ]
+  },
   "DefaultFileSystemReadGuardSetting": {
     "os": ["win", "linux", "mac", "chromeos"],
     "policy_pref_mapping_tests": [
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index f68e140a..b5283998 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -7133,6 +7133,33 @@
           Note that patterns you list here are treated as domains, not URLs, so you should not specify a scheme or port.''',
     },
     {
+      'name': 'LensCameraAssistedSearchEnabled',
+      'owners': [ '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]'],
+      'type': 'main',
+      'schema': { 'type': 'boolean' },
+      'future_on': ['android'],
+      'features': {
+        'dynamic_refresh': False,
+        'per_profile': False,
+      },
+      'items': [
+        {
+          'value': True,
+          'caption': 'Enable Lens camera assisted search for Enterprise user',
+        },
+        {
+          'value': False,
+          'caption': 'Disable Lens camera assisted search for Enterprise user',
+        },
+      ],
+      'example_value': True,
+      'default': True,
+      'id': 853,
+      'caption': '''Allow <ph name="GOOGLE_LENS_PRODUCT_NAME">Google Lens</ph> Camera Assisted Search''',
+      'tags': [],
+      'desc': '''Leaving the policy unset or setting it to Enabled allows users to search with their cameras using <ph name="GOOGLE_LENS_PRODUCT_NAME">Google Lens</ph>. Setting the policy to False means users can't see the <ph name="GOOGLE_LENS_PRODUCT_NAME">Google Lens</ph> button in the search box when <ph name="GOOGLE_LENS_PRODUCT_NAME">Google Lens</ph> Camera Assisted Search is supported.''',
+    },
+    {
       'name': 'InsecurePrivateNetworkRequestsAllowed',
       'owners': [
         '[email protected]',
@@ -26530,6 +26557,6 @@
   'placeholders': [],
   'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669],
   'deleted_atomic_policy_group_ids': [19],
-  'highest_id_currently_used': 852,
+  'highest_id_currently_used': 853,
   'highest_atomic_group_id_currently_used': 40
 }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 458c175..2c91542d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -24150,6 +24150,7 @@
   <int value="850" label="DeviceDebugPacketCaptureAllowed"/>
   <int value="851" label="SuggestLogoutAfterClosingLastWindow"/>
   <int value="852" label="SharedArrayBufferUnrestrictedAccessAllowed"/>
+  <int value="853" label="LensCameraAssistedSearchEnabled"/>
 </enum>
 
 <enum name="EnterprisePolicyDeviceIdValidity">
@@ -43030,10 +43031,10 @@
   <int value="8" label="Lens Search And Shop Supported"/>
   <int value="9" label="Camera Not Available"/>
   <int value="10" label="Disabled on Low End Device"/>
-  <int value="11" label="Disabled by Feature Flag"/>
-  <int value="12" label="AGSA Version Not Supported"/>
-  <int value="13" label="Disabled on Incognito"/>
-  <int value="14" label="Disabled on Tablet"/>
+  <int value="11" label="AGSA Version Not Supported"/>
+  <int value="12" label="Disabled on Incognito"/>
+  <int value="13" label="Disabled on Tablet"/>
+  <int value="14" label="Disabled for Enterprise user"/>
 </enum>
 
 <enum name="LevelDBCorruptionRestoreValue">