Ensure low-memory renderers retry failed loads correctly.
[chromium-blink-merge.git] / components / bubble / bubble_manager.cc
blob41529f980be1f832767d391e73093b4e25bc0640
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/bubble/bubble_manager.h"
7 #include <vector>
9 #include "components/bubble/bubble_controller.h"
10 #include "components/bubble/bubble_delegate.h"
12 BubbleManager::BubbleManager() : manager_state_(SHOW_BUBBLES) {}
14 BubbleManager::~BubbleManager() {
15 FinalizePendingRequests();
18 BubbleReference BubbleManager::ShowBubble(scoped_ptr<BubbleDelegate> bubble) {
19 DCHECK(thread_checker_.CalledOnValidThread());
20 DCHECK(bubble);
22 scoped_ptr<BubbleController> controller(
23 new BubbleController(this, bubble.Pass()));
25 BubbleReference bubble_ref = controller->AsWeakPtr();
27 switch (manager_state_) {
28 case SHOW_BUBBLES:
29 controller->Show();
30 controllers_.push_back(controller.Pass());
31 break;
32 case QUEUE_BUBBLES:
33 show_queue_.push_back(controller.Pass());
34 break;
35 case NO_MORE_BUBBLES:
36 FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
37 OnBubbleNeverShown(controller->AsWeakPtr()));
38 break;
41 return bubble_ref;
44 bool BubbleManager::CloseBubble(BubbleReference bubble,
45 BubbleCloseReason reason) {
46 DCHECK(thread_checker_.CalledOnValidThread());
47 DCHECK_NE(manager_state_, QUEUE_BUBBLES);
48 if (manager_state_ == SHOW_BUBBLES)
49 manager_state_ = QUEUE_BUBBLES;
51 for (auto iter = controllers_.begin(); iter != controllers_.end(); ++iter) {
52 if (*iter == bubble.get()) {
53 bool closed = (*iter)->ShouldClose(reason);
54 if (closed) {
55 FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
56 OnBubbleClosed((*iter)->AsWeakPtr(), reason));
57 iter = controllers_.erase(iter);
59 ShowPendingBubbles();
60 return closed;
64 // Attempting to close a bubble that is already closed or that this manager
65 // doesn't own is a bug.
66 NOTREACHED();
67 return false;
70 void BubbleManager::CloseAllBubbles(BubbleCloseReason reason) {
71 // The following close reasons don't make sense for multiple bubbles:
72 DCHECK_NE(reason, BUBBLE_CLOSE_ACCEPTED);
73 DCHECK_NE(reason, BUBBLE_CLOSE_CANCELED);
75 DCHECK(thread_checker_.CalledOnValidThread());
76 DCHECK_NE(manager_state_, QUEUE_BUBBLES);
77 if (manager_state_ == SHOW_BUBBLES)
78 manager_state_ = QUEUE_BUBBLES;
80 for (auto iter = controllers_.begin(); iter != controllers_.end();) {
81 bool closed = (*iter)->ShouldClose(reason);
82 if (closed) {
83 FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
84 OnBubbleClosed((*iter)->AsWeakPtr(), reason));
86 iter = closed ? controllers_.erase(iter) : iter + 1;
89 ShowPendingBubbles();
92 void BubbleManager::UpdateAllBubbleAnchors() {
93 DCHECK(thread_checker_.CalledOnValidThread());
94 for (auto controller : controllers_)
95 controller->UpdateAnchorPosition();
98 void BubbleManager::AddBubbleManagerObserver(BubbleManagerObserver* observer) {
99 observers_.AddObserver(observer);
102 void BubbleManager::RemoveBubbleManagerObserver(
103 BubbleManagerObserver* observer) {
104 observers_.RemoveObserver(observer);
107 void BubbleManager::FinalizePendingRequests() {
108 // Return if already "Finalized".
109 if (manager_state_ == NO_MORE_BUBBLES)
110 return;
112 manager_state_ = NO_MORE_BUBBLES;
113 CloseAllBubbles(BUBBLE_CLOSE_FORCED);
116 void BubbleManager::ShowPendingBubbles() {
117 if (manager_state_ == QUEUE_BUBBLES)
118 manager_state_ = SHOW_BUBBLES;
120 if (manager_state_ == SHOW_BUBBLES) {
121 for (auto controller : show_queue_)
122 controller->Show();
124 controllers_.insert(controllers_.end(), show_queue_.begin(),
125 show_queue_.end());
127 show_queue_.weak_clear();
128 } else {
129 for (auto controller : show_queue_) {
130 FOR_EACH_OBSERVER(BubbleManagerObserver, observers_,
131 OnBubbleNeverShown(controller->AsWeakPtr()));
134 // Clear the queue if bubbles can't be shown.
135 show_queue_.clear();