Bug 1401019 - Cancel the current U2F API request before starting a new one r=jcj
authorTim Taubert <ttaubert@mozilla.com>
Tue, 19 Sep 2017 16:55:38 +0200
changeset 433635 8d3d707fe0485a8900c4794a0c55018ad722c6de
parent 433634 c8277ab2befdd4c5027741f12bc94a0870925542
child 433636 383a2f567cebe59b0212e414b9a27d46123040bf
push id1567
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 12:36:05 +0000
treeherdermozilla-release@e512c14a0406 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjcj
bugs1401019
milestone57.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 1401019 - Cancel the current U2F API request before starting a new one r=jcj I wasn't sure what the right behavior for the U2F API is when `.sign()` or `.register()` is called but there's an ongoing request that wasn't fulfilled yet. I think it makes sense to deny the request (as we currently do) when a request of the same type is currently active. When however sign() -> register() or vice-versa is called then we should cancel the previous request and start the new one. From what I understand from reading the spec we definitely should call the callback before starting the new request. Bug #: 1401019 Differential Revision: https://phabricator.services.mozilla.com/D70
dom/u2f/U2F.cpp
dom/u2f/U2F.h
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -218,17 +218,17 @@ U2F::Register(const nsAString& aAppId,
 
   RefPtr<U2FManager> mgr = U2FManager::GetOrCreate();
   MOZ_ASSERT(mgr);
   if (!mgr || mRegisterCallback.isSome()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  MOZ_ASSERT(!mPromiseHolder.Exists());
+  Cancel();
   MOZ_ASSERT(mRegisterCallback.isNothing());
   mRegisterCallback = Some(nsMainThreadPtrHandle<U2FRegisterCallback>(
                         new nsMainThreadPtrHolder<U2FRegisterCallback>(
                             "U2F::Register::callback", &aCallback)));
 
   uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
 
   // Evaluate the AppID
@@ -315,17 +315,17 @@ U2F::Sign(const nsAString& aAppId,
 
   RefPtr<U2FManager> mgr = U2FManager::GetOrCreate();
   MOZ_ASSERT(mgr);
   if (!mgr || mSignCallback.isSome()) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  MOZ_ASSERT(!mPromiseHolder.Exists());
+  Cancel();
   MOZ_ASSERT(mSignCallback.isNothing());
   mSignCallback = Some(nsMainThreadPtrHandle<U2FSignCallback>(
                     new nsMainThreadPtrHolder<U2FSignCallback>(
                         "U2F::Sign::callback", &aCallback)));
 
   uint32_t adjustedTimeoutMillis = AdjustedTimeoutMillis(opt_aTimeoutSeconds);
 
   // Evaluate the AppID
@@ -380,10 +380,37 @@ U2F::Sign(const nsAString& aAppId,
               response.mErrorCode.Construct(static_cast<uint32_t>(aErrorCode));
 
               ExecuteCallback(response, localCb);
               localReqHolder.Complete();
           })
   ->Track(mPromiseHolder);
 }
 
+void
+U2F::Cancel()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  const ErrorCode errorCode = ErrorCode::OTHER_ERROR;
+
+  if (mRegisterCallback.isSome()) {
+    RegisterResponse response;
+    response.mErrorCode.Construct(static_cast<uint32_t>(errorCode));
+    ExecuteCallback(response, mRegisterCallback);
+  }
+
+  if (mSignCallback.isSome()) {
+    SignResponse response;
+    response.mErrorCode.Construct(static_cast<uint32_t>(errorCode));
+    ExecuteCallback(response, mSignCallback);
+  }
+
+  RefPtr<U2FManager> mgr = U2FManager::Get();
+  if (mgr) {
+    mgr->Cancel(NS_ERROR_DOM_OPERATION_ERR);
+  }
+
+  mPromiseHolder.DisconnectIfExists();
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -65,16 +65,19 @@ public:
   Sign(const nsAString& aAppId,
        const nsAString& aChallenge,
        const Sequence<RegisteredKey>& aRegisteredKeys,
        U2FSignCallback& aCallback,
        const Optional<Nullable<int32_t>>& opt_aTimeoutSeconds,
        ErrorResult& aRv);
 
 private:
+  void
+  Cancel();
+
   nsString mOrigin;
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   nsCOMPtr<nsISerialEventTarget> mEventTarget;
   Maybe<nsMainThreadPtrHandle<U2FRegisterCallback>> mRegisterCallback;
   Maybe<nsMainThreadPtrHandle<U2FSignCallback>> mSignCallback;
   MozPromiseRequestHolder<U2FPromise> mPromiseHolder;
 
   ~U2F();