blob: 7879ea29006e9ede310b72e7704a752a7dff535c [file] [log] [blame]
// 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 "chrome/browser/geolocation/chrome_geolocation_permission_context.h"
#include <set>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_vector.h"
#include "base/synchronization/waitable_event.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map.h"
#include "chrome/browser/content_settings/permission_request_id.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/geolocation/chrome_geolocation_permission_context_factory.h"
#include "chrome/browser/infobars/confirm_infobar_delegate.h"
#include "chrome/browser/infobars/infobar.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_renderer_host.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/view_type_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#if defined(OS_ANDROID)
#include "base/prefs/pref_service.h"
#include "chrome/browser/android/mock_google_location_settings_helper.h"
#include "chrome/common/pref_names.h"
#endif
using content::MockRenderProcessHost;
// ClosedInfoBarTracker -------------------------------------------------------
// We need to track which infobars were closed.
class ClosedInfoBarTracker : public content::NotificationObserver {
public:
ClosedInfoBarTracker();
virtual ~ClosedInfoBarTracker();
// content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
size_t size() const { return removed_infobars_.size(); }
bool Contains(InfoBarDelegate* infobar) const;
void Clear();
private:
FRIEND_TEST_ALL_PREFIXES(GeolocationPermissionContextTests, TabDestroyed);
content::NotificationRegistrar registrar_;
std::set<InfoBarDelegate*> removed_infobars_;
};
ClosedInfoBarTracker::ClosedInfoBarTracker() {
registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
content::NotificationService::AllSources());
}
ClosedInfoBarTracker::~ClosedInfoBarTracker() {
}
void ClosedInfoBarTracker::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(type == chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED);
removed_infobars_.insert(
content::Details<InfoBarRemovedDetails>(details)->first);
}
bool ClosedInfoBarTracker::Contains(InfoBarDelegate* infobar) const {
return removed_infobars_.count(infobar) != 0;
}
void ClosedInfoBarTracker::Clear() {
removed_infobars_.clear();
}
// GeolocationPermissionContextTests ------------------------------------------
class GeolocationPermissionContextTests
: public ChromeRenderViewHostTestHarness {
protected:
// ChromeRenderViewHostTestHarness:
virtual void SetUp() OVERRIDE;
virtual void TearDown() OVERRIDE;
PermissionRequestID RequestID(int bridge_id);
PermissionRequestID RequestIDForTab(int tab, int bridge_id);
InfoBarService* infobar_service() {
return InfoBarService::FromWebContents(web_contents());
}
InfoBarService* infobar_service_for_tab(int tab) {
return InfoBarService::FromWebContents(extra_tabs_[tab]);
}
void RequestGeolocationPermission(const PermissionRequestID& id,
const GURL& requesting_frame);
void CancelGeolocationPermissionRequest(const PermissionRequestID& id,
const GURL& requesting_frame);
void PermissionResponse(const PermissionRequestID& id,
bool allowed);
void CheckPermissionMessageSent(int bridge_id, bool allowed);
void CheckPermissionMessageSentForTab(int tab, int bridge_id, bool allowed);
void CheckPermissionMessageSentInternal(MockRenderProcessHost* process,
int bridge_id,
bool allowed);
void AddNewTab(const GURL& url);
void CheckTabContentsState(const GURL& requesting_frame,
ContentSetting expected_content_setting);
scoped_refptr<ChromeGeolocationPermissionContext>
geolocation_permission_context_;
ClosedInfoBarTracker closed_infobar_tracker_;
ScopedVector<content::WebContents> extra_tabs_;
// A map between renderer child id and a pair represending the bridge id and
// whether the requested permission was allowed.
base::hash_map<int, std::pair<int, bool> > responses_;
};
PermissionRequestID GeolocationPermissionContextTests::RequestID(
int bridge_id) {
return PermissionRequestID(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetRenderViewHost()->GetRoutingID(),
bridge_id);
}
PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab(
int tab,
int bridge_id) {
return PermissionRequestID(
extra_tabs_[tab]->GetRenderProcessHost()->GetID(),
extra_tabs_[tab]->GetRenderViewHost()->GetRoutingID(),
bridge_id);
}
void GeolocationPermissionContextTests::RequestGeolocationPermission(
const PermissionRequestID& id,
const GURL& requesting_frame) {
geolocation_permission_context_->RequestGeolocationPermission(
id.render_process_id(), id.render_view_id(), id.bridge_id(),
requesting_frame,
base::Bind(&GeolocationPermissionContextTests::PermissionResponse,
base::Unretained(this), id));
}
void GeolocationPermissionContextTests::CancelGeolocationPermissionRequest(
const PermissionRequestID& id,
const GURL& requesting_frame) {
geolocation_permission_context_->CancelGeolocationPermissionRequest(
id.render_process_id(), id.render_view_id(), id.bridge_id(),
requesting_frame);
}
void GeolocationPermissionContextTests::PermissionResponse(
const PermissionRequestID& id,
bool allowed) {
responses_[id.render_process_id()] = std::make_pair(id.bridge_id(), allowed);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSent(
int bridge_id,
bool allowed) {
CheckPermissionMessageSentInternal(process(), bridge_id, allowed);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab(
int tab,
int bridge_id,
bool allowed) {
CheckPermissionMessageSentInternal(static_cast<MockRenderProcessHost*>(
extra_tabs_[tab]->GetRenderProcessHost()),
bridge_id, allowed);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal(
MockRenderProcessHost* process,
int bridge_id,
bool allowed) {
ASSERT_EQ(responses_.count(process->GetID()), 1U);
EXPECT_EQ(bridge_id, responses_[process->GetID()].first);
EXPECT_EQ(allowed, responses_[process->GetID()].second);
responses_.erase(process->GetID());
}
void GeolocationPermissionContextTests::AddNewTab(const GURL& url) {
content::WebContents* new_tab = content::WebContents::Create(
content::WebContents::CreateParams(profile()));
new_tab->GetController().LoadURL(
url, content::Referrer(), content::PAGE_TRANSITION_TYPED, std::string());
content::RenderViewHostTester::For(new_tab->GetRenderViewHost())->
SendNavigate(extra_tabs_.size() + 1, url);
// Set up required helpers, and make this be as "tabby" as the code requires.
extensions::SetViewType(new_tab, extensions::VIEW_TYPE_TAB_CONTENTS);
InfoBarService::CreateForWebContents(new_tab);
extra_tabs_.push_back(new_tab);
}
void GeolocationPermissionContextTests::CheckTabContentsState(
const GURL& requesting_frame,
ContentSetting expected_content_setting) {
TabSpecificContentSettings* content_settings =
TabSpecificContentSettings::FromWebContents(web_contents());
const ContentSettingsUsagesState::StateMap& state_map =
content_settings->geolocation_usages_state().state_map();
EXPECT_EQ(1U, state_map.count(requesting_frame.GetOrigin()));
EXPECT_EQ(0U, state_map.count(requesting_frame));
ContentSettingsUsagesState::StateMap::const_iterator settings =
state_map.find(requesting_frame.GetOrigin());
ASSERT_FALSE(settings == state_map.end())
<< "geolocation state not found " << requesting_frame;
EXPECT_EQ(expected_content_setting, settings->second);
}
void GeolocationPermissionContextTests::SetUp() {
ChromeRenderViewHostTestHarness::SetUp();
// Set up required helpers, and make this be as "tabby" as the code requires.
extensions::SetViewType(web_contents(), extensions::VIEW_TYPE_TAB_CONTENTS);
InfoBarService::CreateForWebContents(web_contents());
TabSpecificContentSettings::CreateForWebContents(web_contents());
#if defined(OS_ANDROID)
MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
#endif
geolocation_permission_context_ =
ChromeGeolocationPermissionContextFactory::GetForProfile(profile());
}
void GeolocationPermissionContextTests::TearDown() {
extra_tabs_.clear();
ChromeRenderViewHostTestHarness::TearDown();
}
// Tests ----------------------------------------------------------------------
TEST_F(GeolocationPermissionContextTests, SinglePermission) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
infobar_delegate->Cancel();
infobar_service()->RemoveInfoBar(infobar_delegate);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate));
delete infobar_delegate;
}
#if defined(OS_ANDROID)
TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
string16 text_0 = infobar_delegate_0->GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_OK);
NavigateAndCommit(requesting_frame);
MockGoogleLocationSettingsHelper::SetLocationStatus(true, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_1);
string16 text_1 = infobar_delegate_1->GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_OK);
EXPECT_NE(text_0, text_1);
NavigateAndCommit(requesting_frame);
MockGoogleLocationSettingsHelper::SetLocationStatus(false, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(0U, infobar_service()->infobar_count());
}
TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsEnabled) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
MockGoogleLocationSettingsHelper::SetLocationStatus(true, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
infobar_delegate->Accept();
CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
}
TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsDisabled) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
MockGoogleLocationSettingsHelper::SetLocationStatus(true, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
infobar_delegate->Accept();
EXPECT_TRUE(
MockGoogleLocationSettingsHelper::WasGoogleLocationSettingsCalled());
}
#endif
TEST_F(GeolocationPermissionContextTests, QueuedPermission) {
GURL requesting_frame_0("http://www.example.com/geolocation");
GURL requesting_frame_1("http://www.example-2.com/geolocation");
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_0, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_1, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
NavigateAndCommit(requesting_frame_0);
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Request permission for two frames.
RequestGeolocationPermission(RequestID(0), requesting_frame_0);
RequestGeolocationPermission(RequestID(1), requesting_frame_1);
// Ensure only one infobar is created.
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
string16 text_0 = infobar_delegate_0->GetMessageText();
// Accept the first frame.
infobar_delegate_0->Accept();
CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
infobar_service()->RemoveInfoBar(infobar_delegate_0);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0));
closed_infobar_tracker_.Clear();
delete infobar_delegate_0;
// Now we should have a new infobar for the second frame.
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_1);
string16 text_1 = infobar_delegate_1->GetMessageText();
EXPECT_NE(text_0, text_1);
// Cancel (block) this frame.
infobar_delegate_1->Cancel();
CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_BLOCK);
CheckPermissionMessageSent(1, false);
infobar_service()->RemoveInfoBar(infobar_delegate_1);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1));
delete infobar_delegate_1;
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Ensure the persisted permissions are ok.
EXPECT_EQ(CONTENT_SETTING_ALLOW,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_0, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
EXPECT_EQ(CONTENT_SETTING_BLOCK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_1, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
}
TEST_F(GeolocationPermissionContextTests, HashIsIgnored) {
GURL url_a("http://www.example.com/geolocation#a");
GURL url_b("http://www.example.com/geolocation#b");
// Navigate to the first url and check permission is requested.
NavigateAndCommit(url_a);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), url_a);
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
// Change the hash, we'll still be on the same page.
NavigateAndCommit(url_b);
// Accept.
infobar_delegate->Accept();
CheckTabContentsState(url_a, CONTENT_SETTING_ALLOW);
CheckTabContentsState(url_b, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
// Cleanup.
infobar_service()->RemoveInfoBar(infobar_delegate);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate));
closed_infobar_tracker_.Clear();
delete infobar_delegate;
}
TEST_F(GeolocationPermissionContextTests, PermissionForFileScheme) {
GURL requesting_frame("file://example/geolocation.html");
NavigateAndCommit(requesting_frame);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
// Accept the frame.
infobar_delegate->Accept();
CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
infobar_service()->RemoveInfoBar(infobar_delegate);
delete infobar_delegate;
// Make sure the setting is not stored.
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame,
requesting_frame,
CONTENT_SETTINGS_TYPE_GEOLOCATION,
std::string()));
}
TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) {
GURL requesting_frame_0("http://www.example.com/geolocation");
GURL requesting_frame_1("http://www.example-2.com/geolocation");
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_0, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_1, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
NavigateAndCommit(requesting_frame_0);
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Request permission for two frames.
RequestGeolocationPermission(RequestID(0), requesting_frame_0);
RequestGeolocationPermission(RequestID(1), requesting_frame_1);
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
string16 text_0 = infobar_delegate_0->GetMessageText();
// Simulate the frame going away, ensure the infobar for this frame
// is removed and the next pending infobar is created.
CancelGeolocationPermissionRequest(RequestID(0), requesting_frame_0);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0));
closed_infobar_tracker_.Clear();
delete infobar_delegate_0;
ASSERT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_1);
string16 text_1 = infobar_delegate_1->GetMessageText();
EXPECT_NE(text_0, text_1);
// Allow this frame.
infobar_delegate_1->Accept();
CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(1, true);
infobar_service()->RemoveInfoBar(infobar_delegate_1);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1));
delete infobar_delegate_1;
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Ensure the persisted permissions are ok.
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_0, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
EXPECT_EQ(CONTENT_SETTING_ALLOW,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_1, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
}
TEST_F(GeolocationPermissionContextTests, InvalidURL) {
GURL invalid_embedder("about:blank");
GURL requesting_frame;
NavigateAndCommit(invalid_embedder);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), requesting_frame);
EXPECT_EQ(0U, infobar_service()->infobar_count());
CheckPermissionMessageSent(0, 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(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), url_a);
ASSERT_EQ(1U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestIDForTab(0, 0), url_b);
EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
RequestGeolocationPermission(RequestIDForTab(1, 0), url_a);
ASSERT_EQ(1U, infobar_service_for_tab(1)->infobar_count());
ConfirmInfoBarDelegate* removed_infobar =
infobar_service_for_tab(1)->infobar_at(0)->AsConfirmInfoBarDelegate();
// Accept the first tab.
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
infobar_delegate_0->Accept();
CheckPermissionMessageSent(0, true);
infobar_service()->RemoveInfoBar(infobar_delegate_0);
EXPECT_EQ(2U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0));
delete infobar_delegate_0;
// Now the infobar for the tab with the same origin should have gone.
EXPECT_EQ(0U, infobar_service_for_tab(1)->infobar_count());
CheckPermissionMessageSentForTab(1, 0, true);
EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar));
closed_infobar_tracker_.Clear();
// Destroy the infobar that has just been removed.
delete removed_infobar;
// But the other tab should still have the info bar...
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate();
infobar_delegate_1->Cancel();
infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_1);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1));
delete infobar_delegate_1;
}
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(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestID(0), url_a);
ASSERT_EQ(1U, infobar_service()->infobar_count());
RequestGeolocationPermission(RequestIDForTab(0, 0), url_a);
EXPECT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
RequestGeolocationPermission(RequestIDForTab(0, 1), url_b);
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
ConfirmInfoBarDelegate* removed_infobar =
infobar_service()->infobar_at(0)->AsConfirmInfoBarDelegate();
// Accept the second tab.
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
infobar_delegate_0->Accept();
CheckPermissionMessageSentForTab(0, 0, true);
infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_0);
EXPECT_EQ(2U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_0));
delete infobar_delegate_0;
// Now the infobar for the tab with the same origin should have gone.
EXPECT_EQ(0U, infobar_service()->infobar_count());
CheckPermissionMessageSent(0, true);
EXPECT_TRUE(closed_infobar_tracker_.Contains(removed_infobar));
closed_infobar_tracker_.Clear();
delete removed_infobar;
// And we should have the queued infobar displayed now.
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
// Accept the second infobar.
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_service_for_tab(0)->infobar_at(0)->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_1);
infobar_delegate_1->Accept();
CheckPermissionMessageSentForTab(0, 1, true);
infobar_service_for_tab(0)->RemoveInfoBar(infobar_delegate_1);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_delegate_1));
delete infobar_delegate_1;
}
TEST_F(GeolocationPermissionContextTests, TabDestroyed) {
GURL requesting_frame_0("http://www.example.com/geolocation");
GURL requesting_frame_1("http://www.example-2.com/geolocation");
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_0, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
EXPECT_EQ(CONTENT_SETTING_ASK,
profile()->GetHostContentSettingsMap()->GetContentSetting(
requesting_frame_1, requesting_frame_0,
CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string()));
NavigateAndCommit(requesting_frame_0);
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Request permission for two frames.
RequestGeolocationPermission(RequestID(0), requesting_frame_0);
RequestGeolocationPermission(RequestID(1), requesting_frame_1);
// Ensure only one infobar is created.
ASSERT_EQ(1U, infobar_service()->infobar_count());
InfoBarDelegate* infobar = infobar_service()->infobar_at(0);
// Delete the tab contents.
DeleteContents();
delete infobar;
// During contents destruction, the infobar will have been closed, and the
// pending request should have been cleared without an infobar being created.
ASSERT_EQ(1U, closed_infobar_tracker_.size());
ASSERT_TRUE(closed_infobar_tracker_.Contains(infobar));
}
TEST_F(GeolocationPermissionContextTests, InfoBarUsesCommittedEntry) {
GURL requesting_frame_0("http://www.example.com/geolocation");
GURL requesting_frame_1("http://www.example-2.com/geolocation");
NavigateAndCommit(requesting_frame_0);
NavigateAndCommit(requesting_frame_1);
EXPECT_EQ(0U, infobar_service()->infobar_count());
// Go back: navigate to a pending entry before requesting geolocation
// permission.
web_contents()->GetController().GoBack();
// Request permission for the committed frame (not the pending one).
RequestGeolocationPermission(RequestID(0), requesting_frame_1);
// Ensure the infobar is created.
ASSERT_EQ(1U, infobar_service()->infobar_count());
InfoBarDelegate* infobar_delegate = infobar_service()->infobar_at(0);
ASSERT_TRUE(infobar_delegate);
// Ensure the infobar wouldn't expire for a navigation to the committed entry.
content::LoadCommittedDetails details;
details.entry = web_contents()->GetController().GetLastCommittedEntry();
EXPECT_FALSE(infobar_delegate->ShouldExpire(details));
// Ensure the infobar will expire when we commit the pending navigation.
details.entry = web_contents()->GetController().GetActiveEntry();
EXPECT_TRUE(infobar_delegate->ShouldExpire(details));
// Delete the tab contents.
DeleteContents();
delete infobar_delegate;
}