Chromium Code Reviews| Index: components/bubble/bubble_manager.cc |
| diff --git a/components/bubble/bubble_manager.cc b/components/bubble/bubble_manager.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0f1ec8697060297c77dfdecb4a827e483cb7da08 |
| --- /dev/null |
| +++ b/components/bubble/bubble_manager.cc |
| @@ -0,0 +1,111 @@ |
| +// 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 <vector> |
| + |
| +#include "components/bubble/bubble_delegate.h" |
| +#include "content/public/browser/browser_thread.h" |
| + |
| +BubbleManager::~BubbleManager() { |
| + // The delegate should NOT outlive the manager. When a delegate is destroyed |
|
msw
2015/08/13 03:37:23
Each delegate is owned by a controller, and there
hcarmona
2015/08/15 02:03:20
Assumption is no longer here. The controller will
|
| + // it should hide itself. This means that when the bubble manager is being |
| + // destroyed there should be no visible bubbles. |
| + DCHECK_EQ(controllers_.size(), 0); |
| +} |
| + |
| +BubbleReference BubbleManager::ShowBubble(scoped_ptr<BubbleDelegate> bubble) { |
| + DCHECK(bubble); |
| + DCHECK(bubble->GetContext()); |
| + |
| + scoped_ptr<BubbleController> controller(new BubbleController(bubble.Pass())); |
| + |
| + BubbleReference bubble_ref = controller->AsWeakPtr(); |
| + ShowBubbleUI(bubble_ref); |
| + |
| + controllers_.push_back(controller.Pass()); |
| + return bubble_ref; |
|
msw
2015/08/13 03:37:23
By exposing a BubbleReference, don't you allow use
hcarmona
2015/08/13 20:50:35
True, do we have an existing pattern that would al
msw
2015/08/13 21:41:37
Maybe remove the controller functions or make them
hcarmona
2015/08/15 02:03:20
Added a TODO item, I'll look into this next week.
|
| +} |
| + |
| +void BubbleManager::CloseBubble(BubbleReference bubble) { |
|
msw
2015/08/13 03:37:23
q: might bubblemanager users ever want to specify
hcarmona
2015/08/15 02:03:20
Now they can :D
|
| + for (auto iter = controllers_.begin(); iter != controllers_.end(); ++iter) { |
| + if ((*iter) == bubble.get()) { |
|
msw
2015/08/13 03:37:23
nit: parens around *iter aren't really necessary.
hcarmona
2015/08/15 02:03:20
Done.
|
| + BubbleController* controller = *iter; |
| + controllers_.weak_erase(iter); |
| + |
| + controller->Hide(BUBBLE_CLOSE_IGNORE); |
| + controller->Close(); |
|
msw
2015/08/13 03:37:23
nit: perhaps closing a bubble should first hide it
hcarmona
2015/08/15 02:03:20
No longer necessary.
|
| + |
| + // Dancing around this because some bubbles will chain another on close. |
|
msw
2015/08/13 03:37:23
I'm not quite sure what you're saying here. Does c
hcarmona
2015/08/13 20:50:35
Permission bubbles will sometimes show another bub
msw
2015/08/13 21:41:37
Acknowledged; maybe rephrase the comment to make t
hcarmona
2015/08/15 02:03:20
Done. Better comment.
|
| + delete controller; |
| + return; |
| + } |
| + } |
| + |
| + // Hidden/unmanaged bubbles should not be hidden: this could indicate a bug. |
|
msw
2015/08/13 03:37:23
nit: replace the colon with a semicolon or a comma
hcarmona
2015/08/15 02:03:20
Acknowledged.
|
| + NOTREACHED(); |
| +} |
| + |
| +bool BubbleManager::ShouldUpdateBubble(BubbleReference bubble) { |
| + return bubble->ShouldUpdateBubble(); |
| +} |
| + |
| +void BubbleManager::UpdateBubble(BubbleReference bubble) { |
| + if (bubble->ShouldUpdateBubble()) { |
| + bubble->Hide(BUBBLE_CLOSE_IGNORE); |
| + ShowBubbleUI(bubble); |
| + } |
| +} |
| + |
| +BubbleManager::BubbleManager() {} |
| + |
| +void BubbleManager::MassUpdateBubbles( |
| + void* context, |
| + base::Callback<void(base::WeakPtr<BubbleController>)> callback) { |
| + DCHECK(context); |
| + |
| + for (auto controller : controllers_) { |
| + if (controller->MatchesContext(context)) |
| + callback.Run(controller->AsWeakPtr()); |
| + } |
| +} |
| + |
| +void BubbleManager::CloseMatchingBubbles(void* context, |
| + CloseOption close_option, |
| + BubbleCloseReason reason) { |
| + DCHECK(context); |
| + |
| + std::vector<BubbleController*> closing; |
| + |
| + for (auto iter = controllers_.begin(); iter != controllers_.end();) { |
| + if ((*iter)->MatchesContext(context)) { |
| + (*iter)->Hide(reason); |
| + if ((close_option == FORCE_CLOSE) || (*iter)->ShouldClose()) { |
| + // Don't call close here to avoid bubbles trying to show the next in a |
|
msw
2015/08/13 03:37:23
Ugh, horrifying... This is why BubbleManager shoul
groby-ooo-7-16
2015/08/13 18:44:38
The problem is that bubbles will be shown _in resp
msw
2015/08/13 19:18:58
Okay, this pattern (weak_erase first then Close la
|
| + // series and messing up iterating the controllers. |
| + // I'm looking at you, permission bubbles! |
| + closing.push_back(*iter); |
| + iter = controllers_.weak_erase(iter); |
| + continue; |
| + } |
| + } |
| + ++iter; |
|
msw
2015/08/13 03:37:23
Shouldn't this also be called if a bubble matches
hcarmona
2015/08/13 20:50:35
Yes, it's outside both checks.
msw
2015/08/13 21:41:37
Oh duh, you're right, sorry.
|
| + } |
| + |
| + for (auto iter : closing) { |
| + iter->Close(); |
| + // No need to remove from the vector. |
| + delete iter; |
|
msw
2015/08/13 03:37:22
ditto: dtor should call close or vice versa.
hcarmona
2015/08/15 02:03:20
Acknowledged.
|
| + } |
| +} |
| + |
| +void BubbleManager::ShowBubbleUI(base::WeakPtr<BubbleController> controller) { |
| + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
|
msw
2015/08/13 03:37:23
As I noted in the DEPS change, this seems like a j
hcarmona
2015/08/15 02:03:20
Done.
|
| + controller->Show(); |
| +} |
| + |
| +void BubbleManager::UpdateBubbleUI(base::WeakPtr<BubbleController> controller) { |
| + controller->UpdateAnchorPosition(); |
|
msw
2015/08/13 03:37:23
nit: unify naming... the layers of controllers and
hcarmona
2015/08/15 02:03:20
Done.
|
| +} |