#include "content/browser/renderer_host/blocked_scheme_navigation_throttle.h"
#include "base/feature_list.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/common/features.h"
#include "content/common/navigation_params_utils.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "storage/browser/file_system/external_mount_points.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/common/file_system/file_system_util.h"
#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
#include "url/url_constants.h"
namespace content {
namespace {
const char kConsoleError[] = "Not allowed to navigate top frame to %s URL: %s";
const char kAnyFrameConsoleError[] = "Not allowed to navigate to %s URL: %s";
bool IsExternalMountedFile(const GURL& url) {
storage::FileSystemURL file_system_url =
storage::ExternalMountPoints::GetSystemInstance()->CrackURL(
url, blink::StorageKey::CreateFirstParty(url::Origin::Create(url)));
return file_system_url.is_valid();
}
}
BlockedSchemeNavigationThrottle::BlockedSchemeNavigationThrottle(
NavigationThrottleRegistry& registry)
: NavigationThrottle(registry) {}
BlockedSchemeNavigationThrottle::~BlockedSchemeNavigationThrottle() {}
NavigationThrottle::ThrottleCheckResult
BlockedSchemeNavigationThrottle::WillStartRequest() {
NavigationRequest* request = NavigationRequest::From(navigation_handle());
if (!request->GetURL().SchemeIs(url::kFileSystemScheme)) {
return PROCEED;
}
if (base::FeatureList::IsEnabled(blink::features::kFileSystemUrlNavigation)) {
return PROCEED;
}
RenderFrameHost* top_frame =
request->frame_tree_node()->frame_tree().root()->current_frame_host();
BrowserContext* browser_context = top_frame->GetBrowserContext();
if (base::FeatureList::IsEnabled(
blink::features::kFileSystemUrlNavigationForChromeAppsOnly) &&
!IsExternalMountedFile(request->GetURL()) &&
(url::Origin::Create(request->GetURL()) ==
request->GetInitiatorOrigin()) &&
GetContentClient()->browser()->IsFileSystemURLNavigationAllowed(
browser_context, request->GetURL())) {
return PROCEED;
}
top_frame->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(kAnyFrameConsoleError,
request->GetURL().GetScheme().c_str(),
request->GetURL().spec().c_str()));
return CANCEL;
}
NavigationThrottle::ThrottleCheckResult
BlockedSchemeNavigationThrottle::WillProcessResponse() {
NavigationRequest* request = NavigationRequest::From(navigation_handle());
if (request->IsDownload()) {
return PROCEED;
}
RenderFrameHost* top_frame =
request->frame_tree_node()->frame_tree().root()->current_frame_host();
top_frame->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(kConsoleError, request->GetURL().GetScheme().c_str(),
request->GetURL().spec().c_str()));
return CANCEL;
}
const char* BlockedSchemeNavigationThrottle::GetNameForLogging() {
return "BlockedSchemeNavigationThrottle";
}
void BlockedSchemeNavigationThrottle::MaybeCreateAndAdd(
NavigationThrottleRegistry& registry) {
NavigationHandle& handle = registry.GetNavigationHandle();
if (handle.IsInMainFrame() && handle.IsRendererInitiated() &&
!handle.IsSameDocument() && !handle.IsHistory() &&
(handle.GetURL().SchemeIs(url::kDataScheme) ||
handle.GetURL().SchemeIs(url::kFileSystemScheme)) &&
!base::FeatureList::IsEnabled(
features::kAllowContentInitiatedDataUrlNavigations)) {
registry.AddThrottle(
std::make_unique<BlockedSchemeNavigationThrottle>(registry));
return;
}
RenderFrameHost* current_frame_host =
NavigationRequest::From(&handle)->frame_tree_node()->current_frame_host();
BrowserContext* browser_context = current_frame_host->GetBrowserContext();
bool is_navigation_allowed =
base::FeatureList::IsEnabled(
blink::features::kFileSystemUrlNavigationForChromeAppsOnly) &&
(url::Origin::Create(handle.GetURL()) == handle.GetInitiatorOrigin()) &&
GetContentClient()->browser()->IsFileSystemURLNavigationAllowed(
browser_context, handle.GetURL());
if (!is_navigation_allowed &&
!base::FeatureList::IsEnabled(
blink::features::kFileSystemUrlNavigation) &&
handle.IsRendererInitiated() &&
handle.GetURL().SchemeIs(url::kFileSystemScheme)) {
registry.AddThrottle(
std::make_unique<BlockedSchemeNavigationThrottle>(registry));
return;
}
if (!base::FeatureList::IsEnabled(
blink::features::kFileSystemUrlNavigation) &&
IsExternalMountedFile(handle.GetURL())) {
registry.AddThrottle(
std::make_unique<BlockedSchemeNavigationThrottle>(registry));
}
}
}