tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_popupNotification_5.js (16913B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 function test() {
      6  waitForExplicitFinish();
      7 
      8  ok(PopupNotifications, "PopupNotifications object exists");
      9  ok(PopupNotifications.panel, "PopupNotifications panel exists");
     10 
     11  setup();
     12 }
     13 
     14 var gNotification;
     15 
     16 var tests = [
     17  // panel updates should fire the showing and shown callbacks again.
     18  {
     19    id: "Test#1",
     20    run() {
     21      this.notifyObj = new BasicNotification(this.id);
     22      this.notification = showNotification(this.notifyObj);
     23    },
     24    onShown(popup) {
     25      checkPopup(popup, this.notifyObj);
     26 
     27      this.notifyObj.showingCallbackTriggered = false;
     28      this.notifyObj.shownCallbackTriggered = false;
     29 
     30      // Force an update of the panel. This is typically called
     31      // automatically when receiving 'activate' or 'TabSelect' events,
     32      // but from a setTimeout, which is inconvenient for the test.
     33      PopupNotifications._update();
     34 
     35      checkPopup(popup, this.notifyObj);
     36 
     37      this.notification.remove();
     38    },
     39    onHidden() {},
     40  },
     41  // A first dismissed notification shouldn't stop _update from showing a second notification
     42  {
     43    id: "Test#2",
     44    run() {
     45      this.notifyObj1 = new BasicNotification(this.id);
     46      this.notifyObj1.id += "_1";
     47      this.notifyObj1.anchorID = "default-notification-icon";
     48      this.notifyObj1.options.dismissed = true;
     49      this.notification1 = showNotification(this.notifyObj1);
     50 
     51      this.notifyObj2 = new BasicNotification(this.id);
     52      this.notifyObj2.id += "_2";
     53      this.notifyObj2.anchorID = "geo-notification-icon";
     54      this.notifyObj2.options.dismissed = true;
     55      this.notification2 = showNotification(this.notifyObj2);
     56 
     57      this.notification2.dismissed = false;
     58      PopupNotifications._update();
     59    },
     60    onShown(popup) {
     61      checkPopup(popup, this.notifyObj2);
     62      this.notification1.remove();
     63      this.notification2.remove();
     64    },
     65    onHidden() {},
     66  },
     67  // The anchor icon should be shown for notifications in background windows.
     68  {
     69    id: "Test#3",
     70    async run() {
     71      let notifyObj = new BasicNotification(this.id);
     72      notifyObj.options.dismissed = true;
     73 
     74      let win = await BrowserTestUtils.openNewBrowserWindow();
     75 
     76      // Open the notification in the original window, now in the background.
     77      let notification = showNotification(notifyObj);
     78      let anchor = document.getElementById("default-notification-icon");
     79      is(anchor.getAttribute("showing"), "true", "the anchor is shown");
     80      notification.remove();
     81 
     82      await BrowserTestUtils.closeWindow(win);
     83      await waitForWindowReadyForPopupNotifications(window);
     84 
     85      goNext();
     86    },
     87  },
     88  // Test that persistent doesn't allow the notification to persist after
     89  // navigation.
     90  {
     91    id: "Test#4",
     92    async run() {
     93      this.oldSelectedTab = gBrowser.selectedTab;
     94      await BrowserTestUtils.openNewForegroundTab(
     95        gBrowser,
     96        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
     97        "http://example.com/"
     98      );
     99      this.notifyObj = new BasicNotification(this.id);
    100      this.notifyObj.addOptions({
    101        persistent: true,
    102      });
    103      this.notification = showNotification(this.notifyObj);
    104    },
    105    async onShown(popup) {
    106      this.complete = false;
    107 
    108      await BrowserTestUtils.loadURIString({
    109        browser: gBrowser.selectedTab.linkedBrowser,
    110        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    111        uriString: "http://example.org/",
    112      });
    113      await BrowserTestUtils.loadURIString({
    114        browser: gBrowser.selectedTab.linkedBrowser,
    115        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    116        uriString: "http://example.com/",
    117      });
    118 
    119      // This code should not be executed.
    120      ok(false, "Should have removed the notification after navigation");
    121      // Properly dismiss and cleanup in case the unthinkable happens.
    122      this.complete = true;
    123      triggerSecondaryCommand(popup, 0);
    124    },
    125    onHidden() {
    126      ok(
    127        !this.complete,
    128        "Should have hidden the notification after navigation"
    129      );
    130      this.notification.remove();
    131      gBrowser.removeTab(gBrowser.selectedTab);
    132      gBrowser.selectedTab = this.oldSelectedTab;
    133    },
    134  },
    135  // Test that persistent allows the notification to persist until explicitly
    136  // dismissed.
    137  {
    138    id: "Test#5",
    139    async run() {
    140      this.oldSelectedTab = gBrowser.selectedTab;
    141      await BrowserTestUtils.openNewForegroundTab(
    142        gBrowser,
    143        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    144        "http://example.com/"
    145      );
    146      this.notifyObj = new BasicNotification(this.id);
    147      this.notifyObj.addOptions({
    148        persistent: true,
    149      });
    150      this.notification = showNotification(this.notifyObj);
    151    },
    152    async onShown(popup) {
    153      this.complete = false;
    154 
    155      // Notification should persist after attempt to dismiss by clicking on the
    156      // content area.
    157      let browser = gBrowser.selectedBrowser;
    158      await BrowserTestUtils.synthesizeMouseAtCenter("body", {}, browser);
    159 
    160      // Notification should be hidden after dismissal via Don't Allow.
    161      this.complete = true;
    162      triggerSecondaryCommand(popup, 0);
    163    },
    164    onHidden() {
    165      ok(
    166        this.complete,
    167        "Should have hidden the notification after clicking Not Now"
    168      );
    169      this.notification.remove();
    170      gBrowser.removeTab(gBrowser.selectedTab);
    171      gBrowser.selectedTab = this.oldSelectedTab;
    172    },
    173  },
    174  // Test that persistent panels are still open after switching to another tab
    175  // and back.
    176  {
    177    id: "Test#6a",
    178    run() {
    179      this.notifyObj = new BasicNotification(this.id);
    180      this.notifyObj.options.persistent = true;
    181      gNotification = showNotification(this.notifyObj);
    182    },
    183    async onShown() {
    184      this.oldSelectedTab = gBrowser.selectedTab;
    185      await BrowserTestUtils.openNewForegroundTab(
    186        gBrowser,
    187        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    188        "http://example.com/"
    189      );
    190    },
    191    onHidden() {
    192      ok(true, "Should have hidden the notification after tab switch");
    193      gBrowser.removeTab(gBrowser.selectedTab);
    194      gBrowser.selectedTab = this.oldSelectedTab;
    195    },
    196  },
    197  // Second part of the previous test that compensates for the limitation in
    198  // runNextTest that expects a single onShown/onHidden invocation per test.
    199  {
    200    id: "Test#6b",
    201    run() {
    202      let id =
    203        PopupNotifications.panel.firstElementChild.getAttribute("popupid");
    204      ok(
    205        id.endsWith("Test#6a"),
    206        "Should have found the notification from Test6a"
    207      );
    208      ok(
    209        PopupNotifications.isPanelOpen,
    210        "Should have shown the popup again after getting back to the tab"
    211      );
    212      gNotification.remove();
    213      gNotification = null;
    214      goNext();
    215    },
    216  },
    217  // Test that persistent panels are still open after switching to another
    218  // window and back.
    219  {
    220    id: "Test#7",
    221    async run() {
    222      this.oldSelectedTab = gBrowser.selectedTab;
    223      await BrowserTestUtils.openNewForegroundTab(
    224        gBrowser,
    225        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    226        "http://example.com/"
    227      );
    228      let firstTab = gBrowser.selectedTab;
    229 
    230      await BrowserTestUtils.openNewForegroundTab(
    231        gBrowser,
    232        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
    233        "http://example.com/"
    234      );
    235 
    236      let shown = waitForNotificationPanel();
    237      let notifyObj = new BasicNotification(this.id);
    238      notifyObj.options.persistent = true;
    239      this.notification = showNotification(notifyObj);
    240      await shown;
    241 
    242      ok(
    243        notifyObj.shownCallbackTriggered,
    244        "Should have triggered the shown event"
    245      );
    246      ok(
    247        notifyObj.showingCallbackTriggered,
    248        "Should have triggered the showing event"
    249      );
    250      // Reset to false so that we can ensure these are not fired a second time.
    251      notifyObj.shownCallbackTriggered = false;
    252      notifyObj.showingCallbackTriggered = false;
    253      let timeShown = this.notification.timeShown;
    254 
    255      let promiseWin = BrowserTestUtils.waitForNewWindow();
    256      gBrowser.replaceTabWithWindow(firstTab);
    257      let win = await promiseWin;
    258 
    259      let anchor = win.document.getElementById("default-notification-icon");
    260      win.PopupNotifications._reshowNotifications(anchor);
    261      ok(
    262        !win.PopupNotifications.panel.children.length,
    263        "no notification displayed in new window"
    264      );
    265 
    266      await BrowserTestUtils.closeWindow(win);
    267      await waitForWindowReadyForPopupNotifications(window);
    268 
    269      let id =
    270        PopupNotifications.panel.firstElementChild.getAttribute("popupid");
    271      ok(
    272        id.endsWith("Test#7"),
    273        "Should have found the notification from Test7"
    274      );
    275      ok(
    276        PopupNotifications.isPanelOpen,
    277        "Should have kept the popup on the first window"
    278      );
    279      ok(
    280        !notifyObj.dismissalCallbackTriggered,
    281        "Should not have triggered a dismissed event"
    282      );
    283      ok(
    284        !notifyObj.shownCallbackTriggered,
    285        "Should not have triggered a second shown event"
    286      );
    287      ok(
    288        !notifyObj.showingCallbackTriggered,
    289        "Should not have triggered a second showing event"
    290      );
    291      Assert.greater(
    292        this.notification.timeShown,
    293        timeShown,
    294        "should have updated timeShown to restart the security delay"
    295      );
    296 
    297      this.notification.remove();
    298      gBrowser.removeTab(gBrowser.selectedTab);
    299      gBrowser.selectedTab = this.oldSelectedTab;
    300 
    301      goNext();
    302    },
    303  },
    304  // Test that only the first persistent notification is shown on update
    305  {
    306    id: "Test#8",
    307    run() {
    308      this.notifyObj1 = new BasicNotification(this.id);
    309      this.notifyObj1.id += "_1";
    310      this.notifyObj1.anchorID = "default-notification-icon";
    311      this.notifyObj1.options.persistent = true;
    312      this.notification1 = showNotification(this.notifyObj1);
    313 
    314      this.notifyObj2 = new BasicNotification(this.id);
    315      this.notifyObj2.id += "_2";
    316      this.notifyObj2.anchorID = "geo-notification-icon";
    317      this.notifyObj2.options.persistent = true;
    318      this.notification2 = showNotification(this.notifyObj2);
    319 
    320      PopupNotifications._update();
    321    },
    322    onShown(popup) {
    323      checkPopup(popup, this.notifyObj1);
    324      this.notification1.remove();
    325      this.notification2.remove();
    326    },
    327    onHidden() {},
    328  },
    329  // Test that persistent notifications are shown stacked by anchor on update
    330  {
    331    id: "Test#9",
    332    run() {
    333      this.notifyObj1 = new BasicNotification(this.id);
    334      this.notifyObj1.id += "_1";
    335      this.notifyObj1.anchorID = "default-notification-icon";
    336      this.notifyObj1.options.persistent = true;
    337      this.notification1 = showNotification(this.notifyObj1);
    338 
    339      this.notifyObj2 = new BasicNotification(this.id);
    340      this.notifyObj2.id += "_2";
    341      this.notifyObj2.anchorID = "geo-notification-icon";
    342      this.notifyObj2.options.persistent = true;
    343      this.notification2 = showNotification(this.notifyObj2);
    344 
    345      this.notifyObj3 = new BasicNotification(this.id);
    346      this.notifyObj3.id += "_3";
    347      this.notifyObj3.anchorID = "default-notification-icon";
    348      this.notifyObj3.options.persistent = true;
    349      this.notification3 = showNotification(this.notifyObj3);
    350 
    351      PopupNotifications._update();
    352    },
    353    onShown(popup) {
    354      let notifications = popup.children;
    355      is(notifications.length, 2, "two notifications displayed");
    356      let [notification1, notification2] = notifications;
    357      is(
    358        notification1.id,
    359        this.notifyObj1.id + "-notification",
    360        "id 1 matches"
    361      );
    362      is(
    363        notification2.id,
    364        this.notifyObj3.id + "-notification",
    365        "id 2 matches"
    366      );
    367 
    368      this.notification1.remove();
    369      this.notification2.remove();
    370      this.notification3.remove();
    371    },
    372    onHidden() {},
    373  },
    374  // Test that on closebutton click, only the persistent notification
    375  // that contained the closebutton loses its persistent status.
    376  {
    377    id: "Test#10",
    378    run() {
    379      this.notifyObj1 = new BasicNotification(this.id);
    380      this.notifyObj1.id += "_1";
    381      this.notifyObj1.anchorID = "geo-notification-icon";
    382      this.notifyObj1.options.persistent = true;
    383      this.notifyObj1.options.hideClose = false;
    384      this.notification1 = showNotification(this.notifyObj1);
    385 
    386      this.notifyObj2 = new BasicNotification(this.id);
    387      this.notifyObj2.id += "_2";
    388      this.notifyObj2.anchorID = "geo-notification-icon";
    389      this.notifyObj2.options.persistent = true;
    390      this.notifyObj2.options.hideClose = false;
    391      this.notification2 = showNotification(this.notifyObj2);
    392 
    393      this.notifyObj3 = new BasicNotification(this.id);
    394      this.notifyObj3.id += "_3";
    395      this.notifyObj3.anchorID = "geo-notification-icon";
    396      this.notifyObj3.options.persistent = true;
    397      this.notifyObj3.options.hideClose = false;
    398      this.notification3 = showNotification(this.notifyObj3);
    399 
    400      PopupNotifications._update();
    401    },
    402    onShown(popup) {
    403      let notifications = popup.children;
    404      is(notifications.length, 3, "three notifications displayed");
    405      EventUtils.synthesizeMouseAtCenter(notifications[1].closebutton, {});
    406    },
    407    onHidden(popup) {
    408      let notifications = popup.children;
    409      is(notifications.length, 2, "two notifications displayed");
    410 
    411      ok(this.notification1.options.persistent, "notification 1 is persistent");
    412      ok(
    413        !this.notification2.options.persistent,
    414        "notification 2 is not persistent"
    415      );
    416      ok(this.notification3.options.persistent, "notification 3 is persistent");
    417 
    418      this.notification1.remove();
    419      this.notification2.remove();
    420      this.notification3.remove();
    421    },
    422  },
    423  // Test clicking the anchor icon.
    424  // Clicking the anchor of an already visible persistent notification should
    425  // focus the main action button, but not cause additional showing/shown event
    426  // callback calls.
    427  // Clicking the anchor of a dismissed notification should show it, even when
    428  // the currently displayed notification is a persistent one.
    429  {
    430    id: "Test#11",
    431    async run() {
    432      await SpecialPowers.pushPrefEnv({ set: [["accessibility.tabfocus", 7]] });
    433 
    434      function clickAnchor(notifyObj) {
    435        let anchor = document.getElementById(notifyObj.anchorID);
    436        EventUtils.synthesizeMouseAtCenter(anchor, {});
    437      }
    438 
    439      let popup = PopupNotifications.panel;
    440 
    441      let notifyObj1 = new BasicNotification(this.id);
    442      notifyObj1.id += "_1";
    443      notifyObj1.anchorID = "default-notification-icon";
    444      notifyObj1.options.persistent = true;
    445      let shown = waitForNotificationPanel();
    446      let notification1 = showNotification(notifyObj1);
    447      await shown;
    448      checkPopup(popup, notifyObj1);
    449      ok(
    450        !notifyObj1.dismissalCallbackTriggered,
    451        "Should not have dismissed the notification"
    452      );
    453      notifyObj1.shownCallbackTriggered = false;
    454      notifyObj1.showingCallbackTriggered = false;
    455 
    456      // Click the anchor. This should focus the closebutton
    457      // (because it's the first focusable element), but not
    458      // call event callbacks on the notification object.
    459      clickAnchor(notifyObj1);
    460      is(document.activeElement, popup.children[0].closebutton);
    461      ok(
    462        !notifyObj1.dismissalCallbackTriggered,
    463        "Should not have dismissed the notification"
    464      );
    465      ok(
    466        !notifyObj1.shownCallbackTriggered,
    467        "Should have triggered the shown event again"
    468      );
    469      ok(
    470        !notifyObj1.showingCallbackTriggered,
    471        "Should have triggered the showing event again"
    472      );
    473 
    474      // Add another notification.
    475      let notifyObj2 = new BasicNotification(this.id);
    476      notifyObj2.id += "_2";
    477      notifyObj2.anchorID = "geo-notification-icon";
    478      notifyObj2.options.dismissed = true;
    479      let notification2 = showNotification(notifyObj2);
    480 
    481      // Click the anchor of the second notification, this should dismiss the
    482      // first notification.
    483      shown = waitForNotificationPanel();
    484      clickAnchor(notifyObj2);
    485      await shown;
    486      checkPopup(popup, notifyObj2);
    487      ok(
    488        notifyObj1.dismissalCallbackTriggered,
    489        "Should have dismissed the first notification"
    490      );
    491 
    492      // Click the anchor of the first notification, it should be shown again.
    493      shown = waitForNotificationPanel();
    494      clickAnchor(notifyObj1);
    495      await shown;
    496      checkPopup(popup, notifyObj1);
    497      ok(
    498        notifyObj2.dismissalCallbackTriggered,
    499        "Should have dismissed the second notification"
    500      );
    501 
    502      // Cleanup.
    503      notification1.remove();
    504      notification2.remove();
    505      goNext();
    506    },
    507  },
    508 ];