Index: components/web_modal/popup_manager.cc |
diff --git a/components/web_modal/popup_manager.cc b/components/web_modal/popup_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5440aff372b01259e0c6f87cc5c60a1b08c49f38 |
--- /dev/null |
+++ b/components/web_modal/popup_manager.cc |
@@ -0,0 +1,136 @@ |
+// 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/popup_manager.h" |
+ |
+#include "content/public/browser/navigation_details.h" |
+#include "content/public/browser/navigation_entry.h" |
+#include "content/public/browser/render_view_host.h" |
+#include "content/public/browser/web_contents.h" |
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
+ |
+using content::WebContents; |
+ |
+namespace web_modal { |
+ |
+PopupManager::PopupManager() |
+ : closing_all_popups_(false) { |
+} |
+ |
+PopupManager::~PopupManager() { |
+ DCHECK(child_popups_.empty()); |
+} |
+ |
+void PopupManager::ShowPopup(scoped_ptr<SinglePopupManager> manager) { |
+ child_popups_.push_back(manager.Pass())); |
+ |
+ if (child_popups_.size() == 1) |
+ child_popups_.back()->Show(); |
+} |
+ |
+ |
+bool PopupManager::IsPopupActive( |
+ const content::WebContents* web_contents) const { |
+ // TODO(gbillock): needs help to figure out what's going on for the given |
+ // web contents. |
+ return !child_popups_.empty(); |
+} |
+ |
+void PopupManager::FocusTopmostPopupForWebContentsIfActive( |
+ const content::WebContents* web_contents) { |
+ // TODO(gbillock): check if the top popups are already being shown, |
+ // or need to be re-activated, or what. We may want to close some, too, |
+ // depending on the policy. |
Mike Wittman
2014/05/23 19:02:35
I think we should be making decisions about showin
Greg Billock
2014/05/27 22:42:03
I'm thinking the same thing. I added a note to tha
Mike Wittman
2014/05/28 21:47:09
On the focus issue, it's also entirely possible th
|
+ DCHECK(!child_popups_.empty()); |
+ child_popups_.front()->Focus(); |
+} |
+ |
+void PopupManager::WillClose(NativePopup popup) { |
+ PopupList::iterator dlg = FindPopupState(popup); |
+ |
+ // The Views tab contents modal dialog calls WillClose twice. Ignore the |
+ // second invocation. |
+ if (dlg == child_popups_.end()) |
+ return; |
+ |
+ bool removed_topmost_dialog = dlg == child_popups_.begin(); |
+ scoped_ptr<SinglePopupManager> deleter(*dlg); |
+ child_popups_.erase(dlg); |
+ if (!child_popups_.empty() && removed_topmost_dialog && |
+ !closing_all_popups_) { |
+ child_popups_.front()->Show(); |
+ } |
+} |
+ |
+PopupManager::PopupList::iterator PopupManager::FindPopupState( |
+ NativePopup popup) { |
+ PopupList::iterator i; |
+ for (i = child_popups_.begin(); i != child_popups_.end(); ++i) { |
+ if ((*i)->popup() == popup) |
+ break; |
+ } |
+ |
+ return i; |
+} |
+ |
+void PopupManager::CloseAllPopups() { |
+ closing_all_popups_ = true; |
+ |
+ // Clear out any dialogs since we are leaving this page entirely. |
+ while (!child_popups_.empty()) { |
+ child_popups_.front()->Close(); |
+ } |
+ |
+ closing_all_popups_ = false; |
+} |
+ |
+void PopupManager::DidNavigateMainFrame( |
+ content::WebContents* web_contents, |
+ const content::LoadCommittedDetails& details, |
+ const content::FrameNavigateParams& params) { |
+ // Close constrained windows if necessary. |
+ if (!net::registry_controlled_domains::SameDomainOrHost( |
+ details.previous_url, details.entry->GetURL(), |
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) |
+ CloseAllPopups(); |
+} |
+ |
+void PopupManager::DidGetIgnoredUIEvent(content::WebContents* web_contents) { |
+ if (!child_popups_.empty()) { |
+ child_popups_.front()->Focus(); |
+ } |
+} |
+ |
+void PopupManager::WasShown(content::WebContents* web_contents) { |
+ if (!child_popups_.empty()) |
+ child_popups_.front()->Show(); |
+} |
+ |
+void PopupManager::WasHidden(content::WebContents* web_contents) { |
+ if (!child_popups_.empty()) |
+ child_popups_.front()->Hide(); |
+} |
+ |
+void PopupManager::WebContentsDestroyed(content::WebContents* web_contents) { |
+ // First cleanly close all child dialogs. |
+ // TODO(mpcomplete): handle case if MaybeCloseChildWindows() already asked |
+ // some of these to close. CloseAllDialogs is async, so it might get called |
+ // twice before it runs. |
+ CloseAllPopups(); |
+} |
+ |
+void PopupManager::DidAttachInterstitialPage( |
+ content::WebContents* web_contents) { |
+ // Copy the dialogs so we can close and remove them while iterating over the |
+ // list. |
+ PopupList popups(child_popups_); |
+ for (PopupList::iterator it = popups.begin(); it != popups.end(); ++it) { |
+ if ((*it)->ShouldCloseOnNavigation()) |
+ (*it)->Close(); |
+ } |
+} |
+ |
+// TODO(gbillock): Need other navigation hooks to close? |
+ |
+} // namespace web_modal |