blob: 5c40897810a48ff705596b03148cfb2be4d6a08d [file] [log] [blame]
// Copyright 2018 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 "base/command_line.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/permissions/permission_request_manager.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/permission_bubble/mock_permission_prompt_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "device/geolocation/public/cpp/scoped_geolocation_overrider.h"
#include "net/dns/mock_host_resolver.h"
class PermissionDelegationBrowserTest : public InProcessBrowserTest {
public:
PermissionDelegationBrowserTest()
: geolocation_overrider_(
std::make_unique<device::ScopedGeolocationOverrider>(0, 0)) {}
~PermissionDelegationBrowserTest() override = default;
void SetUpOnMainThread() override {
scoped_feature_list_.InitAndEnableFeature(features::kPermissionDelegation);
PermissionRequestManager* manager =
PermissionRequestManager::FromWebContents(GetWebContents());
mock_permission_prompt_factory_.reset(
new MockPermissionPromptFactory(manager));
https_embedded_test_server_.reset(
new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
https_embedded_test_server_->ServeFilesFromSourceDirectory(
"chrome/test/data");
host_resolver()->AddRule("*", "127.0.0.1");
content::SetupCrossSiteRedirector(https_embedded_test_server_.get());
ASSERT_TRUE(https_embedded_test_server_->Start());
}
void TearDownOnMainThread() override {
mock_permission_prompt_factory_.reset();
https_embedded_test_server_.reset();
}
void SetUpCommandLine(base::CommandLine* command_line) override {
// HTTPS server only serves a valid cert for localhost, so this is needed
// to load pages from other hosts without an error.
command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
}
MockPermissionPromptFactory* prompt_factory() {
return mock_permission_prompt_factory_.get();
}
content::WebContents* GetWebContents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
net::EmbeddedTestServer* https_embedded_test_server() {
return https_embedded_test_server_.get();
}
private:
std::unique_ptr<MockPermissionPromptFactory> mock_permission_prompt_factory_;
std::unique_ptr<net::EmbeddedTestServer> https_embedded_test_server_;
std::unique_ptr<device::ScopedGeolocationOverrider> geolocation_overrider_;
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(PermissionDelegationBrowserTest);
};
IN_PROC_BROWSER_TEST_F(PermissionDelegationBrowserTest, DelegatedToTwoFrames) {
prompt_factory()->set_response_type(PermissionRequestManager::ACCEPT_ALL);
// Main frame is on a.com, iframe 1 is on b.com and iframe 2 is on c.com.
GURL main_frame_url =
https_embedded_test_server()->GetURL("a.com", "/two_iframes_blank.html");
GURL iframe_url_1 =
https_embedded_test_server()->GetURL("b.com", "/simple.html");
GURL iframe_url_2 =
https_embedded_test_server()->GetURL("c.com", "/simple.html");
ui_test_utils::NavigateToURL(browser(), main_frame_url);
content::RenderFrameHost* main_frame = GetWebContents()->GetMainFrame();
// Delegate permission to both frames.
EXPECT_TRUE(content::ExecuteScript(
main_frame,
"document.getElementById('iframe1').allow = 'geolocation *';"));
EXPECT_TRUE(content::ExecuteScript(
main_frame,
"document.getElementById('iframe2').allow = 'geolocation *';"));
// Load the iframes.
EXPECT_TRUE(
content::NavigateIframeToURL(GetWebContents(), "iframe1", iframe_url_1));
EXPECT_TRUE(
content::NavigateIframeToURL(GetWebContents(), "iframe2", iframe_url_2));
content::RenderFrameHost* frame_1 = content::FrameMatchingPredicate(
GetWebContents(),
base::BindRepeating(&content::FrameMatchesName, "iframe1"));
EXPECT_NE(nullptr, frame_1);
content::RenderFrameHost* frame_2 = content::FrameMatchingPredicate(
GetWebContents(),
base::BindRepeating(&content::FrameMatchesName, "iframe2"));
EXPECT_NE(nullptr, frame_2);
// Request permission from the first iframe.
bool result = false;
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
frame_1,
"navigator.geolocation.getCurrentPosition(function(){ "
"domAutomationController.send(true); });",
&result));
EXPECT_TRUE(result);
// A prompt should have been shown with the top level origin rather than the
// iframe origin.
EXPECT_EQ(1, prompt_factory()->TotalRequestCount());
EXPECT_TRUE(prompt_factory()->RequestOriginSeen(main_frame_url.GetOrigin()));
EXPECT_FALSE(prompt_factory()->RequestOriginSeen(iframe_url_1.GetOrigin()));
EXPECT_FALSE(prompt_factory()->RequestOriginSeen(iframe_url_2.GetOrigin()));
// Request permission from the second iframe. Because it was granted to the
// top level frame, it should also be granted to this iframe and there should
// be no prompt.
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
frame_2,
"navigator.geolocation.getCurrentPosition(function(){ "
"domAutomationController.send(true); });",
&result));
EXPECT_TRUE(result);
EXPECT_EQ(1, prompt_factory()->TotalRequestCount());
// Request permission from the top level frame. It should already be granted
// to this iframe and there should be no prompt.
EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
main_frame,
"navigator.geolocation.getCurrentPosition(function(){ "
"domAutomationController.send(true); });",
&result));
EXPECT_TRUE(result);
EXPECT_EQ(1, prompt_factory()->TotalRequestCount());
}