Skip to content

Commit

Permalink
[fuchsia] Implement NavigationPolicyThrottle for navigation blocking
Browse files Browse the repository at this point in the history
* Add an implementation of NavigationPolicyThrottle to WebEngine
* Add NavigationPolicyHandler, which keeps track of throttles and checks
  if navigations need to be passed on to the client
* Add a FakeNavigationPolicyProvider for tests

Test: NavigationPolicyThrottleTest
Bug: 1117601
Change-Id: I0bdf94345b10d829bea4aeb85f74204970a97239
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2519039
Commit-Queue: Sharon Yang <[email protected]>
Reviewed-by: Sergey Ulanov <[email protected]>
Cr-Commit-Position: refs/heads/master@{#826625}
  • Loading branch information
yangsharon-chromium authored and Commit Bot committed Nov 12, 2020
1 parent bea2652 commit 17bbb4d
Show file tree
Hide file tree
Showing 8 changed files with 464 additions and 0 deletions.
8 changes: 8 additions & 0 deletions fuchsia/engine/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ component("web_engine_core") {
"browser/media_resource_provider_service.h",
"browser/navigation_controller_impl.cc",
"browser/navigation_controller_impl.h",
"browser/navigation_policy_handler.cc",
"browser/navigation_policy_handler.h",
"browser/navigation_policy_throttle.cc",
"browser/navigation_policy_throttle.h",
"browser/url_request_rewrite_rules_manager.cc",
"browser/url_request_rewrite_rules_manager.h",
"browser/web_engine_browser_context.cc",
Expand Down Expand Up @@ -329,8 +333,11 @@ test("web_engine_unittests") {
"browser/ax_tree_converter_unittest.cc",
"browser/cookie_manager_impl_unittest.cc",
"browser/event_filter_unittest.cc",
"browser/fake_navigation_policy_provider.cc",
"browser/fake_navigation_policy_provider.h",
"browser/frame_impl_unittest.cc",
"browser/media_player_impl_unittest.cc",
"browser/navigation_policy_throttle_unittest.cc",
"browser/url_request_rewrite_rules_manager_unittest.cc",
"common/web_engine_url_loader_throttle_unittest.cc",
"context_provider_impl_unittest.cc",
Expand All @@ -343,6 +350,7 @@ test("web_engine_unittests") {
":switches",
":web_engine_core",
"//base/test:test_support",
"//content/test:test_support",
"//fuchsia/base:test_support",
"//mojo/core/embedder",
"//services/media_session/public/mojom",
Expand Down
30 changes: 30 additions & 0 deletions fuchsia/engine/browser/fake_navigation_policy_provider.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2020 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 "fuchsia/engine/browser/fake_navigation_policy_provider.h"

#include "base/logging.h"
#include "base/notreached.h"
#include "testing/gtest/include/gtest/gtest.h"

FakeNavigationPolicyProvider::FakeNavigationPolicyProvider() = default;

FakeNavigationPolicyProvider::~FakeNavigationPolicyProvider() = default;

void FakeNavigationPolicyProvider::EvaluateRequestedNavigation(
fuchsia::web::RequestedNavigation requested_navigation,
EvaluateRequestedNavigationCallback callback) {
fuchsia::web::NavigationDecision decision;
if (should_reject_request_) {
callback(decision.WithAbort(fuchsia::web::NoArgumentsAction()));
} else {
callback(decision.WithProceed(fuchsia::web::NoArgumentsAction()));
}

requested_navigation_ = std::move(requested_navigation);
}

void FakeNavigationPolicyProvider::NotImplemented_(const std::string& name) {
NOTIMPLEMENTED() << name;
}
40 changes: 40 additions & 0 deletions fuchsia/engine/browser/fake_navigation_policy_provider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2020 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.

#ifndef FUCHSIA_ENGINE_BROWSER_FAKE_NAVIGATION_POLICY_PROVIDER_H_
#define FUCHSIA_ENGINE_BROWSER_FAKE_NAVIGATION_POLICY_PROVIDER_H_

#include <fuchsia/web/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl_test_base.h>

class FakeNavigationPolicyProvider
: public fuchsia::web::testing::NavigationPolicyProvider_TestBase {
public:
FakeNavigationPolicyProvider();
~FakeNavigationPolicyProvider() override;

FakeNavigationPolicyProvider(const FakeNavigationPolicyProvider&) = delete;
FakeNavigationPolicyProvider& operator=(const FakeNavigationPolicyProvider&) =
delete;

void set_should_reject_request(bool reject) {
should_reject_request_ = reject;
}

fuchsia::web::RequestedNavigation* requested_navigation() {
return &requested_navigation_;
}

// fuchsia::web::NavigationPolicyProvider implementation.
void EvaluateRequestedNavigation(
fuchsia::web::RequestedNavigation requested_navigation,
EvaluateRequestedNavigationCallback callback) final;
void NotImplemented_(const std::string& name) final;

private:
fuchsia::web::RequestedNavigation requested_navigation_;
bool should_reject_request_ = false;
};

#endif // FUCHSIA_ENGINE_BROWSER_FAKE_NAVIGATION_POLICY_PROVIDER_H_
69 changes: 69 additions & 0 deletions fuchsia/engine/browser/navigation_policy_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2020 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 "fuchsia/engine/browser/navigation_policy_handler.h"

#include <lib/fidl/cpp/binding.h>

#include "base/fuchsia/fuchsia_logging.h"
#include "content/public/browser/navigation_handle.h"
#include "fuchsia/engine/browser/navigation_policy_throttle.h"

NavigationPolicyHandler::NavigationPolicyHandler(
fuchsia::web::NavigationPolicyProviderParams params,
fidl::InterfaceHandle<fuchsia::web::NavigationPolicyProvider> delegate)
: params_(std::move(params)), provider_(delegate.Bind()) {
provider_.set_error_handler(fit::bind_member(
this, &NavigationPolicyHandler::OnNavigationPolicyProviderDisconnected));
}

NavigationPolicyHandler::~NavigationPolicyHandler() {
for (auto* throttle : navigation_throttles_) {
throttle->OnNavigationPolicyProviderDisconnected(
content::NavigationThrottle::CANCEL);
}
navigation_throttles_.clear();
}

void NavigationPolicyHandler::RegisterNavigationThrottle(
NavigationPolicyThrottle* navigation_throttle) {
navigation_throttles_.insert(navigation_throttle);
}

void NavigationPolicyHandler::RemoveNavigationThrottle(
NavigationPolicyThrottle* navigation_throttle) {
navigation_throttles_.erase(navigation_throttle);
}

void NavigationPolicyHandler::EvaluateRequestedNavigation(
fuchsia::web::RequestedNavigation requested_navigation,
fuchsia::web::NavigationPolicyProvider::EvaluateRequestedNavigationCallback
callback) {
provider_->EvaluateRequestedNavigation(std::move(requested_navigation),
std::move(callback));
}

bool NavigationPolicyHandler::ShouldEvaluateNavigation(
content::NavigationHandle* handle,
fuchsia::web::NavigationPhase phase) {
if (handle->IsInMainFrame()) {
return (phase & params_.main_frame_phases()) == phase;
}

return (phase & params_.subframe_phases()) == phase;
}

bool NavigationPolicyHandler::is_provider_connected() {
return provider_.is_bound();
}

void NavigationPolicyHandler::OnNavigationPolicyProviderDisconnected(
zx_status_t status) {
ZX_LOG(ERROR, status) << "NavigationPolicyProvider disconnected";
for (auto* throttle : navigation_throttles_) {
throttle->OnNavigationPolicyProviderDisconnected(
content::NavigationThrottle::CANCEL);
}
navigation_throttles_.clear();
}
59 changes: 59 additions & 0 deletions fuchsia/engine/browser/navigation_policy_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2020 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.

#ifndef FUCHSIA_ENGINE_BROWSER_NAVIGATION_POLICY_HANDLER_H_
#define FUCHSIA_ENGINE_BROWSER_NAVIGATION_POLICY_HANDLER_H_

#include <fuchsia/web/cpp/fidl.h>

#include "base/containers/flat_set.h"

class NavigationPolicyThrottle;

namespace content {
class NavigationHandle;
} // namespace content

class NavigationPolicyHandler {
public:
NavigationPolicyHandler(
fuchsia::web::NavigationPolicyProviderParams params,
fidl::InterfaceHandle<fuchsia::web::NavigationPolicyProvider> delegate);
~NavigationPolicyHandler();

NavigationPolicyHandler(const NavigationPolicyHandler&) = delete;
NavigationPolicyHandler& operator=(const NavigationPolicyHandler&) = delete;

void RegisterNavigationThrottle(
NavigationPolicyThrottle* navigation_throttle);
void RemoveNavigationThrottle(NavigationPolicyThrottle* navigation_throttle);

fuchsia::web::NavigationPolicyProvider* navigation_policy_provider() {
return provider_.get();
}

bool is_provider_connected();

// Passes on the call to |provider_|.
void EvaluateRequestedNavigation(
fuchsia::web::RequestedNavigation requested_navigation,
fuchsia::web::NavigationPolicyProvider::
EvaluateRequestedNavigationCallback callback);

// Determines whether or not the client is interested in evaluating |handle|.
bool ShouldEvaluateNavigation(content::NavigationHandle* handle,
fuchsia::web::NavigationPhase phase);

private:
void OnNavigationPolicyProviderDisconnected(zx_status_t status);

fuchsia::web::NavigationPolicyProviderParams params_;
fuchsia::web::NavigationPolicyProviderPtr provider_;

// Keeps track of the NavigationThrottles associated with the Frame that owns
// |this|.
base::flat_set<NavigationPolicyThrottle*> navigation_throttles_;
};

#endif // FUCHSIA_ENGINE_BROWSER_NAVIGATION_POLICY_HANDLER_H_
122 changes: 122 additions & 0 deletions fuchsia/engine/browser/navigation_policy_throttle.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2020 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 "fuchsia/engine/browser/navigation_policy_throttle.h"

#include "content/public/browser/navigation_handle.h"
#include "fuchsia/engine/browser/navigation_policy_handler.h"

namespace {

fuchsia::web::RequestedNavigation ToRequestedNavigation(
content::NavigationHandle* handle,
fuchsia::web::NavigationPhase phase) {
fuchsia::web::RequestedNavigation event;
event.set_id(static_cast<uint64_t>(handle->GetNavigationId()));
event.set_phase(phase);
event.set_is_main_frame(handle->IsInMainFrame());
event.set_is_same_document(handle->IsSameDocument());
event.set_is_http_post(handle->IsPost());
event.set_url(handle->GetURL().spec());
event.set_has_gesture(handle->HasUserGesture());
event.set_was_server_redirect(handle->WasServerRedirect());

return event;
}

} // namespace

NavigationPolicyThrottle::NavigationPolicyThrottle(
content::NavigationHandle* handle,
NavigationPolicyHandler* policy_handler)
: NavigationThrottle(handle),
policy_handler_(policy_handler),
navigation_handle_(handle) {
if (policy_handler->is_provider_connected()) {
policy_handler_->RegisterNavigationThrottle(this);
} else {
policy_handler_ = nullptr;
}
}

NavigationPolicyThrottle::~NavigationPolicyThrottle() {
if (policy_handler_)
policy_handler_->RemoveNavigationThrottle(this);
}

void NavigationPolicyThrottle::OnNavigationPolicyProviderDisconnected(
content::NavigationThrottle::ThrottleCheckResult check_result) {
if (is_paused_) {
CancelDeferredNavigation(check_result);
is_paused_ = false;
}

policy_handler_ = nullptr;
}

void NavigationPolicyThrottle::OnRequestedNavigationEvaluated(
fuchsia::web::NavigationDecision decision) {
DCHECK(is_paused_);

switch (decision.Which()) {
case fuchsia::web::NavigationDecision::kProceed:
Resume();
break;
case fuchsia::web::NavigationDecision::kAbort:
CancelDeferredNavigation(content::NavigationThrottle::CANCEL);
break;
default:
NOTREACHED();
}
is_paused_ = false;
}

content::NavigationThrottle::ThrottleCheckResult
NavigationPolicyThrottle::WillStartRequest() {
return HandleNavigationPhase(fuchsia::web::NavigationPhase::START);
}

content::NavigationThrottle::ThrottleCheckResult
NavigationPolicyThrottle::WillRedirectRequest() {
return HandleNavigationPhase(fuchsia::web::NavigationPhase::REDIRECT);
}

content::NavigationThrottle::ThrottleCheckResult
NavigationPolicyThrottle::WillFailRequest() {
return HandleNavigationPhase(fuchsia::web::NavigationPhase::FAIL);
}

content::NavigationThrottle::ThrottleCheckResult
NavigationPolicyThrottle::WillProcessResponse() {
return HandleNavigationPhase(fuchsia::web::NavigationPhase::PROCESS_RESPONSE);
}

const char* NavigationPolicyThrottle::GetNameForLogging() {
return "NavigationPolicyThrottle";
}

content::NavigationThrottle::ThrottleCheckResult
NavigationPolicyThrottle::HandleNavigationPhase(
fuchsia::web::NavigationPhase phase) {
DCHECK(!is_paused_);

if (!policy_handler_) {
return content::NavigationThrottle::ThrottleCheckResult(
content::NavigationThrottle::CANCEL);
}

if (!policy_handler_->ShouldEvaluateNavigation(navigation_handle_, phase)) {
return content::NavigationThrottle::ThrottleCheckResult(
content::NavigationThrottle::PROCEED);
}

policy_handler_->navigation_policy_provider()->EvaluateRequestedNavigation(
ToRequestedNavigation(navigation_handle_, phase),
fit::bind_member(
this, &NavigationPolicyThrottle::OnRequestedNavigationEvaluated));

is_paused_ = true;
return content::NavigationThrottle::ThrottleCheckResult(
content::NavigationThrottle::DEFER);
}
Loading

0 comments on commit 17bbb4d

Please sign in to comment.