diff options
author | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-11 13:08:52 +0000 |
---|---|---|
committer | bulach@chromium.org <bulach@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-11 13:08:52 +0000 |
commit | 8b4b84eee1eaa6a77c34f66f7278039004657896 (patch) | |
tree | d8ff62fa586a6dc4d5859453037e1821f2a89bc2 /chrome/browser/geolocation | |
parent | 5ea92a92e9fa26334db821da688d3c46e295d19c (diff) | |
download | chromium_src-8b4b84eee1eaa6a77c34f66f7278039004657896.zip chromium_src-8b4b84eee1eaa6a77c34f66f7278039004657896.tar.gz chromium_src-8b4b84eee1eaa6a77c34f66f7278039004657896.tar.bz2 |
Geolocation: checks pending requests with the same origin when receiving the infobar response.
Moves GeolocationPermissionContext from GeolocationDispatcherHost up to profile.
TEST=GeolocationPermissionContextTests.MultipleOrigins or manual: open two tabs from the same origin with geolocation. Check both info bars are created. Reply to only one of them, check the other is gone.
BUG=40527
Review URL: http://codereview.chromium.org/1585036
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46910 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/geolocation')
3 files changed, 343 insertions, 128 deletions
diff --git a/chrome/browser/geolocation/geolocation_permission_context.cc b/chrome/browser/geolocation/geolocation_permission_context.cc index ae8cc0d..a0e76f8 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.cc +++ b/chrome/browser/geolocation/geolocation_permission_context.cc @@ -27,19 +27,73 @@ #include "grit/theme_resources.h" #include "net/base/net_util.h" +// This class controls the geolocation infobar queue per profile, and it's an +// internal class to GeolocationPermissionContext. +// An alternate approach would be to have this queue per tab, and use +// notifications to broadcast when permission is set / listen to notification to +// cancel pending requests. This may be specially useful if there are other +// things listening for such notifications. +// For the time being this class is self-contained and it doesn't seem pulling +// the notification infrastructure would simplify. +class GeolocationInfoBarQueueController { + public: + GeolocationInfoBarQueueController( + GeolocationPermissionContext* geolocation_permission_context, + Profile* profile); + ~GeolocationInfoBarQueueController(); + + // The InfoBar will be displayed immediately if the tab is not already + // displaying one, otherwise it'll be queued. + void CreateInfoBarRequest( + int render_process_id, int render_view_id, int bridge_id, + const GURL& requesting_frame, const GURL& emebedder); + + // Cancels a specific infobar request. + void CancelInfoBarRequest( + int render_process_id, 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. + void OnPermissionSet( + int render_process_id, int render_view_id, int bridge_id, + const GURL& requesting_frame, const GURL& embedder, bool allowed); + + private: + struct PendingInfoBarRequest; + typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests; + + // Shows the first pending infobar for this tab. + void ShowQueuedInfoBar(int render_process_id, int render_view_id); + + // Cancels an InfoBar request and returns the next iterator position. + std::vector<PendingInfoBarRequest>::iterator CancelInfoBarRequestInternal( + std::vector<PendingInfoBarRequest>::iterator i); + + GeolocationPermissionContext* const geolocation_permission_context_; + Profile* const profile_; + // Contains all pending infobar requests. + PendingInfoBarRequests pending_infobar_requests_; +}; + namespace { // This is the delegate used to display the confirmation info bar. class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { public: GeolocationConfirmInfoBarDelegate( - TabContents* tab_contents, GeolocationPermissionContext* context, + TabContents* tab_contents, GeolocationInfoBarQueueController* controller, int render_process_id, int render_view_id, int bridge_id, const GURL& requesting_frame_url, const std::wstring& display_languages) : ConfirmInfoBarDelegate(tab_contents), tab_contents_(tab_contents), - context_(context), + controller_(controller), render_process_id_(render_process_id), render_view_id_(render_view_id), bridge_id_(bridge_id), @@ -49,13 +103,13 @@ class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { // ConfirmInfoBarDelegate virtual void InfoBarClosed() { - context_->OnInfoBarClosed(tab_contents_, render_process_id_, - render_view_id_, bridge_id_); + controller_->OnInfoBarClosed(render_process_id_, render_view_id_, + bridge_id_); delete this; } virtual Type GetInfoBarType() { return INFO_TYPE; } - virtual bool Accept() { return SetPermission(true); } - virtual bool Cancel() { return SetPermission(false); } + virtual bool Accept() { return OnPermissionSet(true); } + virtual bool Cancel() { return OnPermissionSet(false); } virtual int GetButtons() const { return BUTTON_OK | BUTTON_CANCEL; } virtual std::wstring GetButtonLabel(InfoBarButton button) const { switch (button) { @@ -91,15 +145,15 @@ class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { } private: - bool SetPermission(bool confirm) { - context_->SetPermission( + bool OnPermissionSet(bool confirm) { + controller_->OnPermissionSet( render_process_id_, render_view_id_, bridge_id_, requesting_frame_url_, - confirm); + tab_contents_->GetURL(), confirm); return true; } TabContents* tab_contents_; - scoped_refptr<GeolocationPermissionContext> context_; + GeolocationInfoBarQueueController* controller_; int render_process_id_; int render_view_id_; int bridge_id_; @@ -111,11 +165,12 @@ class GeolocationConfirmInfoBarDelegate : public ConfirmInfoBarDelegate { } // namespace -struct GeolocationPermissionContext::PendingInfoBarRequest { +struct GeolocationInfoBarQueueController::PendingInfoBarRequest { int render_process_id; int render_view_id; int bridge_id; GURL requesting_frame; + GURL embedder; // If non-NULL, it's the current geolocation infobar for this tab. InfoBarDelegate* infobar_delegate; @@ -124,6 +179,11 @@ struct GeolocationPermissionContext::PendingInfoBarRequest { render_view_id == p_render_view_id; } + bool IsForPair(const GURL& p_requesting_frame, const GURL& p_embedder) const { + return requesting_frame == p_requesting_frame && + embedder == p_embedder; + } + bool Equals(int p_render_process_id, int p_render_view_id, int p_bridge_id) const { @@ -132,9 +192,133 @@ struct GeolocationPermissionContext::PendingInfoBarRequest { } }; +GeolocationInfoBarQueueController::GeolocationInfoBarQueueController( + GeolocationPermissionContext* geolocation_permission_context, + Profile* profile) + : geolocation_permission_context_(geolocation_permission_context), + profile_(profile) { +} + +GeolocationInfoBarQueueController::~GeolocationInfoBarQueueController() { +} + +void GeolocationInfoBarQueueController::CreateInfoBarRequest( + int render_process_id, int render_view_id, int bridge_id, + const GURL& requesting_frame, const GURL& embedder) { + PendingInfoBarRequest pending_infobar_request; + pending_infobar_request.render_process_id = render_process_id; + pending_infobar_request.render_view_id = render_view_id; + pending_infobar_request.bridge_id = bridge_id; + pending_infobar_request.requesting_frame = requesting_frame; + pending_infobar_request.embedder = embedder; + pending_infobar_request.infobar_delegate = NULL; + pending_infobar_requests_.push_back(pending_infobar_request); + ShowQueuedInfoBar(render_process_id, render_view_id); +} + +void GeolocationInfoBarQueueController::CancelInfoBarRequest( + int render_process_id, int render_view_id, int bridge_id) { + for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); + i != pending_infobar_requests_.end(); ++i) { + if (i->Equals(render_process_id, render_view_id, bridge_id)) { + CancelInfoBarRequestInternal(i); + break; + } + } +} + +void GeolocationInfoBarQueueController::OnInfoBarClosed( + int render_process_id, int render_view_id, int bridge_id) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); + i != pending_infobar_requests_.end(); ++i) { + if (i->Equals(render_process_id, render_view_id, bridge_id)) { + pending_infobar_requests_.erase(i); + break; + } + } + ShowQueuedInfoBar(render_process_id, render_view_id); +} + +void GeolocationInfoBarQueueController::OnPermissionSet( + int render_process_id, int render_view_id, int bridge_id, + const GURL& requesting_frame, const GURL& embedder, bool allowed) { + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); + // Persist the permission. + ContentSetting content_setting = + allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; + profile_->GetGeolocationContentSettingsMap()->SetContentSetting( + requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting); + + // Now notify all pending requests that the permission has been set. + for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); + i != pending_infobar_requests_.end();) { + if (i->IsForPair(requesting_frame, embedder)) { + // There was a pending request for the same [frame, embedder]. + if (i->Equals(render_process_id, render_view_id, bridge_id)) { + // The request that set permission will be removed by TabContents + // itself, that is, we should not try to cancel the infobar that has + // just notified us. + i->infobar_delegate = NULL; + } + // Cancel it first, and then notify the permission. + // Note: if the pending request had an infobar, TabContents will + // eventually close it and we will pump the queue via OnInfoBarClosed(). + PendingInfoBarRequest other_request = *i; + i = CancelInfoBarRequestInternal(i); + geolocation_permission_context_->NotifyPermissionSet( + other_request.render_process_id, other_request.render_view_id, + other_request.bridge_id, other_request.requesting_frame, allowed); + } else { + ++i; + } + } +} + +void GeolocationInfoBarQueueController::ShowQueuedInfoBar( + 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)) { + // Check if already displayed. + if (i->infobar_delegate) + break; + TabContents* tab_contents = + tab_util::GetTabContentsByID(render_process_id, render_view_id); + i->infobar_delegate = + new GeolocationConfirmInfoBarDelegate( + tab_contents, this, + render_process_id, render_view_id, + i->bridge_id, i->requesting_frame, + profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); + tab_contents->AddInfoBar(i->infobar_delegate); + break; + } + } +} + +std::vector<GeolocationInfoBarQueueController::PendingInfoBarRequest>::iterator + GeolocationInfoBarQueueController::CancelInfoBarRequestInternal( + std::vector<PendingInfoBarRequest>::iterator i) { + TabContents* tab_contents = + tab_util::GetTabContentsByID(i->render_process_id, i->render_view_id); + if (tab_contents && i->infobar_delegate) { + // TabContents will destroy the InfoBar, which will remove from our vector + // asynchronously. + tab_contents->RemoveInfoBar(i->infobar_delegate); + return ++i; + } else { + // Remove it directly from the pending vector. + return pending_infobar_requests_.erase(i); + } +} + GeolocationPermissionContext::GeolocationPermissionContext( Profile* profile) - : profile_(profile) { + : profile_(profile), + ALLOW_THIS_IN_INITIALIZER_LIST( + geolocation_infobar_queue_controller_( + new GeolocationInfoBarQueueController(this, profile))) { } GeolocationPermissionContext::~GeolocationPermissionContext() { @@ -200,31 +384,17 @@ void GeolocationPermissionContext::RequestGeolocationPermission( } else if (content_setting == CONTENT_SETTING_ALLOW) { NotifyPermissionSet(render_process_id, render_view_id, bridge_id, requesting_frame, true); - } else { // setting == ask. Prompt the user. - RequestPermissionFromUI(tab_contents, render_process_id, render_view_id, - bridge_id, requesting_frame); + } else { // setting == ask. Prompt the user. + geolocation_infobar_queue_controller_->CreateInfoBarRequest( + render_process_id, render_view_id, bridge_id, requesting_frame, + embedder); } } void GeolocationPermissionContext::CancelGeolocationPermissionRequest( int render_process_id, int render_view_id, int bridge_id, const GURL& requesting_frame) { - CancelPendingInfoBar(render_process_id, render_view_id, bridge_id); -} - -void GeolocationPermissionContext::SetPermission( - int render_process_id, int render_view_id, int bridge_id, - const GURL& requesting_frame, bool allowed) { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - TabContents* tab_contents = - tab_util::GetTabContentsByID(render_process_id, render_view_id); - GURL embedder = tab_contents->GetURL(); - ContentSetting content_setting = - allowed ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK; - profile_->GetGeolocationContentSettingsMap()->SetContentSetting( - requesting_frame.GetOrigin(), embedder.GetOrigin(), content_setting); - NotifyPermissionSet(render_process_id, render_view_id, bridge_id, - requesting_frame, allowed); + CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id); } GeolocationArbitrator* GeolocationPermissionContext::StartUpdatingRequested( @@ -248,36 +418,7 @@ GeolocationArbitrator* GeolocationPermissionContext::StartUpdatingRequested( void GeolocationPermissionContext::StopUpdatingRequested( int render_process_id, int render_view_id, int bridge_id) { - CancelPendingInfoBar(render_process_id, render_view_id, bridge_id); -} - -void GeolocationPermissionContext::OnInfoBarClosed( - TabContents* tab_contents, int render_process_id, int render_view_id, - int bridge_id) { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); - i != pending_infobar_requests_.end(); ++i) { - if (i->Equals(render_process_id, render_view_id, bridge_id)) { - pending_infobar_requests_.erase(i); - break; - } - } - // Now process the queued infobars, if any. - ShowQueuedInfoBar(tab_contents, render_process_id, render_view_id); -} - -void GeolocationPermissionContext::RequestPermissionFromUI( - TabContents* tab_contents, int render_process_id, int render_view_id, - int bridge_id, const GURL& requesting_frame) { - DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - PendingInfoBarRequest pending_infobar_request; - pending_infobar_request.render_process_id = render_process_id; - pending_infobar_request.render_view_id = render_view_id; - pending_infobar_request.bridge_id = bridge_id; - pending_infobar_request.requesting_frame = requesting_frame; - pending_infobar_request.infobar_delegate = NULL; - pending_infobar_requests_.push_back(pending_infobar_request); - ShowQueuedInfoBar(tab_contents, render_process_id, render_view_id); + CancelPendingInfoBarRequest(render_process_id, render_view_id, bridge_id); } void GeolocationPermissionContext::NotifyPermissionSet( @@ -311,49 +452,17 @@ void GeolocationPermissionContext::NotifyArbitratorPermissionGranted( GeolocationArbitrator::GetInstance()->OnPermissionGranted(requesting_frame); } -void GeolocationPermissionContext::ShowQueuedInfoBar( - TabContents* tab_contents, 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)) { - // Check if already displayed. - if (i->infobar_delegate) - break; - i->infobar_delegate = - new GeolocationConfirmInfoBarDelegate( - tab_contents, this, render_process_id, render_view_id, - i->bridge_id, i->requesting_frame, - profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); - tab_contents->AddInfoBar(i->infobar_delegate); - break; - } - } -} - -void GeolocationPermissionContext::CancelPendingInfoBar( +void GeolocationPermissionContext::CancelPendingInfoBarRequest( int render_process_id, int render_view_id, int bridge_id) { if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) { ChromeThread::PostTask( ChromeThread::UI, FROM_HERE, NewRunnableMethod(this, - &GeolocationPermissionContext::CancelPendingInfoBar, + &GeolocationPermissionContext::CancelPendingInfoBarRequest, render_process_id, render_view_id, bridge_id)); - return; + return; } DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); - for (PendingInfoBarRequests::iterator i = pending_infobar_requests_.begin(); - i != pending_infobar_requests_.end(); ++i) { - if (i->Equals(render_process_id, render_view_id, bridge_id)) { - TabContents* tab_contents = - tab_util::GetTabContentsByID(render_process_id, render_view_id); - if (tab_contents && i->infobar_delegate) { - // Removing an infobar will remove it from the pending vector. - tab_contents->RemoveInfoBar(i->infobar_delegate); - } else { - // Remove it directly from the pending vector. - pending_infobar_requests_.erase(i); - } - break; - } - } + geolocation_infobar_queue_controller_->CancelInfoBarRequest( + render_process_id, render_view_id, bridge_id); } diff --git a/chrome/browser/geolocation/geolocation_permission_context.h b/chrome/browser/geolocation/geolocation_permission_context.h index d8b5fa3..d3f3e37 100644 --- a/chrome/browser/geolocation/geolocation_permission_context.h +++ b/chrome/browser/geolocation/geolocation_permission_context.h @@ -9,8 +9,11 @@ #include "base/basictypes.h" #include "base/file_path.h" #include "base/ref_counted.h" +#include "base/scoped_ptr.h" class GeolocationDispatcherHost; +class GeolocationInfoBarQueueController; +class GeolocationPermissionContext; class GURL; class GeolocationArbitrator; class InfoBarDelegate; @@ -19,7 +22,7 @@ class RenderViewHost; class TabContents; // GeolocationPermissionContext manages Geolocation permissions flow, -// creating UI elements to ask the user for permission when necessary. +// and delegates UI handling via GeolocationInfoBarQueueController. // It always notifies the requesting render_view asynchronously via // ViewMsg_Geolocation_PermissionSet. class GeolocationPermissionContext @@ -38,9 +41,9 @@ class GeolocationPermissionContext int render_process_id, int render_view_id, int bridge_id, const GURL& requesting_frame); - // Called once the user sets the geolocation permission. - // It'll notify the render via ViewMsg_Geolocation_PermissionSet. - void SetPermission( + // Notifies whether or not the corresponding bridge is allowed to use + // geolocation via ViewMsg_Geolocation_PermissionSet. + void NotifyPermissionSet( int render_process_id, int render_view_id, int bridge_id, const GURL& requesting_frame, bool allowed); @@ -62,42 +65,22 @@ class GeolocationPermissionContext void StopUpdatingRequested( int render_process_id, int render_view_id, int bridge_id); - // Called by the InfoBarDelegate to notify it's closed. - void OnInfoBarClosed( - TabContents* tab_contents, int render_process_id, int render_view_id, - int bridge_id); - private: - struct PendingInfoBarRequest; friend class base::RefCountedThreadSafe<GeolocationPermissionContext>; virtual ~GeolocationPermissionContext(); - // Triggers (or queues) the associated UI element to request permission. - void RequestPermissionFromUI( - TabContents* tab_contents, int render_process_id, int render_view_id, - int bridge_id, const GURL& requesting_frame); - - // Notifies whether or not the corresponding render is allowed to use - // geolocation. - void NotifyPermissionSet( - int render_process_id, int render_view_id, int bridge_id, - const GURL& requesting_frame, bool allowed); - // Calls GeolocationArbitrator::OnPermissionGranted. void NotifyArbitratorPermissionGranted(const GURL& requesting_frame); - // Shows an infobar if there's any pending for this tab. - void ShowQueuedInfoBar(TabContents* tab_contents, int render_process_id, - int render_view_id); - - void CancelPendingInfoBar( + // Removes any pending InfoBar request. + void CancelPendingInfoBarRequest( int render_process_id, int render_view_id, int bridge_id); // This should only be accessed from the UI thread. Profile* const profile_; - typedef std::vector<PendingInfoBarRequest> PendingInfoBarRequests; - PendingInfoBarRequests pending_infobar_requests_; + scoped_ptr<GeolocationInfoBarQueueController> + geolocation_infobar_queue_controller_; DISALLOW_COPY_AND_ASSIGN(GeolocationPermissionContext); }; diff --git a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc index b17f337..e8d631d 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_unittest.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_unittest.cc @@ -4,6 +4,7 @@ #include "chrome/browser/geolocation/geolocation_permission_context.h" +#include "base/scoped_vector.h" #include "chrome/browser/geolocation/location_arbitrator.h" #include "chrome/browser/geolocation/location_provider.h" #include "chrome/browser/geolocation/mock_location_provider.h" @@ -76,10 +77,16 @@ class GeolocationPermissionContextTests : public RenderViewHostTestHarness { int process_id() { return contents()->render_view_host()->process()->id(); } + int process_id_for_tab(int tab) { + return extra_tabs_[tab]->render_view_host()->process()->id(); + } int render_id() { return contents()->render_view_host()->routing_id(); } + int render_id_for_tab(int tab) { + return extra_tabs_[tab]->render_view_host()->routing_id(); + } int bridge_id() { // Bridge id is not relevant at this level. @@ -87,17 +94,38 @@ class GeolocationPermissionContextTests : public RenderViewHostTestHarness { } void CheckPermissionMessageSent(int bridge_id, bool allowed) { + CheckPermissionMessageSentInternal(process(), bridge_id, allowed); + } + void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed) { + CheckPermissionMessageSentInternal( + static_cast<MockRenderProcessHost*>( + extra_tabs_[tab]->render_view_host()->process()), + bridge_id, allowed); + } + + void CheckPermissionMessageSentInternal(MockRenderProcessHost* process, + int bridge_id, + bool allowed) { MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); MessageLoop::current()->Run(); const IPC::Message* message = - process()->sink().GetFirstMessageMatching( + process->sink().GetFirstMessageMatching( ViewMsg_Geolocation_PermissionSet::ID); ASSERT_TRUE(message); ViewMsg_Geolocation_PermissionSet::Param param; ViewMsg_Geolocation_PermissionSet::Read(message, ¶m); EXPECT_EQ(bridge_id, param.a); EXPECT_EQ(allowed, param.b); - process()->sink().ClearMessages(); + process->sink().ClearMessages(); + } + + void AddNewTab(const GURL& url) { + TestTabContentsWithPendingInfoBar* new_tab = + new TestTabContentsWithPendingInfoBar(profile(), NULL); + new_tab->controller().LoadURL(url, GURL(), PageTransition::TYPED); + static_cast<TestRenderViewHost*>(new_tab->render_manager()-> + current_host())->SendNavigate(extra_tabs_.size() + 1, url); + extra_tabs_.push_back(new_tab); } void CheckTabContentsState(const GURL& requesting_frame, @@ -120,6 +148,7 @@ class GeolocationPermissionContextTests : public RenderViewHostTestHarness { ChromeThread ui_thread_; TestTabContentsWithPendingInfoBar* tab_contents_with_pending_infobar_; scoped_refptr<GeolocationPermissionContext> geolocation_permission_context_; + ScopedVector<TestTabContentsWithPendingInfoBar> extra_tabs_; }; TEST_F(GeolocationPermissionContextTests, SinglePermission) { @@ -154,6 +183,7 @@ TEST_F(GeolocationPermissionContextTests, QueuedPermission) { EXPECT_EQ(1, contents()->infobar_delegate_count()); ConfirmInfoBarDelegate* infobar_0 = contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_0); std::wstring text_0 = infobar_0->GetMessageText(); // Accept the first frame. @@ -170,6 +200,7 @@ TEST_F(GeolocationPermissionContextTests, QueuedPermission) { ConfirmInfoBarDelegate* infobar_1 = contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_1); std::wstring text_1 = infobar_1->GetMessageText(); EXPECT_NE(text_0, text_1); @@ -216,6 +247,7 @@ TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) { ConfirmInfoBarDelegate* infobar_0 = contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_0); std::wstring text_0 = infobar_0->GetMessageText(); // Simulate the frame going away, ensure the infobar for this frame @@ -229,6 +261,7 @@ TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) { ConfirmInfoBarDelegate* infobar_1 = contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_1); std::wstring text_1 = infobar_1->GetMessageText(); EXPECT_NE(text_0, text_1); @@ -261,6 +294,7 @@ TEST_F(GeolocationPermissionContextTests, StopUpdating) { EXPECT_EQ(1, contents()->infobar_delegate_count()); ConfirmInfoBarDelegate* infobar_0 = contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_0); geolocation_permission_context_->StopUpdatingRequested( process_id(), render_id(), bridge_id()); @@ -284,3 +318,92 @@ TEST_F(GeolocationPermissionContextTests, InvalidURL) { EXPECT_EQ(0, contents()->infobar_delegate_count()); CheckPermissionMessageSent(bridge_id(), false); } + +TEST_F(GeolocationPermissionContextTests, SameOriginMultipleTabs) { + GURL url_a("http://www.example.com/geolocation"); + GURL url_b("http://www.example-2.com/geolocation"); + NavigateAndCommit(url_a); + AddNewTab(url_b); + AddNewTab(url_a); + + EXPECT_EQ(0, contents()->infobar_delegate_count()); + geolocation_permission_context_->RequestGeolocationPermission( + process_id(), render_id(), bridge_id(), url_a); + EXPECT_EQ(1, contents()->infobar_delegate_count()); + + geolocation_permission_context_->RequestGeolocationPermission( + process_id_for_tab(0), render_id_for_tab(0), bridge_id(), url_b); + EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count()); + + geolocation_permission_context_->RequestGeolocationPermission( + process_id_for_tab(1), render_id_for_tab(1), bridge_id(), url_a); + EXPECT_EQ(1, extra_tabs_[1]->infobar_delegate_count()); + + // Accept the first tab. + ConfirmInfoBarDelegate* infobar_0 = + contents()->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_0); + infobar_0->Accept(); + CheckPermissionMessageSent(bridge_id(), true); + contents()->RemoveInfoBar(infobar_0); + EXPECT_EQ(infobar_0, + tab_contents_with_pending_infobar_->removed_infobar_delegate_); + infobar_0->InfoBarClosed(); + // Now the infobar for the tab with the same origin should have gone. + EXPECT_EQ(0, extra_tabs_[1]->infobar_delegate_count()); + CheckPermissionMessageSentForTab(1, bridge_id(), true); + + // But the other tab should still have the info bar... + EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count()); + extra_tabs_.reset(); +} + +TEST_F(GeolocationPermissionContextTests, QueuedOriginMultipleTabs) { + GURL url_a("http://www.example.com/geolocation"); + GURL url_b("http://www.example-2.com/geolocation"); + NavigateAndCommit(url_a); + AddNewTab(url_a); + + EXPECT_EQ(0, contents()->infobar_delegate_count()); + geolocation_permission_context_->RequestGeolocationPermission( + process_id(), render_id(), bridge_id(), url_a); + EXPECT_EQ(1, contents()->infobar_delegate_count()); + + geolocation_permission_context_->RequestGeolocationPermission( + process_id_for_tab(0), render_id_for_tab(0), bridge_id(), url_a); + EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count()); + + geolocation_permission_context_->RequestGeolocationPermission( + process_id_for_tab(0), render_id_for_tab(0), bridge_id() + 1, url_b); + EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count()); + + // Accept the second tab. + ConfirmInfoBarDelegate* infobar_0 = + extra_tabs_[0]->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_0); + infobar_0->Accept(); + CheckPermissionMessageSentForTab(0, bridge_id(), true); + extra_tabs_[0]->RemoveInfoBar(infobar_0); + EXPECT_EQ(infobar_0, + extra_tabs_[0]->removed_infobar_delegate_); + infobar_0->InfoBarClosed(); + // Now the infobar for the tab with the same origin should have gone. + EXPECT_EQ(0, contents()->infobar_delegate_count()); + CheckPermissionMessageSent(bridge_id(), true); + + // And we should have the queued infobar displayed now. + EXPECT_EQ(1, extra_tabs_[0]->infobar_delegate_count()); + + // Accept the second infobar. + ConfirmInfoBarDelegate* infobar_1 = + extra_tabs_[0]->GetInfoBarDelegateAt(0)->AsConfirmInfoBarDelegate(); + ASSERT_TRUE(infobar_1); + infobar_1->Accept(); + CheckPermissionMessageSentForTab(0, bridge_id() + 1, true); + extra_tabs_[0]->RemoveInfoBar(infobar_1); + EXPECT_EQ(infobar_1, + extra_tabs_[0]->removed_infobar_delegate_); + infobar_1->InfoBarClosed(); + + extra_tabs_.reset(); +} |