Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backup search API (Uplift to 1.23.x Release #2) #8553

Merged
merged 15 commits into from
Apr 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ source_set("browser_process") {
"//brave/components/brave_component_updater/browser",
"//brave/components/brave_drm",
"//brave/components/brave_referrals/buildflags",
"//brave/components/brave_search/browser",
"//brave/components/brave_search/common:mojom",
"//brave/components/brave_shields/browser",
"//brave/components/brave_shields/common",
"//brave/components/brave_sync",
Expand Down
1 change: 1 addition & 0 deletions browser/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ include_rules = [
"+chrome/installer/util",
"+chrome/services/mac_notifications/public/cpp",
"+chrome/test",
"+content/browser/service_worker",
"+content/public/browser",
"+content/public/common",
"+content/public/test",
Expand Down
22 changes: 22 additions & 0 deletions browser/brave_content_browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include "brave/common/webui_url_constants.h"
#include "brave/components/binance/browser/buildflags/buildflags.h"
#include "brave/components/brave_rewards/browser/buildflags/buildflags.h"
#include "brave/components/brave_search/browser/brave_search_host.h"
#include "brave/components/brave_search/common/brave_search.mojom.h"
#include "brave/components/brave_shields/browser/brave_shields_util.h"
#include "brave/components/brave_shields/browser/brave_shields_web_contents_observer.h"
#include "brave/components/brave_shields/browser/domain_block_navigation_throttle.h"
Expand All @@ -49,6 +51,7 @@
#include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
#include "components/version_info/version_info.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_host.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
Expand All @@ -61,6 +64,7 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/cookies/site_for_cookies.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "ui/base/l10n/l10n_util.h"

Expand Down Expand Up @@ -236,6 +240,14 @@ void BindCosmeticFiltersResources(
std::move(receiver));
}

void BindBraveSearchHost(
mojo::PendingReceiver<brave_search::mojom::BraveSearchFallback> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<brave_search::BraveSearchHost>(
g_brave_browser_process->shared_url_loader_factory()),
std::move(receiver));
}

} // namespace

BraveContentBrowserClient::BraveContentBrowserClient()
Expand Down Expand Up @@ -279,6 +291,16 @@ BraveContentBrowserClient::AllowWebBluetooth(
return ContentBrowserClient::AllowWebBluetoothResult::BLOCK_GLOBALLY_DISABLED;
}

void BraveContentBrowserClient::ExposeInterfacesToRenderer(
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) {
ChromeContentBrowserClient::ExposeInterfacesToRenderer(
registry, associated_registry, render_process_host);
registry->AddInterface(base::BindRepeating(&BindBraveSearchHost),
content::GetUIThreadTaskRunner({}));
}

void BraveContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
content::RenderFrameHost* render_frame_host,
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
Expand Down
10 changes: 9 additions & 1 deletion browser/brave_content_browser_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class PrefChangeRegistrar;

namespace content {
class BrowserContext;
}
} // namespace content

namespace blink {
class AssociatedInterfaceRegistry;
} // namespace blink

class BraveContentBrowserClient : public ChromeContentBrowserClient {
public:
Expand Down Expand Up @@ -105,6 +109,10 @@ class BraveContentBrowserClient : public ChromeContentBrowserClient {

std::string GetEffectiveUserAgent(content::BrowserContext* browser_context,
const GURL& url) override;
void ExposeInterfacesToRenderer(
service_manager::BinderRegistry* registry,
blink::AssociatedInterfaceRegistry* associated_registry,
content::RenderProcessHost* render_process_host) override;

private:
uint64_t session_token_;
Expand Down
142 changes: 142 additions & 0 deletions browser/brave_search/brave_search_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "base/path_service.h"
#include "base/task/post_task.h"
#include "base/test/thread_test_helper.h"
#include "brave/browser/brave_browser_process_impl.h"
#include "brave/common/brave_paths.h"
#include "brave/common/pref_names.h"
#include "brave/components/brave_search/browser/brave_search_host.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/ui/browser.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/browser/browser_task_traits.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"

using extensions::ExtensionBrowserTest;

namespace {

const char kEmbeddedTestServerDirectory[] = "brave-search";
const char kAllowedDomain[] = "search.brave.com";
const char kAllowedDomainDev[] = "search-dev.brave.com";
const char kNotAllowedDomain[] = "brave.com";
const char kBackupSearchContent[] = "<html><body>results</body></html>";

std::string GetChromeFetchBackupResultsAvailScript() {
return base::StringPrintf(R"(function waitForFunction() {
setTimeout(waitForFunction, 200);
}
navigator.serviceWorker.addEventListener('message', msg => {
if (msg.data && msg.data.result === 'INJECTED') {
window.domAutomationController.send(msg.data.response === '%s');
} else if (msg.data && msg.data.result === 'FAILED') {
window.domAutomationController.send(false);
}});
waitForFunction();)",
kBackupSearchContent);
}

} // namespace

