| 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(
|
|
|