blob: 42273ac3be4ebeb9efb8052049a9e50094b3c88d [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/geolocation_permission_context.h"
#include <set>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/id_map.h"
#include "base/memory/scoped_vector.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/simple_test_clock.h"
#include "base/time/clock.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/tab_specific_content_settings.h"
#include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/permissions/permission_request_id.h"
#include "chrome/browser/ui/website_settings/permission_bubble_request.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/features.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_profile.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/infobars/core/confirm_infobar_delegate.h"
#include "components/infobars/core/infobar.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_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.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/test_utils.h"
#include "content/public/test/web_contents_tester.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(ANDROID_JAVA_UI)
#include "base/prefs/pref_service.h"
#include "chrome/browser/android/mock_location_settings.h"
#include "chrome/browser/geolocation/geolocation_permission_context_android.h"
#else
#include "chrome/browser/ui/website_settings/mock_permission_bubble_view.h"
#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
#endif
#if defined(ENABLE_EXTENSIONS)
#include "extensions/browser/view_type_utils.h"
#endif
using content::MockRenderProcessHost;
// ClosedInfoBarTracker -------------------------------------------------------
// We need to track which infobars were closed.
class ClosedInfoBarTracker : public content::NotificationObserver {
public:
ClosedInfoBarTracker();
~ClosedInfoBarTracker() override;
// content::NotificationObserver:
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
size_t size() const { return removed_infobars_.size(); }
bool Contains(infobars::InfoBar* infobar) const;
void Clear();
private:
FRIEND_TEST_ALL_PREFIXES(GeolocationPermissionContextTests, TabDestroyed);
content::NotificationRegistrar registrar_;
std::set<infobars::InfoBar*> 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<infobars::InfoBar::RemovedDetails>(details)->first);
}
bool ClosedInfoBarTracker::Contains(infobars::InfoBar* infobar) const {
return removed_infobars_.count(infobar) != 0;
}
void ClosedInfoBarTracker::Clear() {
removed_infobars_.clear();
}
// GeolocationPermissionContextTests ------------------------------------------
class GeolocationPermissionContextTests
: public ChromeRenderViewHostTestHarness {
protected:
// ChromeRenderViewHostTestHarness:
void SetUp() override;
void TearDown() override;
PermissionRequestID RequestID(int request_id);
PermissionRequestID RequestIDForTab(int tab, int request_id);
InfoBarService* infobar_service() {
return InfoBarService::FromWebContents(web_contents());
}
InfoBarService* infobar_service_for_tab(int tab) {
return InfoBarService::FromWebContents(extra_tabs_[tab]);
}
void RequestGeolocationPermission(content::WebContents* web_contents,
const PermissionRequestID& id,
const GURL& requesting_frame,
bool user_gesture);
void PermissionResponse(const PermissionRequestID& id,
ContentSetting content_setting);
void CheckPermissionMessageSent(int request_id, bool allowed);
void CheckPermissionMessageSentForTab(int tab, int request_id, bool allowed);
void CheckPermissionMessageSentInternal(MockRenderProcessHost* process,
int request_id,
bool allowed);
void AddNewTab(const GURL& url);
void CheckTabContentsState(const GURL& requesting_frame,
ContentSetting expected_content_setting);
#if !BUILDFLAG(ANDROID_JAVA_UI)
size_t GetBubblesQueueSize(PermissionBubbleManager* manager);
void AcceptBubble(PermissionBubbleManager* manager);
void DenyBubble(PermissionBubbleManager* manager);
void CloseBubble(PermissionBubbleManager* manager);
#endif
void BubbleManagerDocumentLoadCompleted();
void BubbleManagerDocumentLoadCompleted(content::WebContents* web_contents);
ContentSetting GetGeolocationContentSetting(GURL frame_0, GURL frame_1);
size_t GetNumberOfPrompts();
void AcceptPrompt();
base::string16 GetPromptText();
// owned by the browser context
GeolocationPermissionContext* 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 request_id) {
return PermissionRequestID(
web_contents()->GetRenderProcessHost()->GetID(),
web_contents()->GetMainFrame()->GetRoutingID(),
request_id);
}
PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab(
int tab,
int request_id) {
return PermissionRequestID(
extra_tabs_[tab]->GetRenderProcessHost()->GetID(),
extra_tabs_[tab]->GetMainFrame()->GetRoutingID(),
request_id);
}
void GeolocationPermissionContextTests::RequestGeolocationPermission(
content::WebContents* web_contents,
const PermissionRequestID& id,
const GURL& requesting_frame,
bool user_gesture) {
geolocation_permission_context_->RequestPermission(
web_contents, id, requesting_frame, user_gesture,
base::Bind(&GeolocationPermissionContextTests::PermissionResponse,
base::Unretained(this), id));
content::RunAllBlockingPoolTasksUntilIdle();
}
void GeolocationPermissionContextTests::PermissionResponse(
const PermissionRequestID& id,
ContentSetting content_setting) {
responses_[id.render_process_id()] =
std::make_pair(id.request_id(), content_setting == CONTENT_SETTING_ALLOW);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSent(
int request_id,
bool allowed) {
CheckPermissionMessageSentInternal(process(), request_id, allowed);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab(
int tab,
int request_id,
bool allowed) {
CheckPermissionMessageSentInternal(static_cast<MockRenderProcessHost*>(
extra_tabs_[tab]->GetRenderProcessHost()),
request_id, allowed);
}
void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal(
MockRenderProcessHost* process,
int request_id,
bool allowed) {
ASSERT_EQ(responses_.count(process->GetID()), 1U);
EXPECT_EQ(request_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 = CreateTestWebContents();
new_tab->GetController().LoadURL(
url, content::Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
content::NavigationEntry* entry = new_tab->GetController().GetPendingEntry();
content::RenderFrameHostTester::For(new_tab->GetMainFrame())
->SendNavigate(extra_tabs_.size() + 1, entry->GetUniqueID(), true, url);
// Set up required helpers, and make this be as "tabby" as the code requires.
#if defined(ENABLE_EXTENSIONS)
extensions::SetViewType(new_tab, extensions::VIEW_TYPE_TAB_CONTENTS);
#endif
#if BUILDFLAG(ANDROID_JAVA_UI)
InfoBarService::CreateForWebContents(new_tab);
#else
PermissionBubbleManager::CreateForWebContents(new_tab);
PermissionBubbleManager* permission_bubble_manager =
PermissionBubbleManager::FromWebContents(new_tab);
MockPermissionBubbleView::SetFactory(permission_bubble_manager, false);
permission_bubble_manager->DisplayPendingRequests();
#endif
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.
#if defined(ENABLE_EXTENSIONS)
extensions::SetViewType(web_contents(), extensions::VIEW_TYPE_TAB_CONTENTS);
#endif
InfoBarService::CreateForWebContents(web_contents());
TabSpecificContentSettings::CreateForWebContents(web_contents());
geolocation_permission_context_ =
GeolocationPermissionContextFactory::GetForProfile(profile());
#if BUILDFLAG(ANDROID_JAVA_UI)
static_cast<GeolocationPermissionContextAndroid*>(
geolocation_permission_context_)
->SetLocationSettingsForTesting(
scoped_ptr<LocationSettings>(new MockLocationSettings()));
MockLocationSettings::SetLocationStatus(true, true);
#else
PermissionBubbleManager::CreateForWebContents(web_contents());
PermissionBubbleManager* permission_bubble_manager =
PermissionBubbleManager::FromWebContents(web_contents());
MockPermissionBubbleView::SetFactory(permission_bubble_manager, false);
permission_bubble_manager->DisplayPendingRequests();
#endif
}
void GeolocationPermissionContextTests::TearDown() {
extra_tabs_.clear();
ChromeRenderViewHostTestHarness::TearDown();
}
#if !BUILDFLAG(ANDROID_JAVA_UI)
size_t GeolocationPermissionContextTests::GetBubblesQueueSize(
PermissionBubbleManager* manager) {
return manager->requests_.size();
}
void GeolocationPermissionContextTests::AcceptBubble(
PermissionBubbleManager* manager) {
manager->Accept();
}
void GeolocationPermissionContextTests::DenyBubble(
PermissionBubbleManager* manager) {
manager->Deny();
}
void GeolocationPermissionContextTests::CloseBubble(
PermissionBubbleManager* manager) {
manager->Closing();
}
#endif
void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted() {
GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted(
web_contents());
}
void GeolocationPermissionContextTests::BubbleManagerDocumentLoadCompleted(
content::WebContents* web_contents) {
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager::FromWebContents(web_contents)->
DocumentOnLoadCompletedInMainFrame();
#endif
}
ContentSetting GeolocationPermissionContextTests::GetGeolocationContentSetting(
GURL frame_0, GURL frame_1) {
return HostContentSettingsMapFactory::GetForProfile(profile())
->GetContentSetting(frame_0,
frame_1,
CONTENT_SETTINGS_TYPE_GEOLOCATION,
std::string());
}
size_t GeolocationPermissionContextTests::GetNumberOfPrompts() {
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager =
PermissionBubbleManager::FromWebContents(web_contents());
return GetBubblesQueueSize(manager);
#else
return infobar_service()->infobar_count();
#endif
}
void GeolocationPermissionContextTests::AcceptPrompt() {
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager =
PermissionBubbleManager::FromWebContents(web_contents());
AcceptBubble(manager);
#else
infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate =
infobar->delegate()->AsConfirmInfoBarDelegate();
infobar_delegate->Accept();
#endif
}
base::string16 GeolocationPermissionContextTests::GetPromptText() {
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager =
PermissionBubbleManager::FromWebContents(web_contents());
return manager->requests_.front()->GetMessageText();
#else
infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate =
infobar->delegate()->AsConfirmInfoBarDelegate();
return infobar_delegate->GetMessageText();
#endif
}
// Tests ----------------------------------------------------------------------
TEST_F(GeolocationPermissionContextTests, SinglePermissionBubble) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
BubbleManagerDocumentLoadCompleted();
EXPECT_EQ(0U, GetNumberOfPrompts());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
ASSERT_EQ(1U, GetNumberOfPrompts());
}
#if BUILDFLAG(ANDROID_JAVA_UI)
TEST_F(GeolocationPermissionContextTests, SinglePermissionInfobar) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
ASSERT_EQ(1U, infobar_service()->infobar_count());
infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate =
infobar->delegate()->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate);
infobar_delegate->Cancel();
infobar_service()->RemoveInfoBar(infobar);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar));
}
// Infobar-only tests; Android doesn't support permission bubbles.
TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
MockLocationSettings::SetLocationStatus(true, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate_0 =
infobar_service()->infobar_at(0)->delegate()->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_0);
base::string16 text_0 = infobar_delegate_0->GetButtonLabel(
ConfirmInfoBarDelegate::BUTTON_OK);
Reload();
MockLocationSettings::SetLocationStatus(true, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
}
TEST_F(GeolocationPermissionContextTests, MasterEnabledGoogleAppsEnabled) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
MockLocationSettings::SetLocationStatus(true, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(1U, infobar_service()->infobar_count());
ConfirmInfoBarDelegate* infobar_delegate =
infobar_service()->infobar_at(0)->delegate()->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);
MockLocationSettings::SetLocationStatus(true, false);
EXPECT_EQ(0U, infobar_service()->infobar_count());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(0U, infobar_service()->infobar_count());
}
#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,
GetGeolocationContentSetting(requesting_frame_0, requesting_frame_1));
EXPECT_EQ(
CONTENT_SETTING_ASK,
GetGeolocationContentSetting(requesting_frame_1, requesting_frame_1));
NavigateAndCommit(requesting_frame_0);
BubbleManagerDocumentLoadCompleted();
// Check that no permission requests have happened yet.
EXPECT_EQ(0U, GetNumberOfPrompts());
// Request permission for two frames.
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame_0, true);
RequestGeolocationPermission(
web_contents(), RequestID(1), requesting_frame_1, true);
// Ensure only one infobar is created.
ASSERT_EQ(1U, GetNumberOfPrompts());
base::string16 text_0 = GetPromptText();
// Accept the first frame.
AcceptPrompt();
CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
#if BUILDFLAG(ANDROID_JAVA_UI)
infobars::InfoBar* infobar_0 = infobar_service()->infobar_at(0);
infobar_service()->RemoveInfoBar(infobar_0);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_0));
closed_infobar_tracker_.Clear();
#endif
// Now we should have a new infobar for the second frame.
ASSERT_EQ(1U, GetNumberOfPrompts());
base::string16 text_1 = GetPromptText();
// Check that the messages differ.
EXPECT_NE(text_0, text_1);
// Cancel (block) this frame.
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager =
PermissionBubbleManager::FromWebContents(web_contents());
DenyBubble(manager);
#else
infobars::InfoBar* infobar_1 = infobar_service()->infobar_at(0);
infobar_1->delegate()->AsConfirmInfoBarDelegate()->Cancel();
#endif
CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_BLOCK);
CheckPermissionMessageSent(1, false);
// Ensure the persisted permissions are ok.
EXPECT_EQ(
CONTENT_SETTING_ALLOW,
GetGeolocationContentSetting(requesting_frame_0, requesting_frame_0));
EXPECT_EQ(
CONTENT_SETTING_BLOCK,
GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0));
}
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.
NavigateAndCommit(url_a);
BubbleManagerDocumentLoadCompleted();
// Check permission is requested.
ASSERT_EQ(0U, GetNumberOfPrompts());
#if BUILDFLAG(ANDROID_JAVA_UI)
const bool user_gesture = false;
#else
const bool user_gesture = true;
#endif
RequestGeolocationPermission(web_contents(), RequestID(0), url_a,
user_gesture);
ASSERT_EQ(1U, GetNumberOfPrompts());
// Change the hash, we'll still be on the same page.
NavigateAndCommit(url_b);
BubbleManagerDocumentLoadCompleted();
// Accept.
AcceptPrompt();
CheckTabContentsState(url_a, CONTENT_SETTING_ALLOW);
CheckTabContentsState(url_b, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
// Cleanup.
#if BUILDFLAG(ANDROID_JAVA_UI)
infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
infobar_service()->RemoveInfoBar(infobar);
EXPECT_EQ(1U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar));
#endif
}
// TODO(felt): The bubble is rejecting file:// permission requests.
// Fix and enable this test. crbug.com/444047
#if BUILDFLAG(ANDROID_JAVA_UI)
#define MAYBE_PermissionForFileScheme PermissionForFileScheme
#else
#define MAYBE_PermissionForFileScheme DISABLED_PermissionForFileScheme
#endif
TEST_F(GeolocationPermissionContextTests, MAYBE_PermissionForFileScheme) {
GURL requesting_frame("file://example/geolocation.html");
NavigateAndCommit(requesting_frame);
BubbleManagerDocumentLoadCompleted();
// Check permission is requested.
ASSERT_EQ(0U, GetNumberOfPrompts());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(1U, GetNumberOfPrompts());
// Accept the frame.
AcceptPrompt();
CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
// Make sure the setting is not stored.
EXPECT_EQ(
CONTENT_SETTING_ASK,
GetGeolocationContentSetting(requesting_frame, requesting_frame));
}
TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) {
GURL frame_0("http://www.example.com/geolocation");
GURL frame_1("http://www.example-2.com/geolocation");
EXPECT_EQ(
CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_0, frame_0));
EXPECT_EQ(
CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_1, frame_0));
NavigateAndCommit(frame_0);
BubbleManagerDocumentLoadCompleted();
ASSERT_EQ(0U, GetNumberOfPrompts());
// Request permission for two frames.
RequestGeolocationPermission(
web_contents(), RequestID(0), frame_0, true);
RequestGeolocationPermission(
web_contents(), RequestID(1), frame_1, true);
// Get the first permission request text.
ASSERT_EQ(1U, GetNumberOfPrompts());
base::string16 text_0 = GetPromptText();
ASSERT_FALSE(text_0.empty());
// Simulate the frame going away; the request should be removed.
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager =
PermissionBubbleManager::FromWebContents(web_contents());
CloseBubble(manager);
#else
geolocation_permission_context_->CancelPermissionRequest(web_contents(),
RequestID(0));
#endif
// Check that the next pending request is created correctly.
base::string16 text_1 = GetPromptText();
EXPECT_NE(text_0, text_1);
// Allow this frame and check that it worked.
AcceptPrompt();
CheckTabContentsState(frame_1, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(1, true);
// Ensure the persisted permissions are ok.
EXPECT_EQ(
CONTENT_SETTING_ASK, GetGeolocationContentSetting(frame_0, frame_0));
EXPECT_EQ(
CONTENT_SETTING_ALLOW, GetGeolocationContentSetting(frame_1, frame_0));
}
TEST_F(GeolocationPermissionContextTests, InvalidURL) {
// Navigate to the first url.
GURL invalid_embedder("about:blank");
GURL requesting_frame;
NavigateAndCommit(invalid_embedder);
BubbleManagerDocumentLoadCompleted();
// Nothing should be displayed.
EXPECT_EQ(0U, GetNumberOfPrompts());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, true);
EXPECT_EQ(0U, GetNumberOfPrompts());
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); // Tab A0
AddNewTab(url_b); // Tab B (extra_tabs_[0])
AddNewTab(url_a); // Tab A1 (extra_tabs_[1])
BubbleManagerDocumentLoadCompleted();
BubbleManagerDocumentLoadCompleted(extra_tabs_[0]);
BubbleManagerDocumentLoadCompleted(extra_tabs_[1]);
#if !BUILDFLAG(ANDROID_JAVA_UI)
PermissionBubbleManager* manager_a0 =
PermissionBubbleManager::FromWebContents(web_contents());
PermissionBubbleManager* manager_b =
PermissionBubbleManager::FromWebContents(extra_tabs_[0]);
PermissionBubbleManager* manager_a1 =
PermissionBubbleManager::FromWebContents(extra_tabs_[1]);
#endif
// Request permission in all three tabs.
RequestGeolocationPermission(
web_contents(), RequestID(0), url_a, true);
RequestGeolocationPermission(
extra_tabs_[0], RequestIDForTab(0, 0), url_b, true);
RequestGeolocationPermission(
extra_tabs_[1], RequestIDForTab(1, 0), url_a, true);
ASSERT_EQ(1U, GetNumberOfPrompts()); // For A0.
#if !BUILDFLAG(ANDROID_JAVA_UI)
ASSERT_EQ(1U, GetBubblesQueueSize(manager_b));
ASSERT_EQ(1U, GetBubblesQueueSize(manager_a1));
#else
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
ASSERT_EQ(1U, infobar_service_for_tab(1)->infobar_count());
#endif
// Accept the permission in tab A0.
#if !BUILDFLAG(ANDROID_JAVA_UI)
AcceptBubble(manager_a0);
#else
infobars::InfoBar* infobar_a0 = infobar_service()->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate_a0 =
infobar_a0->delegate()->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_a0);
infobar_delegate_a0->Accept();
infobar_service()->RemoveInfoBar(infobar_a0);
EXPECT_EQ(2U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_a0));
#endif
CheckPermissionMessageSent(0, true);
// Because they're the same origin, this will cause tab A1's infobar to
// disappear. It does not cause the bubble to disappear: crbug.com/443013.
// TODO(felt): Update this test when the bubble's behavior is changed.
// Either way, tab B should still have a pending permission request.
#if !BUILDFLAG(ANDROID_JAVA_UI)
ASSERT_EQ(1U, GetBubblesQueueSize(manager_a1));
ASSERT_EQ(1U, GetBubblesQueueSize(manager_b));
#else
CheckPermissionMessageSentForTab(1, 0, true);
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
#endif
}
TEST_F(GeolocationPermissionContextTests, QueuedOriginMultipleTabs) {
GURL url_a("http://www.example.com/geolocation");
GURL url_b("http://www.example-2.com/geolocation");
NavigateAndCommit(url_a); // Tab A0.
AddNewTab(url_a); // Tab A1.
#if !BUILDFLAG(ANDROID_JAVA_UI)
BubbleManagerDocumentLoadCompleted();
BubbleManagerDocumentLoadCompleted(extra_tabs_[0]);
PermissionBubbleManager* manager_a0 =
PermissionBubbleManager::FromWebContents(web_contents());
PermissionBubbleManager* manager_a1 =
PermissionBubbleManager::FromWebContents(extra_tabs_[0]);
#endif
// Request permission in both tabs; the extra tab will have two permission
// requests from two origins.
RequestGeolocationPermission(
web_contents(), RequestID(0), url_a, true);
RequestGeolocationPermission(
extra_tabs_[0], RequestIDForTab(0, 0), url_a, true);
RequestGeolocationPermission(
extra_tabs_[0], RequestIDForTab(0, 1), url_b, true);
#if !BUILDFLAG(ANDROID_JAVA_UI)
ASSERT_EQ(1U, GetBubblesQueueSize(manager_a0));
ASSERT_EQ(1U, GetBubblesQueueSize(manager_a1));
#else
ASSERT_EQ(1U, infobar_service()->infobar_count());
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
#endif
// Accept the first request in tab A1.
#if !BUILDFLAG(ANDROID_JAVA_UI)
AcceptBubble(manager_a1);
#else
infobars::InfoBar* infobar_a1 = infobar_service_for_tab(0)->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate_a1 =
infobar_a1->delegate()->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_a1);
infobar_delegate_a1->Accept();
infobar_service_for_tab(0)->RemoveInfoBar(infobar_a1);
EXPECT_EQ(2U, closed_infobar_tracker_.size());
EXPECT_TRUE(closed_infobar_tracker_.Contains(infobar_a1));
#endif
CheckPermissionMessageSentForTab(0, 0, true);
// Because they're the same origin, this will cause tab A0's infobar to
// disappear. It does not cause the bubble to disappear: crbug.com/443013.
// TODO(felt): Update this test when the bubble's behavior is changed.
#if !BUILDFLAG(ANDROID_JAVA_UI)
EXPECT_EQ(1U, GetBubblesQueueSize(manager_a0));
#else
EXPECT_EQ(0U, infobar_service()->infobar_count());
CheckPermissionMessageSent(0, true);
#endif
// The second request should now be visible in tab A1.
#if !BUILDFLAG(ANDROID_JAVA_UI)
ASSERT_EQ(1U, GetBubblesQueueSize(manager_a1));
#else
ASSERT_EQ(1U, infobar_service_for_tab(0)->infobar_count());
#endif
// Accept the second request and check that it's gone.
#if !BUILDFLAG(ANDROID_JAVA_UI)
AcceptBubble(manager_a1);
EXPECT_EQ(0U, GetBubblesQueueSize(manager_a1));
#else
infobars::InfoBar* infobar_1 = infobar_service_for_tab(0)->infobar_at(0);
ConfirmInfoBarDelegate* infobar_delegate_1 =
infobar_1->delegate()->AsConfirmInfoBarDelegate();
ASSERT_TRUE(infobar_delegate_1);
infobar_delegate_1->Accept();
#endif
}
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,
GetGeolocationContentSetting(requesting_frame_0, requesting_frame_0));
EXPECT_EQ(
CONTENT_SETTING_ASK,
GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0));
NavigateAndCommit(requesting_frame_0);
BubbleManagerDocumentLoadCompleted();
// Request permission for two frames.
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame_0, false);
RequestGeolocationPermission(
web_contents(), RequestID(1), requesting_frame_1, false);
// Ensure only one prompt is created.
ASSERT_EQ(1U, GetNumberOfPrompts());
// Delete the tab contents.
#if BUILDFLAG(ANDROID_JAVA_UI)
infobars::InfoBar* infobar = infobar_service()->infobar_at(0);
DeleteContents();
ASSERT_EQ(1U, closed_infobar_tracker_.size());
ASSERT_TRUE(closed_infobar_tracker_.Contains(infobar));
#endif
// The content settings should not have changed.
EXPECT_EQ(
CONTENT_SETTING_ASK,
GetGeolocationContentSetting(requesting_frame_0, requesting_frame_0));
EXPECT_EQ(
CONTENT_SETTING_ASK,
GetGeolocationContentSetting(requesting_frame_1, requesting_frame_0));
}
TEST_F(GeolocationPermissionContextTests, LastUsageAudited) {
GURL requesting_frame("http://www.example.com/geolocation");
NavigateAndCommit(requesting_frame);
BubbleManagerDocumentLoadCompleted();
base::SimpleTestClock* test_clock = new base::SimpleTestClock;
test_clock->SetNow(base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(10));
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
map->SetPrefClockForTesting(scoped_ptr<base::Clock>(test_clock));
// The permission shouldn't have been used yet.
EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
requesting_frame.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
0);
ASSERT_EQ(0U, GetNumberOfPrompts());
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, false);
ASSERT_EQ(1U, GetNumberOfPrompts());
AcceptPrompt();
CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
// Permission has been used at the starting time.
EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
requesting_frame.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
10);
test_clock->Advance(base::TimeDelta::FromSeconds(3));
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame, false);
// Permission has been used three seconds later.
EXPECT_EQ(map->GetLastUsage(requesting_frame.GetOrigin(),
requesting_frame.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
13);
}
TEST_F(GeolocationPermissionContextTests, LastUsageAuditedMultipleFrames) {
base::SimpleTestClock* test_clock = new base::SimpleTestClock;
test_clock->SetNow(base::Time::UnixEpoch() +
base::TimeDelta::FromSeconds(10));
HostContentSettingsMap* map =
HostContentSettingsMapFactory::GetForProfile(profile());
map->SetPrefClockForTesting(scoped_ptr<base::Clock>(test_clock));
GURL requesting_frame_0("http://www.example.com/geolocation");
GURL requesting_frame_1("http://www.example-2.com/geolocation");
// The permission shouldn't have been used yet.
EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
0);
EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
0);
NavigateAndCommit(requesting_frame_0);
BubbleManagerDocumentLoadCompleted();
EXPECT_EQ(0U, GetNumberOfPrompts());
// Request permission for two frames.
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame_0, false);
RequestGeolocationPermission(
web_contents(), RequestID(1), requesting_frame_1, false);
// Ensure only one infobar is created.
ASSERT_EQ(1U, GetNumberOfPrompts());
// Accept the first frame.
AcceptPrompt();
#if BUILDFLAG(ANDROID_JAVA_UI)
infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
#endif
CheckTabContentsState(requesting_frame_0, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(0, true);
// Verify that accepting the first didn't accept because it's embedded
// in the other.
EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
10);
EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
0);
ASSERT_EQ(1U, GetNumberOfPrompts());
test_clock->Advance(base::TimeDelta::FromSeconds(1));
// Allow the second frame.
AcceptPrompt();
CheckTabContentsState(requesting_frame_1, CONTENT_SETTING_ALLOW);
CheckPermissionMessageSent(1, true);
#if BUILDFLAG(ANDROID_JAVA_UI)
infobar_service()->RemoveInfoBar(infobar_service()->infobar_at(0));
#endif
// Verify that the times are different.
EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
10);
EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
11);
test_clock->Advance(base::TimeDelta::FromSeconds(2));
RequestGeolocationPermission(
web_contents(), RequestID(0), requesting_frame_0, false);
// Verify that requesting permission in one frame doesn't update other where
// it is the embedder.
EXPECT_EQ(map->GetLastUsage(requesting_frame_0.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
13);
EXPECT_EQ(map->GetLastUsage(requesting_frame_1.GetOrigin(),
requesting_frame_0.GetOrigin(),
CONTENT_SETTINGS_TYPE_GEOLOCATION).ToDoubleT(),
11);
}