Storage Access API: Cap the number of times an iframe document can request access
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2019 20:03:58 +0000 (20:03 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 20 Jun 2019 20:03:58 +0000 (20:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=199074
<rdar://problem/51857195>

Reviewed by Brent Fulgham.

Tested manually.

This change just adds a counter to the number of times the user explicitly
denies storage access and returns early if the counter has reached the limit
of 2.

We hoped that iframes that request storage access would count the number
of times the user has been asked and not repeat the request over and over.
However, we're seeing pretty aggressive use of the API and users are
complaining. Therefore, we need a cap on how many times an iframed
document can ask if it is explicitly denied access by the user.

This is a first measure. If we see continued aggressive use of the API,
we'll have to consider more drastic measures.

* dom/DocumentStorageAccess.cpp:
(WebCore::DocumentStorageAccess::requestStorageAccess):
* dom/DocumentStorageAccess.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246647 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/dom/DocumentStorageAccess.cpp
Source/WebCore/dom/DocumentStorageAccess.h

index ca62184..df0980a 100644 (file)
@@ -1,3 +1,30 @@
+2019-06-20  John Wilander  <wilander@apple.com>
+
+        Storage Access API: Cap the number of times an iframe document can request access
+        https://bugs.webkit.org/show_bug.cgi?id=199074
+        <rdar://problem/51857195>
+
+        Reviewed by Brent Fulgham.
+
+        Tested manually.
+
+        This change just adds a counter to the number of times the user explicitly
+        denies storage access and returns early if the counter has reached the limit
+        of 2.
+
+        We hoped that iframes that request storage access would count the number
+        of times the user has been asked and not repeat the request over and over.
+        However, we're seeing pretty aggressive use of the API and users are
+        complaining. Therefore, we need a cap on how many times an iframed
+        document can ask if it is explicitly denied access by the user.
+
+        This is a first measure. If we see continued aggressive use of the API,
+        we'll have to consider more drastic measures.
+
+        * dom/DocumentStorageAccess.cpp:
+        (WebCore::DocumentStorageAccess::requestStorageAccess):
+        * dom/DocumentStorageAccess.h:
+
 2019-06-20  Youenn Fablet  <youenn@apple.com>
 
         Changing settings of a MediaStreamTrack clone should not alter the settings of the original track
 2019-06-20  Youenn Fablet  <youenn@apple.com>
 
         Changing settings of a MediaStreamTrack clone should not alter the settings of the original track
index 4a33aa9..81efb10 100644 (file)
@@ -128,7 +128,7 @@ void DocumentStorageAccess::requestStorageAccess(Ref<DeferredPromise>&& promise)
         return;
     }
     
         return;
     }
     
-    if (!m_document.frame() || m_document.securityOrigin().isUnique()) {
+    if (!m_document.frame() || m_document.securityOrigin().isUnique() || !isAllowedToRequestFrameSpecificStorageAccess()) {
         promise->reject();
         return;
     }
         promise->reject();
         return;
     }
@@ -192,8 +192,11 @@ void DocumentStorageAccess::requestStorageAccess(Ref<DeferredPromise>&& promise)
         if (wasGranted == StorageAccessWasGranted::Yes) {
             document->setHasFrameSpecificStorageAccess(true);
             promise->resolve();
         if (wasGranted == StorageAccessWasGranted::Yes) {
             document->setHasFrameSpecificStorageAccess(true);
             promise->resolve();
-        } else
+        } else {
+            if (promptWasShown == StorageAccessPromptWasShown::Yes)
+                document->setWasExplicitlyDeniedFrameSpecificStorageAccess();
             promise->reject();
             promise->reject();
+        }
 
         if (shouldPreserveUserGesture) {
             MicrotaskQueue::mainThreadQueue().append(std::make_unique<VoidMicrotask>([documentReference = WTFMove(documentReference)] () {
 
         if (shouldPreserveUserGesture) {
             MicrotaskQueue::mainThreadQueue().append(std::make_unique<VoidMicrotask>([documentReference = WTFMove(documentReference)] () {
index 6a6f8c1..ce7f310 100644 (file)
@@ -46,6 +46,8 @@ enum class StorageAccessPromptWasShown : bool {
     Yes
 };
 
     Yes
 };
 
+const unsigned maxNumberOfTimesExplicitlyDeniedFrameSpecificStorageAccess = 2;
+
 class DocumentStorageAccess final : public Supplement<Document>, public CanMakeWeakPtr<DocumentStorageAccess> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
 class DocumentStorageAccess final : public Supplement<Document>, public CanMakeWeakPtr<DocumentStorageAccess> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -64,12 +66,16 @@ private:
     static const char* supplementName();
     bool hasFrameSpecificStorageAccess() const;
     void setHasFrameSpecificStorageAccess(bool);
     static const char* supplementName();
     bool hasFrameSpecificStorageAccess() const;
     void setHasFrameSpecificStorageAccess(bool);
+    void setWasExplicitlyDeniedFrameSpecificStorageAccess() { ++m_numberOfTimesExplicitlyDeniedFrameSpecificStorageAccess; };
+    bool isAllowedToRequestFrameSpecificStorageAccess() { return m_numberOfTimesExplicitlyDeniedFrameSpecificStorageAccess < maxNumberOfTimesExplicitlyDeniedFrameSpecificStorageAccess; };
     void enableTemporaryTimeUserGesture();
     void consumeTemporaryTimeUserGesture();
 
     std::unique_ptr<UserGestureIndicator> m_temporaryUserGesture;
     
     Document& m_document;
     void enableTemporaryTimeUserGesture();
     void consumeTemporaryTimeUserGesture();
 
     std::unique_ptr<UserGestureIndicator> m_temporaryUserGesture;
     
     Document& m_document;
+
+    uint8_t m_numberOfTimesExplicitlyDeniedFrameSpecificStorageAccess = 0;
 };
 
 } // namespace WebCore
 };
 
 } // namespace WebCore