Bug 1105827 - Part 10: Fire change event for PermissionStatus objects. r=baku
authorBirunthan Mohanathas <birunthan@mohanathas.com>
Fri, 21 Aug 2015 19:53:29 -0700
changeset 293218 1bb4c708f660b2e0b2e1dda66c3f79e5f97da6a1
parent 293217 657af0e9e13a372fd5a65ced70ea910ea69a1763
child 293219 413c77eaef08bb8ea7a745e1274c3ea0e91f55cd
push id962
push userjlund@mozilla.com
push dateFri, 04 Dec 2015 23:28:54 +0000
treeherdermozilla-release@23a2d286e80f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1105827
milestone43.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 1105827 - Part 10: Fire change event for PermissionStatus objects. r=baku
dom/permission/PermissionStatus.cpp
dom/permission/PermissionStatus.h
dom/permission/tests/test_permissions_api.html
--- a/dom/permission/PermissionStatus.cpp
+++ b/dom/permission/PermissionStatus.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/PermissionStatus.h"
 
+#include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/Services.h"
 #include "mozilla/UniquePtr.h"
 #include "nsIPermissionManager.h"
 #include "PermissionObserver.h"
 #include "PermissionUtils.h"
 
 namespace mozilla {
 namespace dom {
@@ -108,10 +109,22 @@ PermissionStatus::GetPrincipal() const
   nsIDocument* doc = window->GetExtantDoc();
   if (NS_WARN_IF(!doc)) {
     return nullptr;
   }
 
   return doc->NodePrincipal();
 }
 
+void
+PermissionStatus::PermissionChanged()
+{
+  auto oldState = mState;
+  UpdateState();
+  if (mState != oldState) {
+    nsRefPtr<AsyncEventDispatcher> eventDispatcher =
+      new AsyncEventDispatcher(this, NS_LITERAL_STRING("change"), false);
+    eventDispatcher->PostDOMEvent();
+  }
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/permission/PermissionStatus.h
+++ b/dom/permission/PermissionStatus.h
@@ -39,17 +39,17 @@ private:
   PermissionStatus(nsPIDOMWindow* aWindow, PermissionName aName);
 
   nsresult Init();
 
   nsresult UpdateState();
 
   nsIPrincipal* GetPrincipal() const;
 
-  void PermissionChanged() {}
+  void PermissionChanged();
 
   PermissionName mName;
   PermissionState mState;
 
   nsRefPtr<PermissionObserver> mObserver;
 };
 
 } // namespace dom
--- a/dom/permission/tests/test_permissions_api.html
+++ b/dom/permission/tests/test_permissions_api.html
@@ -10,16 +10,19 @@
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body onload='runTests()'>
 <pre id="test">
 <script type="application/javascript;version=1.8">
 'use strict';
 
+let { UNKNOWN_ACTION, PROMPT_ACTION, ALLOW_ACTION, DENY_ACTION } =
+  SpecialPowers.Ci.nsIPermissionManager;
+
 SimpleTest.waitForExplicitFinish();
 
 const PERMISSIONS = [
   { name: 'geolocation', perm: 'geo' },
   { name: 'notifications', perm: 'desktop-notification' },
   { name: 'push', perm: 'push' },
 ];
 
@@ -63,33 +66,60 @@ function checkUnsupportedPermissions() {
 }
 
 function checkUserVisiblePushPermission() {
   return navigator.permissions.query({ name: 'push', userVisible: true }).then(
     result => ok(false, `query should not have resolved for userVisible push`),
     error => ok(true, `query should have rejected for userVisible push`));
 }
 
+function promiseStateChanged(name, state) {
+  return navigator.permissions.query({ name }).then(
+    status => {
+      return new Promise((resolve, reject) => {
+        status.onchange = () => {
+          status.onchange = null;
+          is(status.state, state, `state changed for '${name}'`);
+          resolve();
+        };
+      });
+    },
+    error => ok(false, `query should not have rejected for '${name}'`));
+}
+
+function testStatusOnChange() {
+  return new Promise((resolve, reject) => {
+    SpecialPowers.popPermissions(() => {
+      let permission = 'geolocation';
+      let promiseGranted = promiseStateChanged(permission, 'granted');
+      setPermissions(ALLOW_ACTION);
+      promiseGranted.then(() => {
+        let promisePrompt = promiseStateChanged(permission, 'prompt');
+        SpecialPowers.popPermissions();
+        return promisePrompt;
+      }).then(resolve);
+    });
+  });
+}
+
 function runTests() {
-  let permMgr = SpecialPowers.Ci.nsIPermissionManager;
-
   setup()
     .then(checkUnsupportedPermissions)
     .then(checkUserVisiblePushPermission)
-    .then(() => setPermissions(permMgr.UNKNOWN_ACTION))
+    .then(() => setPermissions(UNKNOWN_ACTION))
     .then(() => checkPermissions('prompt'))
-    .then(() => setPermissions(permMgr.PROMPT_ACTION))
+    .then(() => setPermissions(PROMPT_ACTION))
     .then(() => checkPermissions('prompt'))
-    .then(() => setPermissions(permMgr.ALLOW_ACTION))
+    .then(() => setPermissions(ALLOW_ACTION))
     .then(() => checkPermissions('granted'))
-    .then(() => setPermissions(permMgr.DENY_ACTION))
+    .then(() => setPermissions(DENY_ACTION))
     .then(() => checkPermissions('denied'))
+    .then(testStatusOnChange)
     .then(SimpleTest.finish)
     .catch ((e) => {
       ok(false, 'Unexpected error ' + e);
       SimpleTest.finish();
     });
 }
 </script>
 </pre>
 </body>
 </html>
-