123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- // 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 "components/web_modal/web_contents_modal_dialog_manager.h"
- #include <map>
- #include <memory>
- #include "base/memory/ptr_util.h"
- #include "base/memory/raw_ptr.h"
- #include "build/build_config.h"
- #include "components/web_modal/single_web_contents_dialog_manager.h"
- #include "components/web_modal/test_web_contents_modal_dialog_manager_delegate.h"
- #include "content/public/test/test_renderer_host.h"
- #include "testing/gtest/include/gtest/gtest.h"
- namespace web_modal {
- // Tracks persistent state changes of the native WC-modal dialog manager.
- class NativeManagerTracker {
- public:
- enum DialogState {
- UNKNOWN,
- NOT_SHOWN,
- SHOWN,
- HIDDEN,
- CLOSED
- };
- NativeManagerTracker() : state_(UNKNOWN), was_shown_(false) {}
- void SetState(DialogState state) {
- state_ = state;
- if (state_ == SHOWN)
- was_shown_ = true;
- }
- DialogState state_;
- bool was_shown_;
- };
- NativeManagerTracker unused_tracker;
- class TestNativeWebContentsModalDialogManager
- : public SingleWebContentsDialogManager {
- public:
- TestNativeWebContentsModalDialogManager(
- gfx::NativeWindow dialog,
- SingleWebContentsDialogManagerDelegate* delegate,
- NativeManagerTracker* tracker)
- : delegate_(delegate),
- dialog_(dialog),
- tracker_(tracker) {
- if (tracker_)
- tracker_->SetState(NativeManagerTracker::NOT_SHOWN);
- }
- TestNativeWebContentsModalDialogManager(
- const TestNativeWebContentsModalDialogManager&) = delete;
- TestNativeWebContentsModalDialogManager& operator=(
- const TestNativeWebContentsModalDialogManager&) = delete;
- void Show() override {
- if (tracker_)
- tracker_->SetState(NativeManagerTracker::SHOWN);
- }
- void Hide() override {
- if (tracker_)
- tracker_->SetState(NativeManagerTracker::HIDDEN);
- }
- void Close() override {
- if (tracker_)
- tracker_->SetState(NativeManagerTracker::CLOSED);
- delegate_->WillClose(dialog_);
- }
- void Focus() override {}
- void Pulse() override {}
- void HostChanged(WebContentsModalDialogHost* new_host) override {}
- gfx::NativeWindow dialog() override { return dialog_; }
- void StopTracking() { tracker_ = nullptr; }
- private:
- raw_ptr<SingleWebContentsDialogManagerDelegate> delegate_;
- gfx::NativeWindow dialog_;
- raw_ptr<NativeManagerTracker> tracker_;
- };
- class WebContentsModalDialogManagerTest
- : public content::RenderViewHostTestHarness {
- public:
- WebContentsModalDialogManagerTest() : next_dialog_id(1), manager(nullptr) {}
- WebContentsModalDialogManagerTest(const WebContentsModalDialogManagerTest&) =
- delete;
- WebContentsModalDialogManagerTest& operator=(
- const WebContentsModalDialogManagerTest&) = delete;
- void SetUp() override {
- content::RenderViewHostTestHarness::SetUp();
- delegate = std::make_unique<TestWebContentsModalDialogManagerDelegate>();
- WebContentsModalDialogManager::CreateForWebContents(web_contents());
- manager = WebContentsModalDialogManager::FromWebContents(web_contents());
- manager->SetDelegate(delegate.get());
- test_api =
- std::make_unique<WebContentsModalDialogManager::TestApi>(manager);
- }
- void TearDown() override {
- test_api.reset();
- content::RenderViewHostTestHarness::TearDown();
- }
- protected:
- gfx::NativeWindow MakeFakeDialog() {
- // WebContentsModalDialogManager treats the dialog window as an opaque
- // type, so creating fake dialog windows using reinterpret_cast is valid.
- #if BUILDFLAG(IS_APPLE)
- NSWindow* window = reinterpret_cast<NSWindow*>(next_dialog_id++);
- return gfx::NativeWindow(window);
- #else
- return reinterpret_cast<gfx::NativeWindow>(next_dialog_id++);
- #endif
- }
- int next_dialog_id;
- std::unique_ptr<TestWebContentsModalDialogManagerDelegate> delegate;
- raw_ptr<WebContentsModalDialogManager> manager;
- std::unique_ptr<WebContentsModalDialogManager::TestApi> test_api;
- };
- // Test that the dialog is shown immediately when the delegate indicates the web
- // contents is visible.
- TEST_F(WebContentsModalDialogManagerTest, WebContentsVisible) {
- // Dialog should be shown while WebContents is visible.
- const gfx::NativeWindow dialog = MakeFakeDialog();
- NativeManagerTracker tracker;
- TestNativeWebContentsModalDialogManager* native_manager =
- new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
- manager->ShowDialogWithManager(dialog, base::WrapUnique(native_manager));
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_TRUE(tracker.was_shown_);
- native_manager->StopTracking();
- }
- // Test that the dialog is not shown immediately when the delegate indicates the
- // web contents is not visible.
- TEST_F(WebContentsModalDialogManagerTest, WebContentsNotVisible) {
- // Dialog should not be shown while WebContents is not visible.
- delegate->set_web_contents_visible(false);
- const gfx::NativeWindow dialog = MakeFakeDialog();
- NativeManagerTracker tracker;
- TestNativeWebContentsModalDialogManager* native_manager =
- new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
- manager->ShowDialogWithManager(dialog, base::WrapUnique(native_manager));
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker.state_);
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_FALSE(tracker.was_shown_);
- native_manager->StopTracking();
- }
- // Test that only the first of multiple dialogs is shown.
- TEST_F(WebContentsModalDialogManagerTest, ShowDialogs) {
- const gfx::NativeWindow dialog1 = MakeFakeDialog();
- const gfx::NativeWindow dialog2 = MakeFakeDialog();
- const gfx::NativeWindow dialog3 = MakeFakeDialog();
- NativeManagerTracker tracker1;
- NativeManagerTracker tracker2;
- NativeManagerTracker tracker3;
- TestNativeWebContentsModalDialogManager* native_manager1 =
- new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
- TestNativeWebContentsModalDialogManager* native_manager2 =
- new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
- TestNativeWebContentsModalDialogManager* native_manager3 =
- new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
- manager->ShowDialogWithManager(dialog1, base::WrapUnique(native_manager1));
- manager->ShowDialogWithManager(dialog2, base::WrapUnique(native_manager2));
- manager->ShowDialogWithManager(dialog3, base::WrapUnique(native_manager3));
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker1.state_);
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker2.state_);
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
- native_manager1->StopTracking();
- native_manager2->StopTracking();
- native_manager3->StopTracking();
- }
- // Test that the dialog is shown/hidden when the WebContents is shown/hidden.
- TEST_F(WebContentsModalDialogManagerTest, VisibilityObservation) {
- const gfx::NativeWindow dialog = MakeFakeDialog();
- NativeManagerTracker tracker;
- TestNativeWebContentsModalDialogManager* native_manager =
- new TestNativeWebContentsModalDialogManager(dialog, manager, &tracker);
- manager->ShowDialogWithManager(dialog, base::WrapUnique(native_manager));
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
- test_api->WebContentsVisibilityChanged(content::Visibility::HIDDEN);
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::HIDDEN, tracker.state_);
- test_api->WebContentsVisibilityChanged(content::Visibility::VISIBLE);
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker.state_);
- native_manager->StopTracking();
- }
- // Test that the first dialog is always shown, regardless of the order in which
- // dialogs are closed.
- TEST_F(WebContentsModalDialogManagerTest, CloseDialogs) {
- // The front dialog is always shown regardless of dialog close order.
- const gfx::NativeWindow dialog1 = MakeFakeDialog();
- const gfx::NativeWindow dialog2 = MakeFakeDialog();
- const gfx::NativeWindow dialog3 = MakeFakeDialog();
- const gfx::NativeWindow dialog4 = MakeFakeDialog();
- NativeManagerTracker tracker1;
- NativeManagerTracker tracker2;
- NativeManagerTracker tracker3;
- NativeManagerTracker tracker4;
- TestNativeWebContentsModalDialogManager* native_manager1 =
- new TestNativeWebContentsModalDialogManager(dialog1, manager, &tracker1);
- TestNativeWebContentsModalDialogManager* native_manager2 =
- new TestNativeWebContentsModalDialogManager(dialog2, manager, &tracker2);
- TestNativeWebContentsModalDialogManager* native_manager3 =
- new TestNativeWebContentsModalDialogManager(dialog3, manager, &tracker3);
- TestNativeWebContentsModalDialogManager* native_manager4 =
- new TestNativeWebContentsModalDialogManager(dialog4, manager, &tracker4);
- manager->ShowDialogWithManager(dialog1, base::WrapUnique(native_manager1));
- manager->ShowDialogWithManager(dialog2, base::WrapUnique(native_manager2));
- manager->ShowDialogWithManager(dialog3, base::WrapUnique(native_manager3));
- manager->ShowDialogWithManager(dialog4, base::WrapUnique(native_manager4));
- native_manager1->Close();
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker3.state_);
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
- native_manager3->Close();
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker2.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
- EXPECT_EQ(NativeManagerTracker::NOT_SHOWN, tracker4.state_);
- EXPECT_FALSE(tracker3.was_shown_);
- native_manager2->Close();
- EXPECT_TRUE(manager->IsDialogActive());
- EXPECT_TRUE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
- EXPECT_EQ(NativeManagerTracker::SHOWN, tracker4.state_);
- EXPECT_FALSE(tracker3.was_shown_);
- native_manager4->Close();
- EXPECT_FALSE(manager->IsDialogActive());
- EXPECT_FALSE(delegate->web_contents_blocked());
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker1.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker2.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker3.state_);
- EXPECT_EQ(NativeManagerTracker::CLOSED, tracker4.state_);
- EXPECT_TRUE(tracker1.was_shown_);
- EXPECT_TRUE(tracker2.was_shown_);
- EXPECT_FALSE(tracker3.was_shown_);
- EXPECT_TRUE(tracker4.was_shown_);
- }
- // Test that CloseAllDialogs does what it says.
- TEST_F(WebContentsModalDialogManagerTest, CloseAllDialogs) {
- const int kWindowCount = 4;
- NativeManagerTracker trackers[kWindowCount];
- TestNativeWebContentsModalDialogManager* native_managers[kWindowCount];
- for (int i = 0; i < kWindowCount; i++) {
- const gfx::NativeWindow dialog = MakeFakeDialog();
- native_managers[i] =
- new TestNativeWebContentsModalDialogManager(
- dialog, manager, &(trackers[i]));
- manager->ShowDialogWithManager(dialog,
- base::WrapUnique(native_managers[i]));
- }
- for (int i = 0; i < kWindowCount; i++)
- EXPECT_NE(NativeManagerTracker::CLOSED, trackers[i].state_);
- test_api->CloseAllDialogs();
- EXPECT_FALSE(delegate->web_contents_blocked());
- EXPECT_FALSE(manager->IsDialogActive());
- for (int i = 0; i < kWindowCount; i++)
- EXPECT_EQ(NativeManagerTracker::CLOSED, trackers[i].state_);
- }
- } // namespace web_modal
|