class BraveSearchTest : public InProcessBrowserTest {
public:
BraveSearchTest() {}

void SetUpOnMainThread() override {
InProcessBrowserTest::SetUpOnMainThread();
host_resolver()->AddRule("*", "127.0.0.1");

https_server_.reset(new net::EmbeddedTestServer(
net::test_server::EmbeddedTestServer::TYPE_HTTPS));
https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
https_server_->RegisterRequestHandler(base::BindRepeating(
&BraveSearchTest::HandleRequest, base::Unretained(this)));

brave::RegisterPathProvider();
base::FilePath test_data_dir;
base::PathService::Get(brave::DIR_TEST_DATA, &test_data_dir);
test_data_dir = test_data_dir.AppendASCII(kEmbeddedTestServerDirectory);
https_server_->ServeFilesFromDirectory(test_data_dir);

ASSERT_TRUE(https_server_->Start());
GURL url = https_server()->GetURL("a.com", "/search");
brave_search::BraveSearchHost::SetBackupProviderForTest(url);
}

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);
}

std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const net::test_server::HttpRequest& request) {
if (request.GetURL().path_piece() == "/sw.js" ||
request.GetURL().path_piece() == "/bravesearch.html")
return nullptr;

GURL url = request.GetURL();
auto http_response =
std::make_unique<net::test_server::BasicHttpResponse>();
if (url.path() + "?" + url.query() ==
"/search?q=test&hl=en&gl=us&safe=active") {
http_response->set_code(net::HTTP_OK);
http_response->set_content_type("text/html");
http_response->set_content(kBackupSearchContent);
return http_response;
}
http_response->set_code(net::HTTP_NOT_FOUND);
return http_response;
}

net::EmbeddedTestServer* https_server() { return https_server_.get(); }

private:
std::unique_ptr<net::EmbeddedTestServer> https_server_;
};

IN_PROC_BROWSER_TEST_F(BraveSearchTest, CheckForAFunction) {
GURL url = https_server()->GetURL(kAllowedDomain, "/bravesearch.html");
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
WaitForLoadStop(contents);

auto result_first =
EvalJsWithManualReply(contents, GetChromeFetchBackupResultsAvailScript());
EXPECT_EQ(base::Value(true), result_first.value);
}

IN_PROC_BROWSER_TEST_F(BraveSearchTest, CheckForAFunctionDev) {
GURL url = https_server()->GetURL(kAllowedDomainDev, "/bravesearch.html");
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
WaitForLoadStop(contents);

auto result_first =
EvalJsWithManualReply(contents, GetChromeFetchBackupResultsAvailScript());
EXPECT_EQ(base::Value(true), result_first.value);
}

IN_PROC_BROWSER_TEST_F(BraveSearchTest, CheckForAnUndefinedFunction) {
GURL url = https_server()->GetURL(kNotAllowedDomain, "/bravesearch.html");
ui_test_utils::NavigateToURL(browser(), url);
content::WebContents* contents =
browser()->tab_strip_model()->GetActiveWebContents();
WaitForLoadStop(contents);

auto result_first =
EvalJsWithManualReply(contents, GetChromeFetchBackupResultsAvailScript());
EXPECT_EQ(base::Value(false), result_first.value);
}
16 changes: 16 additions & 0 deletions components/brave_search/browser/BUILD.gn
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import("//build/config/features.gni")

