blob: f8fa192794391c94c354364caa3a188ab45948c1 [file] [log] [blame]
// Copyright 2017 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 "components/domain_reliability/service.h"
#include "base/logging.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/test_simple_task_runner.h"
#include "base/time/time.h"
#include "components/domain_reliability/monitor.h"
#include "components/domain_reliability/test_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_manager.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/base/host_port_pair.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/modules/permissions/permission_status.mojom.h"
namespace domain_reliability {
namespace {
class TestPermissionManager : public content::PermissionManager {
public:
TestPermissionManager() : get_permission_status_count_(0) {}
int get_permission_status_count() const {
return get_permission_status_count_;
}
content::PermissionType last_permission() const { return last_permission_; }
const GURL& last_requesting_origin() const { return last_requesting_origin_; }
const GURL& last_embedding_origin() const { return last_embedding_origin_; }
void set_permission_status(blink::mojom::PermissionStatus permission_status) {
permission_status_ = permission_status;
}
// content::PermissionManager:
~TestPermissionManager() override {}
blink::mojom::PermissionStatus GetPermissionStatus(
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) override {
++get_permission_status_count_;
last_permission_ = permission;
last_requesting_origin_ = requesting_origin;
last_embedding_origin_ = embedding_origin;
return permission_status_;
}
blink::mojom::PermissionStatus GetPermissionStatusForFrame(
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin) override {
return GetPermissionStatus(
permission, requesting_origin,
content::WebContents::FromRenderFrameHost(render_frame_host)
->GetLastCommittedURL()
.GetOrigin());
}
int RequestPermission(
content::PermissionType permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
override {
NOTIMPLEMENTED();
return content::PermissionController::kNoPendingOperation;
}
int RequestPermissions(
const std::vector<content::PermissionType>& permission,
content::RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
bool user_gesture,
const base::Callback<
void(const std::vector<blink::mojom::PermissionStatus>&)>& callback)
override {
NOTIMPLEMENTED();
return content::PermissionController::kNoPendingOperation;
}
void ResetPermission(content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) override {
NOTIMPLEMENTED();
}
int SubscribePermissionStatusChange(
content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin,
const base::Callback<void(blink::mojom::PermissionStatus)>& callback)
override {
NOTIMPLEMENTED();
return 0;
}
void UnsubscribePermissionStatusChange(int subscription_id) override {
NOTIMPLEMENTED();
}
private:
// Number of calls made to GetPermissionStatus.
int get_permission_status_count_;
// Parameters to last call to GetPermissionStatus:
content::PermissionType last_permission_;
GURL last_requesting_origin_;
GURL last_embedding_origin_;
// Value to return from GetPermissionStatus.
blink::mojom::PermissionStatus permission_status_;
DISALLOW_COPY_AND_ASSIGN(TestPermissionManager);
};
} // namespace
class DomainReliabilityServiceTest : public testing::Test {
protected:
using RequestInfo = DomainReliabilityMonitor::RequestInfo;
DomainReliabilityServiceTest()
: upload_reporter_string_("test"),
permission_manager_(new TestPermissionManager()) {
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::UI);
scoped_refptr<base::SingleThreadTaskRunner> network_task_runner =
content::BrowserThread::GetTaskRunnerForThread(
content::BrowserThread::IO);
url_request_context_getter_ =
new net::TestURLRequestContextGetter(network_task_runner);
browser_context_.SetPermissionManager(
base::WrapUnique(permission_manager_));
service_ = base::WrapUnique(DomainReliabilityService::Create(
upload_reporter_string_, &browser_context_));
monitor_ = service_->CreateMonitor(ui_task_runner, network_task_runner);
monitor_->MoveToNetworkThread();
monitor_->InitURLRequestContext(url_request_context_getter_);
monitor_->SetDiscardUploads(true);
}
~DomainReliabilityServiceTest() override {
if (monitor_)
monitor_->Shutdown();
}
void OnRequestLegComplete(RequestInfo request) {
monitor_->OnRequestLegComplete(request);
}
int GetDiscardedUploadCount() const {
return monitor_->uploader_->GetDiscardedUploadCount();
}
content::TestBrowserThreadBundle thread_bundle_;
std::string upload_reporter_string_;
content::TestBrowserContext browser_context_;
// Owned by browser_context_, not the test class.
TestPermissionManager* permission_manager_;
std::unique_ptr<DomainReliabilityService> service_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::unique_ptr<DomainReliabilityMonitor> monitor_;
private:
DISALLOW_COPY_AND_ASSIGN(DomainReliabilityServiceTest);
};
namespace {
TEST_F(DomainReliabilityServiceTest, Create) {}
TEST_F(DomainReliabilityServiceTest, UploadAllowed) {
permission_manager_->set_permission_status(
blink::mojom::PermissionStatus::GRANTED);
monitor_->AddContextForTesting(
MakeTestConfigWithOrigin(GURL("https://example/")));
RequestInfo request;
request.status =
net::URLRequestStatus::FromError(net::ERR_CONNECTION_REFUSED);
request.response_info.socket_address =
net::HostPortPair::FromString("1.2.3.4");
request.url = GURL("https://example/");
request.response_info.was_cached = false;
request.response_info.network_accessed = true;
request.response_info.was_fetched_via_proxy = false;
request.load_flags = 0;
request.load_timing_info.request_start = base::TimeTicks::Now();
request.upload_depth = 0;
OnRequestLegComplete(request);
monitor_->ForceUploadsForTesting();
content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
EXPECT_EQ(1, permission_manager_->get_permission_status_count());
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
EXPECT_EQ(1, GetDiscardedUploadCount());
}
TEST_F(DomainReliabilityServiceTest, UploadForbidden) {
permission_manager_->set_permission_status(
blink::mojom::PermissionStatus::DENIED);
monitor_->AddContextForTesting(
MakeTestConfigWithOrigin(GURL("https://example/")));
RequestInfo request;
request.status =
net::URLRequestStatus::FromError(net::ERR_CONNECTION_REFUSED);
request.response_info.socket_address =
net::HostPortPair::FromString("1.2.3.4");
request.url = GURL("https://example/");
request.response_info.was_cached = false;
request.response_info.network_accessed = true;
request.response_info.was_fetched_via_proxy = false;
request.load_flags = 0;
request.load_timing_info.request_start = base::TimeTicks::Now();
request.upload_depth = 0;
OnRequestLegComplete(request);
monitor_->ForceUploadsForTesting();
content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
EXPECT_EQ(1, permission_manager_->get_permission_status_count());
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
EXPECT_EQ(0, GetDiscardedUploadCount());
}
TEST_F(DomainReliabilityServiceTest, MonitorDestroyedBeforeCheckRuns) {
permission_manager_->set_permission_status(
blink::mojom::PermissionStatus::DENIED);
monitor_->AddContextForTesting(
MakeTestConfigWithOrigin(GURL("https://example/")));
RequestInfo request;
request.status =
net::URLRequestStatus::FromError(net::ERR_CONNECTION_REFUSED);
request.response_info.socket_address =
net::HostPortPair::FromString("1.2.3.4");
request.url = GURL("https://example/");
request.response_info.was_cached = false;
request.response_info.network_accessed = true;
request.response_info.was_fetched_via_proxy = false;
request.load_flags = 0;
request.load_timing_info.request_start = base::TimeTicks::Now();
request.upload_depth = 0;
OnRequestLegComplete(request);
monitor_->ForceUploadsForTesting();
monitor_->Shutdown();
monitor_.reset();
content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
EXPECT_EQ(1, permission_manager_->get_permission_status_count());
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
// Makes no sense to check upload count, since monitor was destroyed.
}
TEST_F(DomainReliabilityServiceTest, MonitorDestroyedBeforeCheckReturns) {
permission_manager_->set_permission_status(
blink::mojom::PermissionStatus::DENIED);
monitor_->AddContextForTesting(
MakeTestConfigWithOrigin(GURL("https://example/")));
RequestInfo request;
request.status =
net::URLRequestStatus::FromError(net::ERR_CONNECTION_REFUSED);
request.response_info.socket_address =
net::HostPortPair::FromString("1.2.3.4");
request.url = GURL("https://example/");
request.response_info.was_cached = false;
request.response_info.network_accessed = true;
request.response_info.was_fetched_via_proxy = false;
request.load_flags = 0;
request.load_timing_info.request_start = base::TimeTicks::Now();
request.upload_depth = 0;
OnRequestLegComplete(request);
monitor_->ForceUploadsForTesting();
content::RunAllPendingInMessageLoop(content::BrowserThread::UI);
EXPECT_EQ(1, permission_manager_->get_permission_status_count());
monitor_->Shutdown();
monitor_.reset();
content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
// Makes no sense to check upload count, since monitor was destroyed.
}
} // namespace
} // namespace domain_reliability