Index: chrome/browser/geolocation/geolocation_infobar_queue_controller.cc |
=================================================================== |
--- chrome/browser/geolocation/geolocation_infobar_queue_controller.cc (revision 163741) |
+++ chrome/browser/geolocation/geolocation_infobar_queue_controller.cc (working copy) |
@@ -21,103 +21,90 @@ |
#include "content/public/browser/notification_types.h" |
#include "content/public/browser/web_contents.h" |
-using content::BrowserThread; |
-using content::WebContents; |
+// Utilities ------------------------------------------------------------------ |
+ |
+namespace { |
+ |
+InfoBarTabHelper* GetInfoBarHelper(const GeolocationPermissionRequestID& id) { |
+ content::WebContents* web_contents = |
+ tab_util::GetWebContentsByID(id.render_process_id(), id.render_view_id()); |
+ return web_contents ? InfoBarTabHelper::FromWebContents(web_contents) : NULL; |
+} |
+ |
+} |
+ |
+ |
// GeolocationInfoBarQueueController::PendingInfoBarRequest ------------------- |
-struct GeolocationInfoBarQueueController::PendingInfoBarRequest { |
+class GeolocationInfoBarQueueController::PendingInfoBarRequest { |
public: |
- PendingInfoBarRequest(int render_process_id, |
- int render_view_id, |
- int bridge_id, |
+ PendingInfoBarRequest(const GeolocationPermissionRequestID& id, |
const GURL& requesting_frame, |
const GURL& embedder, |
PermissionDecidedCallback callback); |
+ ~PendingInfoBarRequest(); |
- bool IsForTab(int p_render_process_id, int p_render_view_id) const; |
- bool IsForPair(const GURL& p_requesting_frame, |
- const GURL& p_embedder) const; |
- bool Equals(int p_render_process_id, |
- int p_render_view_id, |
- int p_bridge_id) const; |
+ bool IsForPair(const GURL& requesting_frame, |
+ const GURL& embedder) const; |
- int render_process_id; |
- int render_view_id; |
- int bridge_id; |
- GURL requesting_frame; |
- GURL embedder; |
- PermissionDecidedCallback callback; |
- GeolocationConfirmInfoBarDelegate* infobar_delegate; |
+ const GeolocationPermissionRequestID& id() const { return id_; } |
+ const GURL& requesting_frame() const { return requesting_frame_; } |
+ bool has_infobar_delegate() const { return !!infobar_delegate_; } |
+ GeolocationConfirmInfoBarDelegate* infobar_delegate() { |
+ return infobar_delegate_; |
+ } |
+ |
+ void RunCallback(bool allowed); |
+ void CreateInfoBarDelegate(GeolocationInfoBarQueueController* controller, |
+ const std::string& display_languages); |
+ |
+ private: |
+ GeolocationPermissionRequestID id_; |
+ GURL requesting_frame_; |
+ GURL embedder_; |
+ PermissionDecidedCallback callback_; |
+ GeolocationConfirmInfoBarDelegate* infobar_delegate_; |
+ |
+ // Purposefully do not disable copying, as this is stored in STL containers. |
}; |
GeolocationInfoBarQueueController::PendingInfoBarRequest::PendingInfoBarRequest( |
- int render_process_id, |
- int render_view_id, |
- int bridge_id, |
+ const GeolocationPermissionRequestID& id, |
const GURL& requesting_frame, |
const GURL& embedder, |
PermissionDecidedCallback callback) |
- : render_process_id(render_process_id), |
- render_view_id(render_view_id), |
- bridge_id(bridge_id), |
- requesting_frame(requesting_frame), |
- embedder(embedder), |
- callback(callback), |
- infobar_delegate(NULL) { |
+ : id_(id), |
+ requesting_frame_(requesting_frame), |
+ embedder_(embedder), |
+ callback_(callback), |
+ infobar_delegate_(NULL) { |
} |
-bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForTab( |
- int p_render_process_id, |
- int p_render_view_id) const { |
- return (render_process_id == p_render_process_id) && |
- (render_view_id == p_render_view_id); |
+GeolocationInfoBarQueueController::PendingInfoBarRequest:: |
+ ~PendingInfoBarRequest() { |
} |
bool GeolocationInfoBarQueueController::PendingInfoBarRequest::IsForPair( |
- const GURL& p_requesting_frame, |
- const GURL& p_embedder) const { |
- return (requesting_frame == p_requesting_frame) && (embedder == p_embedder); |
+ const GURL& requesting_frame, |
+ const GURL& embedder) const { |
+ return (requesting_frame_ == requesting_frame) && (embedder_ == embedder); |
} |
-bool GeolocationInfoBarQueueController::PendingInfoBarRequest::Equals( |
- int p_render_process_id, |
- int p_render_view_id, |
- int p_bridge_id) const { |
- return IsForTab(p_render_process_id, p_render_view_id) && |
- (bridge_id == p_bridge_id); |
+void GeolocationInfoBarQueueController::PendingInfoBarRequest::RunCallback( |
+ bool allowed) { |
+ callback_.Run(allowed); |
} |
+void GeolocationInfoBarQueueController::PendingInfoBarRequest:: |
+ CreateInfoBarDelegate(GeolocationInfoBarQueueController* controller, |
+ const std::string& display_languages) { |
+ infobar_delegate_ = GeolocationConfirmInfoBarDelegateFactory::Create( |
+ GetInfoBarHelper(id_), controller, id_, requesting_frame_, |
+ display_languages); |
-// GeolocationInfoBarQueueController::RequestEquals --------------------------- |
- |
-// Useful predicate for checking PendingInfoBarRequest equality. |
-class GeolocationInfoBarQueueController::RequestEquals |
- : public std::unary_function<PendingInfoBarRequest, bool> { |
- public: |
- RequestEquals(int render_process_id, int render_view_id, int bridge_id); |
- |
- bool operator()(const PendingInfoBarRequest& request) const; |
- |
- private: |
- int render_process_id_; |
- int render_view_id_; |
- int bridge_id_; |
-}; |
- |
-GeolocationInfoBarQueueController::RequestEquals::RequestEquals( |
- int render_process_id, |
- int render_view_id, |
- int bridge_id) |
- : render_process_id_(render_process_id), |
- render_view_id_(render_view_id), |
- bridge_id_(bridge_id) { |
} |
-bool GeolocationInfoBarQueueController::RequestEquals::operator()( |
- const PendingInfoBarRequest& request) const { |
- return request.Equals(render_process_id_, render_view_id_, bridge_id_); |
-} |
// GeolocationInfoBarQueueController ------------------------------------------ |
@@ -130,65 +117,48 @@ |
} |
void GeolocationInfoBarQueueController::CreateInfoBarRequest( |
- int render_process_id, |
- int render_view_id, |
- int bridge_id, |
+ const GeolocationPermissionRequestID& id, |
const GURL& requesting_frame, |
const GURL& embedder, |
PermissionDecidedCallback callback) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
// We shouldn't get duplicate requests. |
- DCHECK(std::find_if(pending_infobar_requests_.begin(), |
- pending_infobar_requests_.end(), |
- RequestEquals(render_process_id, render_view_id, bridge_id)) == |
- pending_infobar_requests_.end()); |
+ for (PendingInfoBarRequests::const_iterator i( |
+ pending_infobar_requests_.begin()); |
+ i != pending_infobar_requests_.end(); ++i) |
+ DCHECK(!i->id().Equals(id)); |
- InfoBarTabHelper* helper = GetInfoBarHelper(render_process_id, |
- render_view_id); |
- if (!helper) { |
- // We won't be able to create any infobars, shortcut and remove any pending |
- // requests. |
- ClearPendingInfoBarRequestsForTab(render_process_id, render_view_id); |
- return; |
- } |
- pending_infobar_requests_.push_back(PendingInfoBarRequest(render_process_id, |
- render_view_id, bridge_id, requesting_frame, embedder, callback)); |
- if (!AlreadyShowingInfoBar(render_process_id, render_view_id)) |
- ShowQueuedInfoBar(render_process_id, render_view_id, helper); |
+ pending_infobar_requests_.push_back(PendingInfoBarRequest( |
+ id, requesting_frame, embedder, callback)); |
+ if (!AlreadyShowingInfoBarForTab(id)) |
+ ShowQueuedInfoBarForTab(id); |
} |
void GeolocationInfoBarQueueController::CancelInfoBarRequest( |
- int render_process_id, |
- int render_view_id, |
- int bridge_id) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ const GeolocationPermissionRequestID& id) { |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::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)); |
- // TODO(pkasting): Can this conditional become a DCHECK()? |
- if (i == pending_infobar_requests_.end()) |
- return; |
- InfoBarDelegate* delegate = i->infobar_delegate; |
- if (!delegate) { |
- pending_infobar_requests_.erase(i); |
- return; |
+ for (PendingInfoBarRequests::iterator i(pending_infobar_requests_.begin()); |
+ i != pending_infobar_requests_.end(); ++i) { |
+ if (i->id().Equals(id)) { |
+ if (i->has_infobar_delegate()) |
+ GetInfoBarHelper(id)->RemoveInfoBar(i->infobar_delegate()); |
+ else |
+ pending_infobar_requests_.erase(i); |
+ return; |
+ } |
} |
- InfoBarTabHelper* helper = GetInfoBarHelper(render_process_id, |
- render_view_id); |
- helper->RemoveInfoBar(delegate); |
} |
void GeolocationInfoBarQueueController::OnPermissionSet( |
- int render_process_id, |
- int render_view_id, |
- int bridge_id, |
+ const GeolocationPermissionRequestID& id, |
const GURL& requesting_frame, |
const GURL& embedder, |
bool update_content_setting, |
bool allowed) { |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
+ |
if (update_content_setting) { |
ContentSetting content_setting = |
allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; |
@@ -199,6 +169,7 @@ |
std::string(), |
content_setting); |
} |
+ |
// Cancel this request first, then notify listeners. TODO(pkasting): Why |
// is this order important? |
PendingInfoBarRequests requests_to_notify; |
@@ -207,13 +178,13 @@ |
i != pending_infobar_requests_.end(); ) { |
if (i->IsForPair(requesting_frame, embedder)) { |
requests_to_notify.push_back(*i); |
- if (i->Equals(render_process_id, render_view_id, bridge_id)) { |
+ if (i->id().Equals(id)) { |
// The delegate that called us is i, and it's currently in either |
// Accept() or Cancel(). This means that the owning InfoBar will call |
// RemoveInfoBar() later on, and that will trigger a notification we're |
// observing. |
++i; |
- } else if (i->infobar_delegate) { |
+ } else if (i->has_infobar_delegate()) { |
// This InfoBar is for the same frame/embedder pair, but in a different |
// tab. We should remove it now that we've got an answer for it. |
infobars_to_remove.push_back(*i); |
@@ -229,17 +200,13 @@ |
// Remove all InfoBars for the same |requesting_frame| and |embedder|. |
for (PendingInfoBarRequests::iterator i = infobars_to_remove.begin(); |
- i != infobars_to_remove.end(); ++i ) { |
- InfoBarTabHelper* helper = GetInfoBarHelper(i->render_process_id, |
- i->render_view_id); |
- helper->RemoveInfoBar(i->infobar_delegate); |
- } |
+ i != infobars_to_remove.end(); ++i) |
+ GetInfoBarHelper(i->id())->RemoveInfoBar(i->infobar_delegate()); |
// Send out the permission notifications. |
for (PendingInfoBarRequests::iterator i = requests_to_notify.begin(); |
- i != requests_to_notify.end(); ++i ) { |
- i->callback.Run(allowed); |
- } |
+ i != requests_to_notify.end(); ++i) |
+ i->RunCallback(allowed); |
} |
void GeolocationInfoBarQueueController::Observe( |
@@ -260,86 +227,68 @@ |
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; |
+ GeolocationConfirmInfoBarDelegate* confirm_delegate = i->infobar_delegate(); |
if (confirm_delegate == delegate) { |
- InfoBarTabHelper* helper = |
- content::Source<InfoBarTabHelper>(source).ptr(); |
- int render_process_id = i->render_process_id; |
- int render_view_id = i->render_view_id; |
+ GeolocationPermissionRequestID id(i->id()); |
pending_infobar_requests_.erase(i); |
- ShowQueuedInfoBar(render_process_id, render_view_id, helper); |
+ ShowQueuedInfoBarForTab(id); |
return; |
} |
} |
} |
-GeolocationConfirmInfoBarDelegate* |
-GeolocationInfoBarQueueController::CreateInfoBarDelegate( |
- InfoBarTabHelper* infobar_helper, |
- GeolocationInfoBarQueueController* controller, |
- int render_process_id, |
- int render_view_id, |
- int bridge_id, |
- const GURL& requesting_frame_url, |
- const std::string& display_languages) { |
- return GeolocationConfirmInfoBarDelegateFactory::Create( |
- infobar_helper, controller, render_process_id, render_view_id, bridge_id, |
- requesting_frame_url, display_languages); |
+bool GeolocationInfoBarQueueController::AlreadyShowingInfoBarForTab( |
+ const GeolocationPermissionRequestID& id) const { |
+ for (PendingInfoBarRequests::const_iterator i( |
+ pending_infobar_requests_.begin()); |
+ i != pending_infobar_requests_.end(); ++i) { |
+ if (i->id().IsForSameTabAs(id) && i->has_infobar_delegate()) |
+ return true; |
+ } |
+ return false; |
} |
-void GeolocationInfoBarQueueController::ShowQueuedInfoBar( |
- int render_process_id, |
- int render_view_id, |
- InfoBarTabHelper* helper) { |
- DCHECK(helper); |
- DCHECK(!AlreadyShowingInfoBar(render_process_id, render_view_id)); |
+void GeolocationInfoBarQueueController::ShowQueuedInfoBarForTab( |
+ const GeolocationPermissionRequestID& id) { |
+ DCHECK(!AlreadyShowingInfoBarForTab(id)); |
+ |
+ InfoBarTabHelper* helper = GetInfoBarHelper(id); |
+ if (!helper) { |
+ // We can get here for example during tab shutdown, when the |
+ // InfoBarTabHelper is removing all existing infobars, thus calling back to |
+ // Observe(). In this case the helper still exists, and is supplied as the |
+ // source of the notification we observed, but is no longer accessible from |
+ // its WebContents. In this case we should just go ahead and cancel further |
+ // infobars for this tab instead of trying to access the helper. |
+ ClearPendingInfoBarRequestsForTab(id); |
+ return; |
+ } |
+ |
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) { |
+ if (i->id().IsForSameTabAs(id) && !i->has_infobar_delegate()) { |
RegisterForInfoBarNotifications(helper); |
- i->infobar_delegate = CreateInfoBarDelegate( |
- helper, this, render_process_id, |
- render_view_id, i->bridge_id, i->requesting_frame, |
- profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
- helper->AddInfoBar(i->infobar_delegate); |
+ i->CreateInfoBarDelegate( |
+ this, profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
+ helper->AddInfoBar(i->infobar_delegate()); |
return; |
} |
} |
+ |
UnregisterForInfoBarNotifications(helper); |
} |
void GeolocationInfoBarQueueController::ClearPendingInfoBarRequestsForTab( |
- int render_process_id, |
- int render_view_id) { |
+ const GeolocationPermissionRequestID& id) { |
for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); |
i != pending_infobar_requests_.end(); ) { |
- if (i->IsForTab(render_process_id, render_view_id)) |
+ if (i->id().IsForSameTabAs(id)) |
i = pending_infobar_requests_.erase(i); |
else |
++i; |
} |
} |
-InfoBarTabHelper* GeolocationInfoBarQueueController::GetInfoBarHelper( |
- int render_process_id, |
- int render_view_id) { |
- WebContents* web_contents = |
- tab_util::GetWebContentsByID(render_process_id, render_view_id); |
- return web_contents ? InfoBarTabHelper::FromWebContents(web_contents) : NULL; |
-} |
- |
-bool GeolocationInfoBarQueueController::AlreadyShowingInfoBar( |
- int render_process_id, |
- int 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) |
- return true; |
- } |
- return false; |
-} |
- |
void GeolocationInfoBarQueueController::RegisterForInfoBarNotifications( |
InfoBarTabHelper* helper) { |
if (!registrar_.IsRegistered( |