[WebNFC] Add permission prompt for NDEFWriter.push

This CL makes sure NDEFWriter.push shows a permission request if user
didn't previously allow Web NFC. Follow-up CL will do something
similar for NDEFReader.

Screenshots: https://photos.app.goo.gl/k7wz55v9ELVTS19i8

Bug: 520391
Change-Id: I4a1ac1edcd39d5d8a27f891a37044de8e9d0587a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895345
Commit-Queue: François Beaufort <[email protected]>
Reviewed-by: Rijubrata Bhaumik <[email protected]>
Reviewed-by: Balazs Engedy <[email protected]>
Reviewed-by: Peter Conn <[email protected]>
Reviewed-by: Charlie Harrison <[email protected]>
Reviewed-by: Andrew Grieve <[email protected]>
Cr-Commit-Position: refs/heads/master@{#718123}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 73a9ec4..8727d27 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -911,6 +911,8 @@
     "net/system_network_context_manager.h",
     "net_benchmarking.cc",
     "net_benchmarking.h",
+    "nfc/nfc_permission_context.cc",
+    "nfc/nfc_permission_context.h",
     "notifications/alert_dispatcher_mac.h",
     "notifications/metrics/notification_metrics_logger.cc",
     "notifications/metrics/notification_metrics_logger.h",
@@ -2810,8 +2812,6 @@
       "metrics/incognito_observer_android.cc",
       "metrics/page_load_metrics_provider.cc",
       "metrics/page_load_metrics_provider.h",
-      "nfc/nfc_permission_context.cc",
-      "nfc/nfc_permission_context.h",
       "notifications/notification_platform_bridge_android.cc",
       "notifications/notification_platform_bridge_android.h",
       "notifications/notification_trigger_scheduler_android.cc",
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index 6a3b0fb6..fe3ef6b4 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -49,6 +49,7 @@
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_MIDI, R.drawable.infobar_midi)
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_MULTIPLE_DOWNLOADS,
                     R.drawable.infobar_downloading)
+DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_NFC, R.drawable.ic_infobar_nfc)
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_NOTIFICATIONS,
                     R.drawable.infobar_desktop_notifications)
 DECLARE_RESOURCE_ID(IDR_ANDROID_INFOBAR_NOTIFICATIONS_OFF,
diff --git a/chrome/browser/nfc/nfc_permission_context.cc b/chrome/browser/nfc/nfc_permission_context.cc
index 68d2faed..76625aa 100644
--- a/chrome/browser/nfc/nfc_permission_context.cc
+++ b/chrome/browser/nfc/nfc_permission_context.cc
@@ -4,12 +4,8 @@
 
 #include "chrome/browser/nfc/nfc_permission_context.h"
 
-#include "build/build_config.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
 #include "chrome/browser/permissions/permission_request_id.h"
-#if !defined(OS_ANDROID)
-#error This file currently only supports Android.
-#endif
 
 NfcPermissionContext::NfcPermissionContext(Profile* profile)
     : PermissionContextBase(profile,
@@ -18,12 +14,14 @@
 
 NfcPermissionContext::~NfcPermissionContext() = default;
 
+#if !defined(OS_ANDROID)
 ContentSetting NfcPermissionContext::GetPermissionStatusInternal(
     content::RenderFrameHost* render_frame_host,
     const GURL& requesting_origin,
     const GURL& embedding_origin) const {
   return CONTENT_SETTING_BLOCK;
 }
+#endif
 
 void NfcPermissionContext::DecidePermission(
     content::WebContents* web_contents,
@@ -32,9 +30,13 @@
     const GURL& embedding_origin,
     bool user_gesture,
     BrowserPermissionCallback callback) {
-  // The user should never be prompted to authorize NFC from
-  // NfcPermissionContext.
-  NOTREACHED();
+  if (!user_gesture) {
+    std::move(callback).Run(CONTENT_SETTING_BLOCK);
+    return;
+  }
+  PermissionContextBase::DecidePermission(web_contents, id, requesting_origin,
+                                          embedding_origin, user_gesture,
+                                          std::move(callback));
 }
 
 void NfcPermissionContext::UpdateTabContext(const PermissionRequestID& id,
diff --git a/chrome/browser/nfc/nfc_permission_context.h b/chrome/browser/nfc/nfc_permission_context.h
index f346814..1adc139 100644
--- a/chrome/browser/nfc/nfc_permission_context.h
+++ b/chrome/browser/nfc/nfc_permission_context.h
@@ -18,10 +18,12 @@
 
  private:
   // PermissionContextBase:
+#if !defined(OS_ANDROID)
   ContentSetting GetPermissionStatusInternal(
       content::RenderFrameHost* render_frame_host,
       const GURL& requesting_origin,
       const GURL& embedding_origin) const override;
+#endif
   void DecidePermission(content::WebContents* web_contents,
                         const PermissionRequestID& id,
                         const GURL& requesting_origin,
diff --git a/chrome/browser/permissions/permission_manager.cc b/chrome/browser/permissions/permission_manager.cc
index dd532ab..1bc9a37 100644
--- a/chrome/browser/permissions/permission_manager.cc
+++ b/chrome/browser/permissions/permission_manager.cc
@@ -155,11 +155,7 @@
     case PermissionType::WAKE_LOCK_SYSTEM:
       return ContentSettingsType::WAKE_LOCK_SYSTEM;
     case PermissionType::NFC:
-#if defined(OS_ANDROID)
       return ContentSettingsType::NFC;
-#else
-      break;
-#endif
     case PermissionType::NUM:
       break;
   }
@@ -362,10 +358,8 @@
   permission_contexts_[ContentSettingsType::WAKE_LOCK_SYSTEM] =
       std::make_unique<WakeLockPermissionContext>(
           profile, ContentSettingsType::WAKE_LOCK_SYSTEM);
-#if defined(OS_ANDROID)
   permission_contexts_[ContentSettingsType::NFC] =
       std::make_unique<NfcPermissionContext>(profile);
-#endif
 }
 
 PermissionManager::~PermissionManager() {
diff --git a/chrome/browser/permissions/permission_request.h b/chrome/browser/permissions/permission_request.h
index 575ade8b..3213077 100644
--- a/chrome/browser/permissions/permission_request.h
+++ b/chrome/browser/permissions/permission_request.h
@@ -45,6 +45,7 @@
   PERMISSION_CLIPBOARD_READ = 16,
   PERMISSION_SECURITY_KEY_ATTESTATION = 17,
   PERMISSION_PAYMENT_HANDLER = 18,
+  PERMISSION_NFC = 19,
   // NUM must be the last value in the enum.
   NUM
 };
diff --git a/chrome/browser/permissions/permission_request_impl.cc b/chrome/browser/permissions/permission_request_impl.cc
index a27242e0..85cc20c 100644
--- a/chrome/browser/permissions/permission_request_impl.cc
+++ b/chrome/browser/permissions/permission_request_impl.cc
@@ -56,6 +56,8 @@
       return IDR_ANDROID_INFOBAR_ACCESSIBILITY_EVENTS;
     case ContentSettingsType::CLIPBOARD_READ:
       return IDR_ANDROID_INFOBAR_CLIPBOARD;
+    case ContentSettingsType::NFC:
+      return IDR_ANDROID_INFOBAR_NFC;
     default:
       NOTREACHED();
       return IDR_ANDROID_INFOBAR_WARNING;
@@ -118,6 +120,9 @@
     case ContentSettingsType::CLIPBOARD_READ:
       message_id = IDS_CLIPBOARD_PERMISSION_TITLE;
       break;
+    case ContentSettingsType::NFC:
+      message_id = IDS_NFC_PERMISSION_TITLE;
+      break;
     default:
       NOTREACHED();
       return base::string16();
@@ -155,6 +160,9 @@
     case ContentSettingsType::CLIPBOARD_READ:
       message_id = IDS_CLIPBOARD_INFOBAR_TEXT;
       break;
+    case ContentSettingsType::NFC:
+      message_id = IDS_NFC_INFOBAR_TEXT;
+      break;
     default:
       NOTREACHED();
       return base::string16();
diff --git a/chrome/browser/permissions/permission_uma_util.cc b/chrome/browser/permissions/permission_uma_util.cc
index 891aa2a..4c67abc 100644
--- a/chrome/browser/permissions/permission_uma_util.cc
+++ b/chrome/browser/permissions/permission_uma_util.cc
@@ -95,6 +95,8 @@
       return "SecurityKeyAttestation";
     case PermissionRequestType::PERMISSION_PAYMENT_HANDLER:
       return "PaymentHandler";
+    case PermissionRequestType::PERMISSION_NFC:
+      return "Nfc";
     default:
       NOTREACHED();
       return "";
@@ -432,6 +434,10 @@
       UMA_HISTOGRAM_ENUMERATION("Permissions.Action.PaymentHandler", action,
                                 PermissionAction::NUM);
       break;
+    case ContentSettingsType::NFC:
+      UMA_HISTOGRAM_ENUMERATION("Permissions.Action.Nfc", action,
+                                PermissionAction::NUM);
+      break;
     // The user is not prompted for these permissions, thus there is no
     // permission action recorded for them.
     default:
diff --git a/chrome/browser/permissions/permission_util.cc b/chrome/browser/permissions/permission_util.cc
index 2cd0eab..ca5266e1 100644
--- a/chrome/browser/permissions/permission_util.cc
+++ b/chrome/browser/permissions/permission_util.cc
@@ -91,6 +91,8 @@
       return PermissionRequestType::PERMISSION_CLIPBOARD_READ;
     case ContentSettingsType::PAYMENT_HANDLER:
       return PermissionRequestType::PERMISSION_PAYMENT_HANDLER;
+    case ContentSettingsType::NFC:
+      return PermissionRequestType::PERMISSION_NFC;
     default:
       NOTREACHED();
       return PermissionRequestType::UNKNOWN;
@@ -171,9 +173,7 @@
     case ContentSettingsType::PERIODIC_BACKGROUND_SYNC:
     case ContentSettingsType::WAKE_LOCK_SCREEN:
     case ContentSettingsType::WAKE_LOCK_SYSTEM:
-#if defined(OS_ANDROID)
     case ContentSettingsType::NFC:
-#endif
       return true;
     default:
       return false;