text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include <string>
  
  #include "base/bind.h"
  #include "base/callback.h"
  #include "base/command_line.h"
  #include "base/compiler_specific.h"
  #include "base/memory/ref_counted.h"
  #include "base/strings/stringprintf.h"
  #include "base/strings/utf_string_conversions.h"
  #include "base/test/simple_test_clock.h"
  #include "base/time/clock.h"
  #include "build/build_config.h"
  #include "build/chromeos_buildflags.h"
  #include "chrome/browser/browser_process.h"
  #include "chrome/browser/history/history_service_factory.h"
  #include "chrome/browser/infobars/infobar_service.h"
  #include "chrome/browser/notifications/notification_interactive_uitest_support.h"
  #include "chrome/browser/notifications/notification_test_util.h"
  #include "chrome/browser/profiles/profile.h"
  #include "chrome/browser/ui/browser.h"
  #include "chrome/browser/ui/browser_commands.h"
  #include "chrome/browser/ui/browser_tabstrip.h"
  #include "chrome/browser/ui/browser_window.h"
  #include "chrome/browser/ui/exclusive_access/exclusive_access_context.h"
  #include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
  #include "chrome/browser/ui/tabs/tab_strip_model.h"
  #include "chrome/common/chrome_switches.h"
  #include "chrome/grit/generated_resources.h"
  #include "chrome/test/base/interactive_test_utils.h"
  #include "chrome/test/base/ui_test_utils.h"
  #include "components/content_settings/core/common/content_settings_pattern.h"
  #include "components/history/core/browser/history_service.h"
  #include "components/permissions/permission_uma_util.h"
  #include "components/ukm/test_ukm_recorder.h"
  #include "content/public/browser/notification_service.h"
  #include "content/public/browser/notification_source.h"
  #include "content/public/browser/notification_types.h"
  #include "content/public/browser/render_view_host.h"
  #include "content/public/browser/web_contents.h"
  #include "content/public/test/browser_test.h"
  #include "content/public/test/browser_test_utils.h"
  #include "media/base/media_switches.h"
  #include "net/test/embedded_test_server/embedded_test_server.h"
  #include "testing/gtest/include/gtest/gtest.h"
  #include "ui/base/l10n/l10n_util.h"
  #include "ui/base/window_open_disposition.h"
  #include "ui/message_center/message_center.h"
  #include "ui/message_center/notification_blocker.h"
  #include "ui/message_center/public/cpp/message_center_constants.h"
  #include "ui/message_center/public/cpp/notification.h"
  #include "url/gurl.h"
  
  #if defined(OS_MAC)
  #include "base/mac/mac_util.h"
  #include "ui/base/test/scoped_fake_nswindow_fullscreen.h"
  #endif
  
  namespace {
  
  class ToggledNotificationBlocker : public message_center::NotificationBlocker {
   public:
    ToggledNotificationBlocker()
        : message_center::NotificationBlocker(
              message_center::MessageCenter::Get()),
          notifications_enabled_(true) {}
    ToggledNotificationBlocker(const ToggledNotificationBlocker&) = delete;
    ToggledNotificationBlocker& operator=(const ToggledNotificationBlocker&) =
        delete;
    ~ToggledNotificationBlocker() override {}
  
    void SetNotificationsEnabled(bool enabled) {
      if (notifications_enabled_ != enabled) {
        notifications_enabled_ = enabled;
        NotifyBlockingStateChanged();
      }
    }
  
    // NotificationBlocker overrides:
    bool ShouldShowNotificationAsPopup(
        const message_center::Notification& notification) const override {
      return notifications_enabled_;
    }
  
   private:
    bool notifications_enabled_;
  };
  
  #if !defined(OS_ANDROID)
  // Browser test class that creates a fake monitor MediaStream device and auto
  // selects it when requesting one via navigator.mediaDevices.getDisplayMedia().
  class NotificationsTestWithFakeMediaStream : public NotificationsTest {
   public:
    NotificationsTestWithFakeMediaStream() = default;
    ~NotificationsTestWithFakeMediaStream() override = default;
  
    // InProcessBrowserTest:
    void SetUpCommandLine(base::CommandLine* command_line) override {
      NotificationsTest::SetUpCommandLine(command_line);
      command_line->RemoveSwitch(switches::kUseFakeDeviceForMediaStream);
      command_line->AppendSwitchASCII(switches::kUseFakeDeviceForMediaStream,
                                      "display-media-type=monitor");
      command_line->AppendSwitchASCII(switches::kAutoSelectDesktopCaptureSource,
                                      "Entire screen");
    }
  };
  #endif  // !defined(OS_ANDROID)
  
  }  // namespace
  
  namespace {
  
  const char kExpectedIconUrl[] = "/notifications/no_such_file.png";
  
  }  // namespace
  
  // Flaky on Windows, Mac, Linux: http://crbug.com/437414.
  IN_PROC_BROWSER_TEST_F(NotificationsTest, DISABLED_TestUserGestureInfobar) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    ui_test_utils::NavigateToURL(
        browser(),
        embedded_test_server()->GetURL(
            "/notifications/notifications_request_function.html"));
  
    // Request permission by calling request() while eval'ing an inline script;
    // That's considered a user gesture to webkit, and should produce an infobar.
    bool result;
    ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
        GetActiveWebContents(browser()),
        "window.domAutomationController.send(request());", &result));
    EXPECT_TRUE(result);
  
    InfoBarService* infobar_service = InfoBarService::FromWebContents(
        browser()->tab_strip_model()->GetWebContentsAt(0));
    EXPECT_EQ(1U, infobar_service->infobar_count());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCreateSimpleNotification) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Creates a simple notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    GURL EXPECTED_ICON_URL = embedded_test_server()->GetURL(kExpectedIconUrl);
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    EXPECT_EQ(u"My Title", (*notifications.rbegin())->title());
    EXPECT_EQ(u"My Body", (*notifications.rbegin())->message());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, NotificationBlockerTest) {
    ToggledNotificationBlocker blocker;
    TestMessageCenterObserver observer;
  
    ASSERT_TRUE(embedded_test_server()->Start());
    message_center::MessageCenter::Get()->AddObserver(&observer);
  
    // Creates a simple notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    EXPECT_EQ(0, GetNotificationPopupCount());
    blocker.SetNotificationsEnabled(false);
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
    EXPECT_EQ(0, GetNotificationPopupCount());
    EXPECT_EQ("", observer.last_displayed_id());
  
    blocker.SetNotificationsEnabled(true);
    EXPECT_EQ(1, GetNotificationPopupCount());
    EXPECT_NE("", observer.last_displayed_id());
  
    result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
    result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    blocker.SetNotificationsEnabled(false);
    EXPECT_EQ(0, GetNotificationPopupCount());
  
    message_center::MessageCenter::Get()->RemoveObserver(&observer);
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseNotification) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Creates a notification and closes it.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
    ASSERT_EQ(1, GetNotificationCount());
  
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    message_center::MessageCenter::Get()->RemoveNotification(
        (*notifications.rbegin())->id(),
        true);  // by_user
  
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCancelNotification) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Creates a notification and cancels it in the origin page.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string note_id = CreateSimpleNotification(browser(), true);
    EXPECT_NE(note_id, "-1");
  
    ASSERT_EQ(1, GetNotificationCount());
    ASSERT_TRUE(CancelNotification(note_id.c_str(), browser()));
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  // Requests notification privileges and verifies the prompt appears.
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestPermissionRequestUIAppears) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    EXPECT_TRUE(RequestPermissionAndWait(browser()));
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowOnPermissionRequestUI) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Tries to create a notification & clicks 'allow' on the prompt.
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    // This notification should not be shown because we do not have permission.
    CreateSimpleNotification(browser(), false);
    ASSERT_EQ(0, GetNotificationCount());
  
    ASSERT_TRUE(RequestAndAcceptPermission(browser()));
  
    CreateSimpleNotification(browser(), true);
    EXPECT_EQ(1, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyOnPermissionRequestUI) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that no notification is created when Deny is chosen from prompt.
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    ASSERT_TRUE(RequestAndDenyPermission(browser()));
    CreateSimpleNotification(browser(), false);
    ASSERT_EQ(0, GetNotificationCount());
    ContentSettingsForOneType settings;
    GetDisabledContentSettings(&settings);
    EXPECT_TRUE(CheckOriginInSetting(settings, GetTestPageURL()));
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestClosePermissionRequestUI) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that no notification is created when prompt is dismissed.
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    ASSERT_TRUE(RequestAndDismissPermission(browser()));
    CreateSimpleNotification(browser(), false);
    ASSERT_EQ(0, GetNotificationCount());
    ContentSettingsForOneType settings;
    GetDisabledContentSettings(&settings);
    EXPECT_EQ(0U, settings.size());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestPermissionAPI) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that Notification.permission returns the right thing.
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    EXPECT_EQ("default", QueryPermissionStatus(browser()));
  
    AllowOrigin(GetTestPageURL().GetOrigin());
    EXPECT_EQ("granted", QueryPermissionStatus(browser()));
  
    DenyOrigin(GetTestPageURL().GetOrigin());
    EXPECT_EQ("denied", QueryPermissionStatus(browser()));
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTestWithPermissionsEmbargo,
                         TestPermissionEmbargo) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    // Verify embargo behaviour - automatically blocked after 3 dismisses.
    ASSERT_TRUE(RequestAndDismissPermission(browser()));
    EXPECT_EQ("default", QueryPermissionStatus(browser()));
  
    ASSERT_TRUE(RequestAndDismissPermission(browser()));
    EXPECT_EQ("default", QueryPermissionStatus(browser()));
  
    ASSERT_TRUE(RequestAndDismissPermission(browser()));
    EXPECT_EQ("denied", QueryPermissionStatus(browser()));
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowNotificationsFromAllSites) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify that all domains can be allowed to show notifications.
    SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyNotificationsFromAllSites) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify that no domain can show notifications.
    SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), false);
    EXPECT_EQ("-1", result);
  
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyDomainAndAllowAll) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify that denying a domain and allowing all shouldn't show
    // notifications from the denied domain.
    DenyOrigin(GetTestPageURL().GetOrigin());
    SetDefaultContentSetting(CONTENT_SETTING_ALLOW);
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), false);
    EXPECT_EQ("-1", result);
  
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestAllowDomainAndDenyAll) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify that allowing a domain and denying all others should show
    // notifications from the allowed domain.
    AllowOrigin(GetTestPageURL().GetOrigin());
    SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestDenyAndThenAllowDomain) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify that denying and again allowing should show notifications.
    DenyOrigin(GetTestPageURL().GetOrigin());
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), false);
    EXPECT_EQ("-1", result);
  
    ASSERT_EQ(0, GetNotificationCount());
  
    AllowOrigin(GetTestPageURL().GetOrigin());
    result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, InlinePermissionRevokeUkm) {
    ASSERT_TRUE(embedded_test_server()->Start());
    ukm::TestAutoSetUkmRecorder ukm_recorder;
  
    // Verify able to create, deny, and close the notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    Profile* profile = Profile::FromBrowserContext(browser()
                                                       ->tab_strip_model()
                                                       ->GetActiveWebContents()
                                                       ->GetBrowserContext());
    history::HistoryService* history_service =
        HistoryServiceFactory::GetForProfile(profile,
                                             ServiceAccessType::EXPLICIT_ACCESS);
    base::RunLoop origin_queried_waiter;
    history_service->set_origin_queried_closure_for_testing(
        origin_queried_waiter.QuitClosure());
  
    CreateSimpleNotification(browser(), true);
    ASSERT_EQ(1, GetNotificationCount());
  
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    message_center::MessageCenter::Get()->DisableNotification(
        (*notifications.rbegin())->id());
  
    origin_queried_waiter.Run();
  
    auto entries = ukm_recorder.GetEntriesByName("Permission");
    EXPECT_EQ(1u, entries.size());
    auto* entry = entries.front();
  
    ukm_recorder.ExpectEntrySourceHasUrl(entry,
                                         embedded_test_server()->base_url());
    EXPECT_EQ(
        *ukm_recorder.GetEntryMetric(entry, "Source"),
        static_cast<int64_t>(permissions::PermissionSourceUI::INLINE_SETTINGS));
    size_t num_values = 0;
    EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "PermissionType"),
              ContentSettingTypeToHistogramValue(
                  ContentSettingsType::NOTIFICATIONS, &num_values));
    EXPECT_EQ(*ukm_recorder.GetEntryMetric(entry, "Action"),
              static_cast<int64_t>(permissions::PermissionAction::REVOKED));
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCreateDenyCloseNotifications) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Verify able to create, deny, and close the notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    CreateSimpleNotification(browser(), true);
    ASSERT_EQ(1, GetNotificationCount());
  
    DenyOrigin(GetTestPageURL().GetOrigin());
    ContentSettingsForOneType settings;
    GetDisabledContentSettings(&settings);
    ASSERT_TRUE(CheckOriginInSetting(settings, GetTestPageURL().GetOrigin()));
  
    EXPECT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    message_center::MessageCenter::Get()->RemoveNotification(
        (*notifications.rbegin())->id(),
        true);  // by_user
    ASSERT_EQ(0, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestCloseTabWithPermissionRequestUI) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that user can close tab when bubble present.
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    EXPECT_TRUE(RequestPermissionAndWait(browser()));
    content::WebContentsDestroyedWatcher destroyed_watcher(
        browser()->tab_strip_model()->GetWebContentsAt(0));
    browser()->tab_strip_model()->CloseWebContentsAt(0,
                                                     TabStripModel::CLOSE_NONE);
    destroyed_watcher.Wait();
  }
  
  // See crbug.com/248470
  #if defined(OS_LINUX) || defined(OS_CHROMEOS)
  #define MAYBE_TestCrashRendererNotificationRemain \
      DISABLED_TestCrashRendererNotificationRemain
  #else
  #define MAYBE_TestCrashRendererNotificationRemain \
      TestCrashRendererNotificationRemain
  #endif
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest,
                         MAYBE_TestCrashRendererNotificationRemain) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test crashing renderer does not close or crash notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURLWithDisposition(
        browser(), GURL("about:blank"), WindowOpenDisposition::NEW_BACKGROUND_TAB,
        ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB);
    browser()->tab_strip_model()->ActivateTabAt(
        0, {TabStripModel::GestureType::kOther});
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    CreateSimpleNotification(browser(), true);
    ASSERT_EQ(1, GetNotificationCount());
    CrashTab(browser(), 0);
    ASSERT_EQ(1, GetNotificationCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNotificationReplacement) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that we can replace a notification using the replaceId.
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateNotification(
        browser(), true, "abc.png", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
  
    result = CreateNotification(
        browser(), false, "no_such_file.png", "Title2", "Body2", "chat");
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    EXPECT_EQ(u"Title2", (*notifications.rbegin())->title());
    EXPECT_EQ(u"Body2", (*notifications.rbegin())->message());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest,
                         TestNotificationReplacementReappearance) {
    message_center::MessageCenter::Get()->SetHasMessageCenterView(false);
  
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Test that we can replace a notification using the tag, and that it will
    // cause the notification to reappear as a popup again.
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    ASSERT_EQ(0, GetNotificationPopupCount());
  
    std::string result = CreateNotification(
        browser(), true, "abc.png", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationPopupCount());
  
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    message_center::MessageCenter::Get()->ClickOnNotification(
        (*notifications.rbegin())->id());
  
    ASSERT_EQ(1, GetNotificationPopupCount());
  
    result = CreateNotification(
        browser(), true, "abc.png", "Title2", "Body2", "chat");
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationPopupCount());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNotificationValidIcon) {
    ASSERT_TRUE(embedded_test_server()->Start());
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    ASSERT_EQ(0, GetNotificationPopupCount());
  
    std::string result = CreateNotification(
        browser(), true, "icon.png", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    message_center::NotificationList::PopupNotifications notifications =
        message_center::MessageCenter::Get()->GetPopupNotifications();
    ASSERT_EQ(1u, notifications.size());
  
    auto* notification = *notifications.rbegin();
  
    EXPECT_EQ(100, notification->icon().Width());
    EXPECT_EQ(100, notification->icon().Height());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNotificationInvalidIcon) {
    ASSERT_TRUE(embedded_test_server()->Start());
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    ASSERT_EQ(0, GetNotificationPopupCount());
  
    // Not supplying an icon URL.
    std::string result = CreateNotification(
        browser(), true, "", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    message_center::NotificationList::PopupNotifications notifications =
        message_center::MessageCenter::Get()->GetPopupNotifications();
    ASSERT_EQ(1u, notifications.size());
  
    auto* notification = *notifications.rbegin();
    EXPECT_TRUE(notification->icon().IsEmpty());
  
    // Supplying an invalid icon URL.
    result = CreateNotification(
        browser(), true, "invalid.png", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    notifications = message_center::MessageCenter::Get()->GetPopupNotifications();
    ASSERT_EQ(1u, notifications.size());
  
    notification = *notifications.rbegin();
    EXPECT_TRUE(notification->icon().IsEmpty());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestNotificationDoubleClose) {
    ASSERT_TRUE(embedded_test_server()->Start());
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(
        browser(), GetTestPageURLForFile("notification-double-close.html"));
    ASSERT_EQ(0, GetNotificationPopupCount());
  
    std::string result = CreateNotification(
        browser(), true, "", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    message_center::MessageCenter::Get()->RemoveNotification(
        (*notifications.rbegin())->id(),
        true);  // by_user
  
    ASSERT_EQ(0, GetNotificationCount());
  
    // Calling WebContents::IsCrashed() will return FALSE here, even if the WC did
    // crash. Work around this timing issue by creating another notification,
    // which requires interaction with the renderer process.
    result = CreateNotification(browser(), true, "", "Title1", "Body1", "chat");
    EXPECT_NE("-1", result);
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayNormal) {
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Creates a simple notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
  
    // Because the webpage is not fullscreen, there will be no special fullscreen
    // visibility tagged on the notification.
    EXPECT_EQ(message_center::FullscreenVisibility::NONE,
              (*notifications.rbegin())->fullscreen_visibility());
  }
  
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayFullscreen) {
  #if defined(OS_MAC)
    ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen;
  #endif
    ASSERT_TRUE(embedded_test_server()->Start());
  
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    // Set the page fullscreen
    browser()->exclusive_access_manager()->fullscreen_controller()->
        ToggleBrowserFullscreenMode();
  
    {
      FullscreenStateWaiter fs_state(browser(), true);
      fs_state.Wait();
    }
  
    ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
        browser()->window()->GetNativeWindow()));
  
    ASSERT_TRUE(browser()->window()->IsActive());
  
    // Creates a simple notification.
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
  
    // Because the webpage is fullscreen, the fullscreen bit will be set.
    EXPECT_EQ(message_center::FullscreenVisibility::OVER_USER,
              (*notifications.rbegin())->fullscreen_visibility());
  }
  
  // The Fake OSX fullscreen window doesn't like drawing a second fullscreen
  // window when another is visible.
  #if !defined(OS_MAC)
  // Disabled on other platforms because it is flaky.  http://crbug.com/1195324
  IN_PROC_BROWSER_TEST_F(NotificationsTest, DISABLED_TestShouldDisplayMultiFullscreen) {
    ASSERT_TRUE(embedded_test_server()->Start());
    AllowAllOrigins();
  
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    Browser* other_browser = CreateBrowser(browser()->profile());
    ui_test_utils::NavigateToURL(other_browser, GURL("about:blank"));
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    // Set the notification page fullscreen
    browser()->exclusive_access_manager()->fullscreen_controller()->
        ToggleBrowserFullscreenMode();
    {
      FullscreenStateWaiter fs_state(browser(), true);
      fs_state.Wait();
    }
  
    // Set the other browser fullscreen
    other_browser->exclusive_access_manager()->fullscreen_controller()->
        ToggleBrowserFullscreenMode();
    {
      FullscreenStateWaiter fs_state(other_browser, true);
      fs_state.Wait();
    }
  
    ASSERT_TRUE(browser()->exclusive_access_manager()->context()->IsFullscreen());
    ASSERT_TRUE(
        other_browser->exclusive_access_manager()->context()->IsFullscreen());
  
    ASSERT_FALSE(browser()->window()->IsActive());
    ASSERT_TRUE(other_browser->window()->IsActive());
  
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    // Because the second page is the top-most fullscreen, the fullscreen bit
    // won't be set.
    EXPECT_EQ(message_center::FullscreenVisibility::NONE,
              (*notifications.rbegin())->fullscreen_visibility());
  }
  #endif
  
  // Verify that a notification is actually displayed when the webpage that
  // creates it is fullscreen with the fullscreen notification flag turned on.
  IN_PROC_BROWSER_TEST_F(NotificationsTest, TestShouldDisplayPopupNotification) {
  #if defined(OS_MAC)
    ui::test::ScopedFakeNSWindowFullscreen fake_fullscreen;
  #endif
    ASSERT_TRUE(embedded_test_server()->Start());
  
    // Creates a simple notification.
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
  
    // Set the page fullscreen
    browser()->exclusive_access_manager()->fullscreen_controller()->
        ToggleBrowserFullscreenMode();
  
    {
      FullscreenStateWaiter fs_state(browser(), true);
      fs_state.Wait();
    }
  
    ASSERT_TRUE(ui_test_utils::ShowAndFocusNativeWindow(
        browser()->window()->GetNativeWindow()));
  
    std::string result = CreateSimpleNotification(browser(), true);
    EXPECT_NE("-1", result);
  
    ASSERT_EQ(1, GetNotificationCount());
    message_center::NotificationList::PopupNotifications notifications =
        message_center::MessageCenter::Get()->GetPopupNotifications();
    ASSERT_EQ(1u, notifications.size());
  }
  
  #if !defined(OS_ANDROID)
  // TODO(knollr): Test fails on Windows and macOS on the bots as there is no real
  // display to test with. Need to find a way to run these without a display and
  // figure out why Lacros is timing out. Tests pass locally with a real display.
  #if defined(OS_MAC) || defined(OS_WIN) || BUILDFLAG(IS_CHROMEOS_LACROS)
  #define MAYBE_ShouldQueueDuringScreenPresent \
    DISABLED_ShouldQueueDuringScreenPresent
  #else
  #define MAYBE_ShouldQueueDuringScreenPresent ShouldQueueDuringScreenPresent
  #endif
  IN_PROC_BROWSER_TEST_F(NotificationsTestWithFakeMediaStream,
                         MAYBE_ShouldQueueDuringScreenPresent) {
    ASSERT_TRUE(embedded_test_server()->Start());
    // Start second server so we can test screen recording on secure connections.
    net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
    https_server.ServeFilesFromSourceDirectory(GetChromeTestDataDir());
    ASSERT_TRUE(https_server.Start());
  
    AllowAllOrigins();
    ui_test_utils::NavigateToURL(browser(), GetTestPageURL());
    const int notification_tab = browser()->tab_strip_model()->active_index();
  
    // We should see displayed notifications by default.
    std::string result = CreateSimpleNotification(browser(), /*wait=*/false);
    EXPECT_NE("-1", result);
    message_center::NotificationList::Notifications notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    ASSERT_EQ(1u, notifications.size());
    EXPECT_EQ(u"My Title", (*notifications.begin())->title());
    EXPECT_EQ(u"My Body", (*notifications.begin())->message());
  
    // Open a new tab to a diffent origin from the one that shows notifications.
    chrome::NewTab(browser());
    ui_test_utils::NavigateToURL(
        browser(),
        https_server.GetURL("/notifications/notification_tester.html"));
    const int screen_capture_tab = browser()->tab_strip_model()->active_index();
  
    // Start a screen capture session.
    content::WebContents* web_contents = GetActiveWebContents(browser());
    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
        web_contents, "startScreenCapture();", &result));
    ASSERT_EQ("success", result);
  
    // Showing a notification during the screen capture session should show the
    // "Notifications muted" notification.
    browser()->tab_strip_model()->ActivateTabAt(notification_tab);
    result = CreateSimpleNotification(browser(), /*wait=*/false);
    EXPECT_NE("-1", result);
    notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    ASSERT_EQ(2u, notifications.size());
    EXPECT_EQ(l10n_util::GetPluralStringFUTF16(IDS_NOTIFICATION_MUTED_TITLE,
                                               /*count=*/1),
              (*notifications.begin())->title());
    EXPECT_EQ(l10n_util::GetStringUTF16(IDS_NOTIFICATION_MUTED_MESSAGE),
              (*notifications.begin())->message());
  
    // Showing another notification during the screen captuure session should
    // update the "Notifications muted" notification title.
    result = CreateSimpleNotification(browser(), /*wait=*/false);
    EXPECT_NE("-1", result);
    notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    ASSERT_EQ(2u, notifications.size());
    EXPECT_EQ(l10n_util::GetPluralStringFUTF16(IDS_NOTIFICATION_MUTED_TITLE,
                                               /*count=*/2),
              (*notifications.begin())->title());
    EXPECT_EQ(l10n_util::GetStringUTF16(IDS_NOTIFICATION_MUTED_MESSAGE),
              (*notifications.begin())->message());
  
    // Stop the screen capture session.
    browser()->tab_strip_model()->ActivateTabAt(screen_capture_tab);
    EXPECT_TRUE(content::ExecuteScriptAndExtractString(
        web_contents, "stopScreenCapture();", &result));
    ASSERT_EQ("success", result);
  
    // Stopping the screen capture session should display the queued notifications
    // and close the "Notifications muted" notification.
    notifications =
        message_center::MessageCenter::Get()->GetVisibleNotifications();
    ASSERT_EQ(3u, notifications.size());
    for (const auto* notification : notifications) {
      EXPECT_EQ(u"My Title", notification->title());
      EXPECT_EQ(u"My Body", notification->message());
    }
  }
  #endif  // !defined(OS_ANDROID)
  