Bug 1605005 [wpt PR 20859] - [webnfc] Reject the push when a non-NDEF tag comes in proximity, a=testonly
authorLeon Han <leon.han@intel.com>
Fri, 20 Dec 2019 11:40:01 +0000
changeset 508256 a3d27e58f2d62a91a2f0ff8fa812c88fb53ef860
parent 508255 f7407fcab287c168cfd92f2a618bea759bee20c4
child 508257 d0c32e81066eb407d28788002d31dec53eaa090f
push id36943
push useropoprus@mozilla.com
push dateMon, 23 Dec 2019 16:27:52 +0000
treeherdermozilla-central@6d2e33d632e7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1605005, 20859, 520391, 1967745, 726643
milestone73.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1605005 [wpt PR 20859] - [webnfc] Reject the push when a non-NDEF tag comes in proximity, a=testonly Automatic update from web-platform-tests [webnfc] Reject the push when a non-NDEF tag comes in proximity Previously, when a non-NDEF tag comes in proximity, NDEFWriter#push() does nothing and still keeps in pending state. This CL switches to reject NDEFWriter#push() in such case so that WebDev can get a sense of what's happening. BUG=520391 Change-Id: I17569910466e75f12ff4e37c29180e2a9af9db13 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1967745 Commit-Queue: Leon Han <leon.han@intel.com> Reviewed-by: Fran├žois Beaufort <beaufort.francois@gmail.com> Reviewed-by: Rijubrata Bhaumik <rijubrata.bhaumik@intel.com> Cr-Commit-Position: refs/heads/master@{#726643} -- wpt-commits: 256b4685b8e702c14ed854347f23f4979edbfc8e wpt-pr: 20859
testing/web-platform/tests/resources/chromium/nfc-mock.js
testing/web-platform/tests/web-nfc/NDEFReader_scan.https.html
testing/web-platform/tests/web-nfc/NDEFWriter_push.https.html
testing/web-platform/tests/web-nfc/README.md
--- a/testing/web-platform/tests/resources/chromium/nfc-mock.js
+++ b/testing/web-platform/tests/resources/chromium/nfc-mock.js
@@ -149,63 +149,56 @@ var WebNFCTest = (() => {
       this.interceptor_ = new MojoInterfaceInterceptor(
           device.mojom.NFC.name, "context", true);
       this.interceptor_.oninterfacerequest =
           e => this.bindingSet_.addBinding(this, e.handle);
       this.interceptor_.start();
 
       this.hw_status_ = NFCHWStatus.ENABLED;
       this.pushed_message_ = null;
-      this.push_options_ = null;
+      this.pending_push_options_ = null;
       this.pending_promise_func_ = null;
       this.push_completed_ = true;
       this.client_ = null;
       this.watchers_ = [];
       this.reading_messages_ = [];
       this.operations_suspended_ = false;
-      this.is_ndef_tech_ = true;
       this.is_formatted_tag_ = false;
     }
 
     // NFC delegate functions.
     async push(message, options) {
       let error = this.getHWError();
       if (error)
         return error;
       // Cancels previous pending push operation.
       if (this.pending_promise_func_) {
         this.cancelPendingPushOperation();
       }
 
       this.pushed_message_ = message;
-      this.push_options_ = options;
-
+      this.pending_push_options_ = options;
       return new Promise(resolve => {
-        this.pending_promise_func_ = resolve;
-        if (this.operations_suspended_) {
-          // Pends push operation if NFC operation is suspended.
-        } else if (!this.push_completed_) {
-          // Leaves the push operating pending.
-        } else if (!this.is_ndef_tech_) {
-          // Resolves with NotSupportedError if the device does not expose
-          // NDEF technology.
-          resolve(createNDEFError(device.mojom.NDEFErrorType.NOT_SUPPORTED));
+        if (this.operations_suspended_ || !this.push_completed_) {
+          // Leaves the push pending.
+          this.pending_promise_func_ = resolve;
         } else if (this.is_formatted_tag_ && !options.overwrite) {
           // Resolves with NotAllowedError if there are NDEF records on the device
           // and overwrite is false.
           resolve(createNDEFError(device.mojom.NDEFErrorType.NOT_ALLOWED));
         } else {
           resolve(createNDEFError(null));
         }
       });
     }
 
     async cancelPush(target) {
-      if (this.push_options_ && ((target === device.mojom.NDEFPushTarget.ANY) ||
-          (this.push_options_.target === target))) {
+      if (this.pending_push_options_ &&
+          ((target === device.mojom.NDEFPushTarget.ANY) ||
+           (this.pending_push_options_.target === target))) {
         this.cancelPendingPushOperation();
       }
 
       return createNDEFError(null);
     }
 
     setClient(client) {
       this.client_ = client;
@@ -216,17 +209,17 @@ var WebNFCTest = (() => {
       let error = this.getHWError();
       if (error) {
         return error;
       }
 
       this.watchers_.push({id: id, options: options});
       // Ignores reading if NFC operation is suspended
       // or the NFC tag does not expose NDEF technology.
-      if(!this.operations_suspended_ && this.is_ndef_tech_) {
+      if (!this.operations_suspended_) {
         // Triggers onWatch if the new watcher matches existing messages.
         for (let message of this.reading_messages_) {
           if (matchesWatchOptions(message, options)) {
             this.client_.onWatch(
                 [id], fake_tag_serial_number, toMojoNDEFMessage(message));
           }
         }
       }
@@ -265,17 +258,17 @@ var WebNFCTest = (() => {
       this.hw_status_ = status;
     }
 
     pushedMessage() {
       return this.pushed_message_;
     }
 
     pushOptions() {
-      return this.push_options_;
+      return this.pending_push_options_;
     }
 
     watchOptions() {
       assert_not_equals(this.watchers_.length, 0);
       return this.watchers_[this.watchers_.length - 1].options;
     }
 
     setPendingPushCompleted(result) {
@@ -283,41 +276,38 @@ var WebNFCTest = (() => {
     }
 
     reset() {
       this.hw_status_ = NFCHWStatus.ENABLED;
       this.watchers_ = [];
       this.reading_messages_ = [];
       this.operations_suspended_ = false;
       this.cancelPendingPushOperation();
-      this.is_ndef_tech_ = true;
       this.is_formatted_tag_ = false;
     }
 
     cancelPendingPushOperation() {
       if (this.pending_promise_func_) {
         this.pending_promise_func_(
             createNDEFError(device.mojom.NDEFErrorType.OPERATION_CANCELLED));
+        this.pending_promise_func_ = null;
       }
 
       this.pushed_message_ = null;
-      this.push_options_ = null;
-      this.pending_promise_func_ = null;
+      this.pending_push_options_ = null;
       this.push_completed_ = true;
     }
 
     // Sets message that is used to deliver NFC reading updates.
     setReadingMessage(message) {
       this.reading_messages_.push(message);
-      // Ignores reading if the NFC tag does not expose NDEF technology.
-      if(!this.is_ndef_tech_) return;
       // Ignores reading if NFC operation is suspended.
       if(this.operations_suspended_) return;
       // Ignores reading if NDEFPushOptions.ignoreRead is true.
-      if(this.push_options_ && this.push_options_.ignoreRead)
+      if (this.pending_push_options_ && this.pending_push_options_.ignoreRead)
         return;
       // Triggers onWatch if the new message matches existing watchers.
       for (let watcher of this.watchers_) {
         if (matchesWatchOptions(message, watcher.options)) {
           this.client_.onWatch(
               [watcher.id], fake_tag_serial_number,
               toMojoNDEFMessage(message));
         }
@@ -331,34 +321,42 @@ var WebNFCTest = (() => {
     }
 
     // Resumes all suspended NFC operations.
     resumeNFCOperations() {
       this.operations_suspended_ = false;
       // Resumes pending NFC reading.
       for (let watcher of this.watchers_) {
         for (let message of this.reading_messages_) {
-          if (matchesWatchOptions(message, watcher.options) && this.is_ndef_tech_) {
+          if (matchesWatchOptions(message, watcher.options)) {
             this.client_.onWatch(
                 [watcher.id], fake_tag_serial_number,
                 toMojoNDEFMessage(message));
           }
         }
       }
       // Resumes pending push operation.
-      if (this.pending_promise_func_) {
+      if (this.pending_promise_func_ && this.push_completed_) {
         this.pending_promise_func_(createNDEFError(null));
+        this.pending_promise_func_ = null;
       }
     }
 
-    setIsNDEFTech(isNdef) {
-      this.is_ndef_tech_ = isNdef;
-      if (!isNdef && this.watchers_.length != 0) {
+    // Simulates the device coming in proximity does not expose NDEF technology.
+    simulateNonNDEFTagDiscovered() {
+      // Notify NotSupportedError to all active readers.
+      if (this.watchers_.length != 0) {
         this.client_.onError(device.mojom.NDEFErrorType.NOT_SUPPORTED);
       }
+      // Reject the pending push with NotSupportedError.
+      if (this.pending_promise_func_) {
+        this.pending_promise_func_(
+            createNDEFError(device.mojom.NDEFErrorType.NOT_SUPPORTED));
+        this.pending_promise_func_ = null;
+      }
     }
 
     setIsFormattedTag(isFormatted) {
       this.is_formatted_tag_ = isFormatted;
     }
   }
 
   let testInternal = {
--- a/testing/web-platform/tests/web-nfc/NDEFReader_scan.https.html
+++ b/testing/web-platform/tests/web-nfc/NDEFReader_scan.https.html
@@ -181,17 +181,17 @@ nfc_test(async (t, mockNFC) => {
   const reader2 = new NDEFReader();
   const readerWatcher2 = new EventWatcher(t, reader2, ["reading", "error"]);
   const promise2 = readerWatcher2.wait_for("error").then(event => {
     assert_true(event instanceof ErrorEvent);
   });
   promises.push(promise2);
   await reader2.scan();
 
-  mockNFC.setIsNDEFTech(false);
+  mockNFC.simulateNonNDEFTagDiscovered();
   await Promise.all(promises);
 }, "Test that NDEFReader.onerror should be fired if the NFC tag does not \
 expose NDEF technology.");
 
 nfc_test(async (t, mockNFC) => {
   const reader = new NDEFReader();
   const controller = new AbortController();
   const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]);
--- a/testing/web-platform/tests/web-nfc/NDEFWriter_push.https.html
+++ b/testing/web-platform/tests/web-nfc/NDEFWriter_push.https.html
@@ -403,20 +403,29 @@ nfc_test(async (t, mockNFC) => {
   const writer = new NDEFWriter();
   await writer.push({ records: [{ recordType: "mime", data: test_buffer_data }] });
   assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage());
 }, "Test that mediaType should be set to 'application/octet-stream' if \
 NDEFRecordInit.record's recordType is 'mime' and NDEFRecordInit.record's \
 mediaType is undefined.");
 
 nfc_test(async (t, mockNFC) => {
+  // Make sure the push will be pending in the mock.
+  mockNFC.setPendingPushCompleted(false);
+
   const writer = new NDEFWriter();
-  mockNFC.setIsNDEFTech(false);
-  await promise_rejects(t, 'NotSupportedError', writer.push(test_text_data));
-}, "NDEFWriter.push should fail when the NFC device does not expose \
+  const promise = writer.push(test_text_data);
+
+  // Just to make sure the push() request has already reached to the mock.
+  const reader = new NDEFReader();
+  await reader.scan();
+
+  mockNFC.simulateNonNDEFTagDiscovered();
+  await promise_rejects(t, 'NotSupportedError', promise);
+}, "NDEFWriter.push should fail when the NFC device coming up does not expose \
 NDEF technology.");
 
 nfc_test(async (t, mockNFC) => {
   const writer = new NDEFWriter();
   await writer.push(test_text_data, { overwrite: false });
   assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage());
 }, "NDEFWriter.push should succeed to push data to an unformatted NFC device \
 when the NDEFPushOptions.overwrite is false.");
--- a/testing/web-platform/tests/web-nfc/README.md
+++ b/testing/web-platform/tests/web-nfc/README.md
@@ -11,17 +11,17 @@ The `WebNFCTest` interface is defined as
   };
 
   class MockNFC {
     setHWStatus(number status); // Sets the hardware status.
     setReadingMessage(NDEFMessageInit message); // Sets message that is used to deliver NFC reading updates.
     setPendingPushCompleted(boolean result); // Sets if the pending push is completed.
     pushedMessage(); // Gets the pushed `NDEFMessageSource`.
     pushOptions(); // Gets the pushed `NDEFPushOptions`.
-    setIsNDEFTech(boolean isNDEF); // Sets if the NFC device exposes NDEF technology.
+    simulateNonNDEFTagDiscovered(); // Simulates that the NFC device discovered does not expose NDEF technology.
     setIsFormattedTag(boolean isFormatted); // Sets if the NFC tag has formatted NDEF message.
   };
 ```
 
 The Chromium implementation of the `WebNFCTest` interface is located in
 [nfc-mock.js](../resources/chromium/nfc-mock.js).
 
 Other browser vendors should provide their own implementations of