summaryrefslogtreecommitdiff
path: root/chromium/components/bubble/bubble_manager_unittest.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-05-09 14:22:11 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-05-09 15:11:45 +0000
commit2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c (patch)
treee75f511546c5fd1a173e87c1f9fb11d7ac8d1af3 /chromium/components/bubble/bubble_manager_unittest.cc
parenta4f3d46271c57e8155ba912df46a05559d14726e (diff)
downloadqtwebengine-chromium-2ddb2d3e14eef3de7dbd0cef553d669b9ac2361c.tar.gz
BASELINE: Update Chromium to 51.0.2704.41
Also adds in all smaller components by reversing logic for exclusion. Change-Id: Ibf90b506e7da088ea2f65dcf23f2b0992c504422 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
Diffstat (limited to 'chromium/components/bubble/bubble_manager_unittest.cc')
-rw-r--r--chromium/components/bubble/bubble_manager_unittest.cc446
1 files changed, 446 insertions, 0 deletions
diff --git a/chromium/components/bubble/bubble_manager_unittest.cc b/chromium/components/bubble/bubble_manager_unittest.cc
new file mode 100644
index 00000000000..625fe94ffe3
--- /dev/null
+++ b/chromium/components/bubble/bubble_manager_unittest.cc
@@ -0,0 +1,446 @@
+// Copyright 2015 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/bubble/bubble_manager.h"
+
+#include <utility>
+
+#include "base/macros.h"
+#include "components/bubble/bubble_controller.h"
+#include "components/bubble/bubble_manager_mocks.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+// A "show chain" happens when a bubble decides to show another bubble on close.
+// All bubbles must be iterated to handle a close event. If a bubble shows
+// another bubble while it's being closed, the iterator can get messed up.
+class ChainShowBubbleDelegate : public MockBubbleDelegate {
+ public:
+ // |chained_bubble| can be nullptr if not interested in getting a reference to
+ // the chained bubble.
+ ChainShowBubbleDelegate(BubbleManager* manager,
+ scoped_ptr<BubbleDelegate> delegate,
+ BubbleReference* chained_bubble)
+ : manager_(manager),
+ delegate_(std::move(delegate)),
+ chained_bubble_(chained_bubble),
+ closed_(false) {
+ EXPECT_CALL(*this, ShouldClose(testing::_)).WillOnce(testing::Return(true));
+ }
+
+ ~ChainShowBubbleDelegate() override { EXPECT_TRUE(closed_); }
+
+ void DidClose(BubbleCloseReason reason) override {
+ MockBubbleDelegate::DidClose(reason);
+ BubbleReference ref = manager_->ShowBubble(std::move(delegate_));
+ if (chained_bubble_)
+ *chained_bubble_ = ref;
+ closed_ = true;
+ }
+
+ private:
+ BubbleManager* manager_;
+ scoped_ptr<BubbleDelegate> delegate_;
+ BubbleReference* chained_bubble_;
+ bool closed_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChainShowBubbleDelegate);
+};
+
+// A "close chain" happens when a close event is received while another close
+// event is in progress. Ex: Closing the BubbleUi will hide the bubble, causing
+// it to lose focus, which causes another close event. This test simulates this
+// by sending a close event during the |DidClose| method of a BubbleDelegate.
+// Similarly to the show chain, a close chain can mess up the iterator.
+class ChainCloseBubbleDelegate : public MockBubbleDelegate {
+ public:
+ ChainCloseBubbleDelegate(BubbleManager* manager) : manager_(manager) {}
+
+ ~ChainCloseBubbleDelegate() override {}
+
+ void DidClose(BubbleCloseReason reason) override {
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+ }
+
+ private:
+ BubbleManager* manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ChainCloseBubbleDelegate);
+};
+
+class MockBubbleManagerObserver : public BubbleManager::BubbleManagerObserver {
+ public:
+ MockBubbleManagerObserver() {}
+ ~MockBubbleManagerObserver() override {}
+
+ MOCK_METHOD1(OnBubbleNeverShown, void(BubbleReference));
+ MOCK_METHOD2(OnBubbleClosed, void(BubbleReference, BubbleCloseReason));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockBubbleManagerObserver);
+};
+
+class BubbleManagerSubclass : public BubbleManager {
+ public:
+ using BubbleManager::CloseBubblesOwnedBy;
+};
+
+class BubbleManagerTest : public testing::Test {
+ public:
+ BubbleManagerTest();
+ ~BubbleManagerTest() override {}
+
+ void SetUp() override;
+ void TearDown() override;
+
+ protected:
+ scoped_ptr<BubbleManagerSubclass> manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BubbleManagerTest);
+};
+
+BubbleManagerTest::BubbleManagerTest() {}
+
+void BubbleManagerTest::SetUp() {
+ testing::Test::SetUp();
+ manager_.reset(new BubbleManagerSubclass);
+}
+
+void BubbleManagerTest::TearDown() {
+ manager_.reset();
+ testing::Test::TearDown();
+}
+
+TEST_F(BubbleManagerTest, ManagerShowsBubbleUi) {
+ scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default();
+
+ MockBubbleUi* bubble_ui = delegate->bubble_ui();
+ EXPECT_CALL(*bubble_ui, Destroyed());
+ EXPECT_CALL(*bubble_ui, Show(testing::_));
+ EXPECT_CALL(*bubble_ui, Close());
+ EXPECT_CALL(*bubble_ui, UpdateAnchorPosition()).Times(0);
+
+ manager_->ShowBubble(std::move(delegate));
+}
+
+TEST_F(BubbleManagerTest, ManagerUpdatesBubbleUiAnchor) {
+ scoped_ptr<MockBubbleDelegate> delegate = MockBubbleDelegate::Default();
+
+ MockBubbleUi* bubble_ui = delegate->bubble_ui();
+ EXPECT_CALL(*bubble_ui, Destroyed());
+ EXPECT_CALL(*bubble_ui, Show(testing::_));
+ EXPECT_CALL(*bubble_ui, Close());
+ EXPECT_CALL(*bubble_ui, UpdateAnchorPosition());
+
+ manager_->ShowBubble(std::move(delegate));
+ manager_->UpdateAllBubbleAnchors();
+}
+
+TEST_F(BubbleManagerTest, CloseOnReferenceInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ ASSERT_TRUE(ref->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST));
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseOnStubbornReferenceDoesNotInvalidate) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ ASSERT_FALSE(ref->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST));
+
+ ASSERT_TRUE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FOCUS_LOST));
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, DestroyInvalidatesReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_.reset();
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED));
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FORCED);
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, DestroyInvalidatesStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_.reset();
+
+ ASSERT_FALSE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseDoesNotInvalidateStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ ASSERT_FALSE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FOCUS_LOST));
+
+ ASSERT_TRUE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllDoesNotInvalidateStubbornReference) {
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+
+ ASSERT_TRUE(ref);
+}
+
+TEST_F(BubbleManagerTest, CloseAllInvalidatesMixAppropriately) {
+ BubbleReference stubborn_ref1 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref1 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference stubborn_ref2 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref2 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference stubborn_ref3 =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+ BubbleReference normal_ref3 =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+
+ ASSERT_TRUE(stubborn_ref1);
+ ASSERT_TRUE(stubborn_ref2);
+ ASSERT_TRUE(stubborn_ref3);
+ ASSERT_FALSE(normal_ref1);
+ ASSERT_FALSE(normal_ref2);
+ ASSERT_FALSE(normal_ref3);
+}
+
+TEST_F(BubbleManagerTest, CloseBubbleShouldOnlylCloseSelf) {
+ BubbleReference ref1 = manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference ref2 = manager_->ShowBubble(MockBubbleDelegate::Default());
+ BubbleReference ref3 = manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ EXPECT_TRUE(ref1);
+ EXPECT_TRUE(ref2);
+ EXPECT_TRUE(ref3);
+
+ ref2->CloseBubble(BUBBLE_CLOSE_FOCUS_LOST);
+
+ EXPECT_TRUE(ref1);
+ EXPECT_FALSE(ref2);
+ EXPECT_TRUE(ref3);
+}
+
+TEST_F(BubbleManagerTest, CloseOwnedByShouldLeaveUnowned) {
+ scoped_ptr<MockBubbleDelegate> delegate1 = MockBubbleDelegate::Default();
+ scoped_ptr<MockBubbleDelegate> delegate2 = MockBubbleDelegate::Default();
+ scoped_ptr<MockBubbleDelegate> delegate3 = MockBubbleDelegate::Default();
+ MockBubbleDelegate& delegate1_ref = *delegate1;
+ MockBubbleDelegate& delegate2_ref = *delegate2;
+ MockBubbleDelegate& delegate3_ref = *delegate3;
+ BubbleReference ref1 = manager_->ShowBubble(std::move(delegate1));
+ BubbleReference ref2 = manager_->ShowBubble(std::move(delegate2));
+ BubbleReference ref3 = manager_->ShowBubble(std::move(delegate3));
+
+ // These pointers are only compared for equality, not dereferenced.
+ const content::RenderFrameHost* const frame1 =
+ reinterpret_cast<const content::RenderFrameHost*>(&ref1);
+ const content::RenderFrameHost* const frame2 =
+ reinterpret_cast<const content::RenderFrameHost*>(&ref2);
+
+ EXPECT_CALL(delegate1_ref, OwningFrame())
+ .WillRepeatedly(testing::Return(frame1));
+ EXPECT_CALL(delegate2_ref, OwningFrame())
+ .WillRepeatedly(testing::Return(frame2));
+ EXPECT_CALL(delegate3_ref, OwningFrame())
+ .WillRepeatedly(testing::Return(nullptr));
+ EXPECT_CALL(delegate1_ref, ShouldClose(BUBBLE_CLOSE_FRAME_DESTROYED))
+ .WillOnce(testing::Return(true));
+
+ manager_->CloseBubblesOwnedBy(frame1);
+ EXPECT_FALSE(ref1);
+ EXPECT_TRUE(ref2);
+ EXPECT_TRUE(ref3);
+}
+
+TEST_F(BubbleManagerTest, UpdateAllShouldWorkWithoutBubbles) {
+ // Manager shouldn't crash if bubbles have never been added.
+ manager_->UpdateAllBubbleAnchors();
+
+ // Add a bubble and close it.
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+ ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED));
+
+ // Bubble should NOT get an update event because it's already closed.
+ manager_->UpdateAllBubbleAnchors();
+}
+
+TEST_F(BubbleManagerTest, CloseAllShouldWorkWithoutBubbles) {
+ // Manager shouldn't crash if bubbles have never been added.
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+
+ // Add a bubble and close it.
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+ ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED));
+
+ // Bubble should NOT get a close event because it's already closed.
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FOCUS_LOST);
+}
+
+// This test validates that it's possible to show another bubble when
+// |CloseBubble| is called.
+TEST_F(BubbleManagerTest, AllowBubbleChainingOnClose) {
+ BubbleReference chained_bubble;
+ BubbleReference ref =
+ manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+ manager_.get(), MockBubbleDelegate::Default(), &chained_bubble)));
+ ASSERT_FALSE(chained_bubble); // Bubble not yet visible.
+ ASSERT_TRUE(manager_->CloseBubble(ref, BUBBLE_CLOSE_FORCED));
+ ASSERT_TRUE(chained_bubble); // Bubble is now visible.
+}
+
+// This test validates that it's possible to show another bubble when
+// |CloseAllBubbles| is called.
+TEST_F(BubbleManagerTest, AllowBubbleChainingOnCloseAll) {
+ BubbleReference chained_bubble;
+ BubbleReference ref =
+ manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+ manager_.get(), MockBubbleDelegate::Default(), &chained_bubble)));
+ ASSERT_FALSE(chained_bubble); // Bubble not yet visible.
+ manager_->CloseAllBubbles(BUBBLE_CLOSE_FORCED);
+ ASSERT_TRUE(chained_bubble); // Bubble is now visible.
+}
+
+// This test validates that a show chain will not happen in the destructor.
+// While chaining is during the normal life span of the manager, it should NOT
+// happen when the manager is being destroyed.
+TEST_F(BubbleManagerTest, BubblesDoNotChainOnDestroy) {
+ MockBubbleManagerObserver metrics;
+ // |chained_delegate| should never be shown.
+ EXPECT_CALL(metrics, OnBubbleNeverShown(testing::_));
+ // The ChainShowBubbleDelegate should be closed when the manager is destroyed.
+ EXPECT_CALL(metrics, OnBubbleClosed(testing::_, BUBBLE_CLOSE_FORCED));
+ manager_->AddBubbleManagerObserver(&metrics);
+
+ scoped_ptr<MockBubbleDelegate> chained_delegate(new MockBubbleDelegate);
+ EXPECT_CALL(*chained_delegate->bubble_ui(), Show(testing::_)).Times(0);
+ EXPECT_CALL(*chained_delegate, ShouldClose(testing::_)).Times(0);
+ EXPECT_CALL(*chained_delegate, DidClose(testing::_)).Times(0);
+
+ manager_->ShowBubble(make_scoped_ptr(new ChainShowBubbleDelegate(
+ manager_.get(), std::move(chained_delegate), nullptr)));
+ manager_.reset();
+}
+
+TEST_F(BubbleManagerTest, BubbleCloseReasonIsCalled) {
+ MockBubbleManagerObserver metrics;
+ EXPECT_CALL(metrics, OnBubbleNeverShown(testing::_)).Times(0);
+ EXPECT_CALL(metrics, OnBubbleClosed(testing::_, BUBBLE_CLOSE_ACCEPTED));
+ manager_->AddBubbleManagerObserver(&metrics);
+
+ BubbleReference ref = manager_->ShowBubble(MockBubbleDelegate::Default());
+ ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED);
+
+ // Destroy to verify no events are sent to |metrics| in destructor.
+ manager_.reset();
+}
+
+// In a close chain, it should be possible for the bubble in the second close
+// event to close.
+TEST_F(BubbleManagerTest, BubbleCloseChainCloseClose) {
+ scoped_ptr<ChainCloseBubbleDelegate> closing_bubble(
+ new ChainCloseBubbleDelegate(manager_.get()));
+ EXPECT_CALL(*closing_bubble, ShouldClose(testing::_))
+ .WillOnce(testing::Return(true));
+
+ BubbleReference other_bubble_ref =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ BubbleReference closing_bubble_ref =
+ manager_->ShowBubble(std::move(closing_bubble));
+
+ EXPECT_TRUE(other_bubble_ref);
+ EXPECT_TRUE(closing_bubble_ref);
+
+ closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED);
+
+ EXPECT_FALSE(other_bubble_ref);
+ EXPECT_FALSE(closing_bubble_ref);
+}
+
+// In a close chain, it should be possible for the bubble in the second close
+// event to remain open because close is a request.
+TEST_F(BubbleManagerTest, BubbleCloseChainCloseNoClose) {
+ scoped_ptr<ChainCloseBubbleDelegate> closing_bubble(
+ new ChainCloseBubbleDelegate(manager_.get()));
+ EXPECT_CALL(*closing_bubble, ShouldClose(testing::_))
+ .WillOnce(testing::Return(true));
+
+ BubbleReference other_bubble_ref =
+ manager_->ShowBubble(MockBubbleDelegate::Stubborn());
+
+ BubbleReference closing_bubble_ref =
+ manager_->ShowBubble(std::move(closing_bubble));
+
+ EXPECT_TRUE(other_bubble_ref);
+ EXPECT_TRUE(closing_bubble_ref);
+
+ closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED);
+
+ EXPECT_TRUE(other_bubble_ref);
+ EXPECT_FALSE(closing_bubble_ref);
+}
+
+// This test is a sanity check. |closing_bubble| will attempt to close all other
+// bubbles if it's closed, but it doesn't want to close. Sending a close request
+// should keep it open without starting a close chain.
+TEST_F(BubbleManagerTest, BubbleCloseChainNoCloseNoClose) {
+ scoped_ptr<ChainCloseBubbleDelegate> closing_bubble(
+ new ChainCloseBubbleDelegate(manager_.get()));
+ EXPECT_CALL(*closing_bubble, ShouldClose(testing::_))
+ .WillRepeatedly(testing::Return(false));
+
+ BubbleReference other_bubble_ref =
+ manager_->ShowBubble(MockBubbleDelegate::Default());
+
+ BubbleReference closing_bubble_ref =
+ manager_->ShowBubble(std::move(closing_bubble));
+
+ EXPECT_TRUE(other_bubble_ref);
+ EXPECT_TRUE(closing_bubble_ref);
+
+ closing_bubble_ref->CloseBubble(BUBBLE_CLOSE_ACCEPTED);
+
+ EXPECT_TRUE(other_bubble_ref);
+ EXPECT_TRUE(closing_bubble_ref);
+}
+
+} // namespace