Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(966)

Unified Diff: chrome/browser/geolocation/chrome_geolocation_permission_context.cc

Issue 9491009: Show queued geolocation InfoBars when InfoBar is hidden. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Refactor to make logic clearer. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/geolocation/chrome_geolocation_permission_context.cc
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
index aa28177e23f4b49a4464c1935bbad0e8db47a2a5..caefc2c19fcb8aba38575fab4e968472a6455020 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
@@ -14,17 +14,20 @@
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_tab_helper.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
#include "chrome/browser/tab_contents/tab_util.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"
@@ -78,12 +81,6 @@ class GeolocationInfoBarQueueController : content::NotificationObserver {
int render_view_id,
int bridge_id);
- // Called by the InfoBarDelegate to notify it's closed. It'll display a new
- // InfoBar if there's any request pending for this tab.
- void OnInfoBarClosed(int render_process_id,
- int render_view_id,
- int bridge_id);
-
// Called by the InfoBarDelegate to notify permission has been set.
// It'll notify and dismiss any other pending InfoBar request for the same
// |requesting_frame| and embedder.
@@ -97,7 +94,7 @@ class GeolocationInfoBarQueueController : content::NotificationObserver {
// content::NotificationObserver
virtual void Observe(int type,
const content::NotificationSource& source,
- const content::NotificationDetails& details);
+ const content::NotificationDetails& details) OVERRIDE;
private:
struct PendingInfoBarRequest;
@@ -106,11 +103,19 @@ class GeolocationInfoBarQueueController : content::NotificationObserver {
typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests;
// Shows the first pending infobar for this tab.
- void ShowQueuedInfoBar(int render_process_id, int render_view_id);
+ void ShowQueuedInfoBar(int render_process_id, int render_view_id,
+ InfoBarTabHelper* helper);
// Cancels an InfoBar request and returns the next iterator position.
PendingInfoBarRequests::iterator CancelInfoBarRequestInternal(
- PendingInfoBarRequests::iterator i);
+ PendingInfoBarRequests::iterator i,
+ bool remove_showing_infobar);
+
+ // Removes any pending requests for a given dead tab.
+ void ClearInfoBarRequestsFromTab(int render_process_id, int render_view_id);
bulach 2012/03/22 17:01:46 nit: maybe ClearPendingInfoBarRequestsFromTab, to
John Knottenbelt 2012/03/22 18:09:02 Done.
+
+ InfoBarTabHelper* GetInfoBarHelper(int render_process_id, int render_view_id);
+ bool AlreadyShowingQueuedInfoBar(int render_process_id, int render_view_id);
bulach 2012/03/22 17:01:46 nit: and in this case the could probably remove th
John Knottenbelt 2012/03/22 18:09:02 Done.
content::NotificationRegistrar registrar_;
@@ -135,8 +140,10 @@ class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate {
const GURL& requesting_frame_url,
const std::string& display_languages);
+ int render_process_id() const { return render_process_id_; }
+ int render_view_id() const { return render_view_id_; }
+
private:
- virtual ~GeolocationConfirmInfoBarDelegate();
// ConfirmInfoBarDelegate:
virtual bool ShouldExpire(
@@ -185,11 +192,6 @@ GeolocationConfirmInfoBarDelegate::GeolocationConfirmInfoBarDelegate(
committed_entry->GetUniqueID() : 0;
}
-GeolocationConfirmInfoBarDelegate::~GeolocationConfirmInfoBarDelegate() {
- controller_->OnInfoBarClosed(render_process_id_, render_view_id_,
- bridge_id_);
-}
-
bool GeolocationConfirmInfoBarDelegate::ShouldExpire(
const content::LoadCommittedDetails& details) const {
if (details.did_replace_entry || !details.is_navigation_to_different_page())
@@ -283,7 +285,8 @@ struct GeolocationInfoBarQueueController::PendingInfoBarRequest {
GURL requesting_frame;
GURL embedder;
base::Callback<void(bool)> callback;
- InfoBarDelegate* infobar_delegate;
+ GeolocationConfirmInfoBarDelegate* infobar_delegate;
+ bool notified;
bulach 2012/03/22 17:01:46 unused?
John Knottenbelt 2012/03/22 18:09:02 Removed. On 2012/03/22 17:01:46, bulach wrote:
};
GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
@@ -299,7 +302,8 @@ GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest(
requesting_frame(requesting_frame),
embedder(embedder),
callback(callback),
- infobar_delegate(NULL) {
+ infobar_delegate(NULL),
+ notified(false) {
}
bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab(
@@ -354,7 +358,6 @@ bool GeolocationInfoBarQueueController::RequestEquals::operator()(
return request.Equals(render_process_id_, render_view_id_, bridge_id_);
}
-
// GeolocationInfoBarQueueController ------------------------------------------
GeolocationInfoBarQueueController::GeolocationInfoBarQueueController(
@@ -384,7 +387,15 @@ void GeolocationInfoBarQueueController::CreateInfoBarRequest(
pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id,
render_view_id, bridge_id, requesting_frame, embedder, callback));
- ShowQueuedInfoBar(render_process_id, render_view_id);
+
+ InfoBarTabHelper* helper = GetInfoBarHelper(render_process_id,
+ render_view_id);
+ if (!helper) {
bulach 2012/03/22 17:01:46 maybe move 388 after this and add a comment saying
John Knottenbelt 2012/03/22 18:09:02 Done.
+ ClearInfoBarRequestsFromTab(render_process_id, render_view_id);
+ return;
+ }
+ if (!AlreadyShowingQueuedInfoBar(render_process_id, render_view_id))
+ ShowQueuedInfoBar(render_process_id, render_view_id, helper);
}
void GeolocationInfoBarQueueController::CancelInfoBarRequest(
@@ -398,21 +409,7 @@ void GeolocationInfoBarQueueController::CancelInfoBarRequest(
RequestEquals(render_process_id, render_view_id, bridge_id));
// TODO(pkasting): Can this conditional become a DCHECK()?
if (i != pending_infobar_requests_.end())
- CancelInfoBarRequestInternal(i);
-}
-
-void GeolocationInfoBarQueueController::OnInfoBarClosed(int render_process_id,
- int render_view_id,
- int bridge_id) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- PendingInfoBarRequests::iterator i = std::find_if(
- pending_infobar_requests_.begin(), pending_infobar_requests_.end(),
- RequestEquals(render_process_id, render_view_id, bridge_id));
- if (i != pending_infobar_requests_.end())
- pending_infobar_requests_.erase(i);
-
- ShowQueuedInfoBar(render_process_id, render_view_id);
+ CancelInfoBarRequestInternal(i, true);
}
void GeolocationInfoBarQueueController::OnPermissionSet(
@@ -433,108 +430,142 @@ void GeolocationInfoBarQueueController::OnPermissionSet(
std::string(),
content_setting);
+ // Cancel this request first, then notify listeners. TODO(pkasting): Why
+ // is this order important?
+ PendingInfoBarRequests requests_to_notify;
for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
i != pending_infobar_requests_.end(); ) {
if (i->IsForPair(requesting_frame, embedder)) {
- // Cancel this request first, then notify listeners. TODO(pkasting): Why
- // is this order important?
- // NOTE: If the pending request had an infobar, TabContents will close it
- // either synchronously or asynchronously, which will then pump the queue
- // via OnInfoBarClosed().
- PendingInfoBarRequest copied_request = *i;
+ requests_to_notify.push_back(*i);
// Don't let CancelInfoBarRequestInternal() call RemoveInfoBar() with the
// delegate that's currently calling us. That delegate is in either
// Accept() or Cancel(), so its owning InfoBar will call RemoveInfoBar()
// later on in this callstack anyway; and if we do it here, and it causes
// the delegate to be deleted, our GURL& args will point to garbage and we
// may also cause other problems during stack unwinding.
- if (i->Equals(render_process_id, render_view_id, bridge_id))
- i->infobar_delegate = NULL;
- i = CancelInfoBarRequestInternal(i);
-
- geolocation_permission_context_->NotifyPermissionSet(
- copied_request.render_process_id, copied_request.render_view_id,
- copied_request.bridge_id, copied_request.requesting_frame,
- copied_request.callback, allowed);
- } else {
- ++i;
+ if (!i->Equals(render_process_id, render_view_id, bridge_id)) {
+ i = CancelInfoBarRequestInternal(i, true);
+ continue;
+ }
}
+ ++i;
+ }
+
+ for (PendingInfoBarRequests::iterator i = requests_to_notify.begin();
+ i != requests_to_notify.end(); ++i ) {
+ geolocation_permission_context_->NotifyPermissionSet(
+ i->render_process_id, i->render_view_id,
+ i->bridge_id, i->requesting_frame,
+ i->callback, allowed);
}
}
void GeolocationInfoBarQueueController::Observe(
- int type, const content::NotificationSource& source,
+ int type,
+ const content::NotificationSource& source,
const content::NotificationDetails& details) {
- registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- source);
- WebContents* web_contents = content::Source<WebContents>(source).ptr();
+ DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED, type);
+ // We will receive this notification for all infobar closures, so we need to
+ // check whether this is the geolocation infobar we're tracking.
+ InfoBarDelegate* delegate =
+ content::Details<InfoBarRemovedDetails>(details)->first;
+ for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
+ i != pending_infobar_requests_.end(); ++i) {
+ GeolocationConfirmInfoBarDelegate* confirm_delegate = i->infobar_delegate;
+ if (confirm_delegate == delegate) {
+ // We're being called from InfoBarTabHelper, so pass in false to
+ // stop CancelInfoBarRequestInternal calling helper->RemoveInfoBar.
+ CancelInfoBarRequestInternal(i, false);
bulach 2012/03/22 17:01:46 see below, I think it'd be nicer to ShowQueuedInfo
+ return;
+ }
+ }
+}
+
+void GeolocationInfoBarQueueController::ClearInfoBarRequestsFromTab(
+ int render_process_id,
+ int render_view_id) {
for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
- i != pending_infobar_requests_.end();) {
- if (i->infobar_delegate == NULL &&
- web_contents == tab_util::GetWebContentsByID(i->render_process_id,
- i->render_view_id)) {
+ i != pending_infobar_requests_.end(); ) {
+ if (i->IsForTab(render_process_id, render_view_id))
i = pending_infobar_requests_.erase(i);
- } else {
+ else
++i;
- }
}
}
-void GeolocationInfoBarQueueController::ShowQueuedInfoBar(int render_process_id,
- int render_view_id) {
+InfoBarTabHelper* GeolocationInfoBarQueueController::GetInfoBarHelper(
+ int render_process_id,
+ int render_view_id) {
WebContents* tab_contents =
tab_util::GetWebContentsByID(render_process_id, render_view_id);
- TabContentsWrapper* wrapper = NULL;
- if (tab_contents)
- wrapper = TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
+ if (!tab_contents)
+ return NULL;
+ TabContentsWrapper* wrapper =
+ TabContentsWrapper::GetCurrentWrapperForContents(tab_contents);
+ if (!wrapper)
+ return NULL;
+ return wrapper->infobar_tab_helper();
+}
+
+bool GeolocationInfoBarQueueController::AlreadyShowingQueuedInfoBar(
+ int render_process_id,
+ int render_view_id) {
for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
- i != pending_infobar_requests_.end(); ) {
- if (i->IsForTab(render_process_id, render_view_id)) {
- if (!wrapper) {
- i = pending_infobar_requests_.erase(i);
- continue;
- }
+ i != pending_infobar_requests_.end(); ++i) {
+ if (i->IsForTab(render_process_id, render_view_id) && i->infobar_delegate)
+ return true;
+ }
+ return false;
+}
- if (!i->infobar_delegate) {
- if (!registrar_.IsRegistered(
- this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(tab_contents))) {
- registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
- content::Source<WebContents>(tab_contents));
- }
+void GeolocationInfoBarQueueController::ShowQueuedInfoBar(
+ int render_process_id,
+ int render_view_id,
+ InfoBarTabHelper* helper) {
+ DCHECK(helper);
+ DCHECK(!AlreadyShowingQueuedInfoBar(render_process_id, render_view_id));
+ for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin();
+ i != pending_infobar_requests_.end(); ++i) {
+ if (i->IsForTab(render_process_id, render_view_id) &&
+ !i->infobar_delegate) {
+ DCHECK(!registrar_.IsRegistered(
+ this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
+ content::Source<InfoBarTabHelper>(helper)));
+ registrar_.Add(
+ this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
+ content::Source<InfoBarTabHelper>(helper));
i->infobar_delegate = new GeolocationConfirmInfoBarDelegate(
- wrapper->infobar_tab_helper(), this, render_process_id,
+ helper, this, render_process_id,
render_view_id, i->bridge_id, i->requesting_frame,
profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
- wrapper->infobar_tab_helper()->AddInfoBar(i->infobar_delegate);
- }
- break;
+ helper->AddInfoBar(i->infobar_delegate);
+ break;
}
- ++i;
}
}
GeolocationInfoBarQueueController::PendingInfoBarRequests::iterator
GeolocationInfoBarQueueController::CancelInfoBarRequestInternal(
- PendingInfoBarRequests::iterator i) {
+ PendingInfoBarRequests::iterator i,
+ bool remove_showing_infobar) {
InfoBarDelegate* delegate = i->infobar_delegate;
if (!delegate)
return pending_infobar_requests_.erase(i);
-
- WebContents* web_contents =
- tab_util::GetWebContentsByID(i->render_process_id, i->render_view_id);
- if (!web_contents)
+ InfoBarTabHelper* helper = GetInfoBarHelper(i->render_process_id,
+ i->render_view_id);
+ if (!helper)
return pending_infobar_requests_.erase(i);
-
- // WebContents will destroy the InfoBar, which will remove from our vector
- // asynchronously.
- TabContentsWrapper* wrapper =
- TabContentsWrapper::GetCurrentWrapperForContents(web_contents);
- wrapper->infobar_tab_helper()->RemoveInfoBar(i->infobar_delegate);
- return ++i;
+ registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
+ content::Source<InfoBarTabHelper>(helper));
+ if (remove_showing_infobar)
+ helper->RemoveInfoBar(delegate);
+ int render_process_id = i->render_process_id;
+ int render_view_id = i->render_view_id;
+ PendingInfoBarRequests::iterator next = pending_infobar_requests_.erase(i);
+ ShowQueuedInfoBar(render_process_id, render_view_id, helper);
bulach 2012/03/22 17:01:46 hmm.. I'm not sure we want to create the infobar h
+ return next;
}
-
// GeolocationPermissionContext -----------------------------------------------
ChromeGeolocationPermissionContext::ChromeGeolocationPermissionContext(
« no previous file with comments | « no previous file | chrome/browser/geolocation/chrome_geolocation_permission_context_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698