source_set("browser") {
sources = [
"brave_search_host.cc",
"brave_search_host.h",
]

deps = [
"//base",
"//brave/components/brave_search/common:mojom",
"//net",
"//services/network/public/cpp",
"//url",
]
}
3 changes: 3 additions & 0 deletions components/brave_search/browser/DEPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
include_rules = [
"+services/network/public/cpp",
]
116 changes: 116 additions & 0 deletions components/brave_search/browser/brave_search_host.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "brave/components/brave_search/browser/brave_search_host.h"

#include <utility>

#include "net/base/load_flags.h"
#include "net/base/url_util.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"

namespace {
net::NetworkTrafficAnnotationTag GetNetworkTrafficAnnotationTag() {
return net::DefineNetworkTrafficAnnotation("brave_search_host", R"(
semantics {
sender: "Brave Search Host Controller"
description:
"This controller is used as a backup search "
"provider for users that have opted into this feature."
trigger:
"Triggered by Brave search if a user has opted in."
data:
"Local backup provider results."
destination: WEBSITE
}
policy {
cookies_allowed: NO
setting:
"You can enable or disable this feature on chrome://flags."
policy_exception_justification:
"Not implemented."
}
)");
}

const unsigned int kRetriesCountOnNetworkChange = 1;
static GURL backup_provider_for_test;
} // namespace

namespace brave_search {

void BraveSearchHost::SetBackupProviderForTest(const GURL& backup_provider) {
backup_provider_for_test = backup_provider;
}

BraveSearchHost::BraveSearchHost(
scoped_refptr<network::SharedURLLoaderFactory> factory)
: shared_url_loader_factory_(std::move(factory)), weak_factory_(this) {}

BraveSearchHost::~BraveSearchHost() {}

// [static]
GURL BraveSearchHost::GetBackupResultURL(const GURL& baseURL,
const std::string& query,
const std::string& lang,
const std::string& country,
const std::string& geo,
bool filter_explicit_results) {
GURL url = baseURL;
url = net::AppendQueryParameter(url, "q", query);
if (!lang.empty()) {
url = net::AppendQueryParameter(url, "hl", lang);
}
if (!country.empty()) {
url = net::AppendQueryParameter(url, "gl", country);
}
if (filter_explicit_results) {
url = net::AppendQueryParameter(url, "safe", "active");
}
return url;
}

void BraveSearchHost::FetchBackupResults(const std::string& query,
const std::string& lang,
const std::string& country,
const std::string& geo,
bool filter_explicit_results,
FetchBackupResultsCallback callback) {
auto request = std::make_unique<network::ResourceRequest>();
request->url = GURL("https://www.google.com/search");
if (!backup_provider_for_test.is_empty()) {
request->url = backup_provider_for_test;
}
request->url = GetBackupResultURL(request->url, query, lang, country, geo,
filter_explicit_results);
request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE;
request->credentials_mode = network::mojom::CredentialsMode::kOmit;
request->load_flags |= net::LOAD_DO_NOT_SAVE_COOKIES;
request->method = "GET";
request->headers.SetHeaderIfMissing("x-geo", geo);

auto url_loader = network::SimpleURLLoader::Create(
std::move(request), GetNetworkTrafficAnnotationTag());
url_loader->SetRetryOptions(
kRetriesCountOnNetworkChange,
network::SimpleURLLoader::RetryMode::RETRY_ON_NETWORK_CHANGE);
auto iter = url_loaders_.insert(url_loaders_.begin(), std::move(url_loader));
iter->get()->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
shared_url_loader_factory_.get(),
base::BindOnce(&BraveSearchHost::OnURLLoaderComplete,
weak_factory_.GetWeakPtr(), std::move(iter),
std::move(callback)));
}

void BraveSearchHost::OnURLLoaderComplete(
SimpleURLLoaderList::iterator iter,
BraveSearchHost::FetchBackupResultsCallback callback,
const std::unique_ptr<std::string> response_body) {
url_loaders_.erase(iter);
std::move(callback).Run(*response_body);
}

} // namespace brave_search
Loading