Skip to content

Commit

Permalink
WebTorrent: intercept only top-level frame requests for .torrent files
Browse files Browse the repository at this point in the history
If a web page embeds the WebTorrent client-side JS library and attempts to
load a .torrent file using an XHR request or fetch, Brave will intercept the
.torrent file load and replace it with the chrome-extension HTML, breaking the
site. This is true not just for the WebTorrent JS library but for any request
to fetch a .torrent file.

Fixes: brave/brave-browser#5361
Fixes: brave/brave-browser#3164
Fixes: brave/brave-browser#1436
  • Loading branch information
feross committed Jul 26, 2019
1 parent 623a37f commit 03868fe
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@

#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "brave/common/network_constants.h"
#include "brave/common/extensions/extension_constants.h"
#include "brave/common/network_constants.h"
#include "content/public/common/resource_type.h"
#include "extensions/common/constants.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_response_headers.h"
Expand Down Expand Up @@ -74,6 +75,16 @@ bool IsWebtorrentInitiated(std::shared_ptr<brave::BraveRequestInfo> ctx) {
ctx->initiator_url.host() == brave_webtorrent_extension_id;
}

/*
* Returns true if the resource type is a frame (i.e. a top level page) or a
* subframe (i.e. a frame or iframe). For all other resource types (stylesheet,
* script, XHR request, etc.), returns false.
*/

bool IsFrameResource(std::shared_ptr<brave::BraveRequestInfo> ctx) {
return content::IsResourceTypeFrame(ctx->resource_type);
}

} // namespace

namespace webtorrent {
Expand All @@ -85,6 +96,7 @@ int OnHeadersReceived_TorrentRedirectWork(
const brave::ResponseCallback& next_callback,
std::shared_ptr<brave::BraveRequestInfo> ctx) {
if (!original_response_headers ||
!IsFrameResource(ctx) ||
ctx->is_webtorrent_disabled ||
// download .torrent, do not redirect
(IsWebtorrentInitiated(ctx) && !IsViewerURL(ctx->request_url)) ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/common/resource_type.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
Expand Down Expand Up @@ -120,6 +121,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -156,6 +158,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -194,6 +197,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -237,6 +241,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -276,6 +281,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -310,6 +316,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest, MimeTypeNoRedirect) {
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -348,6 +355,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand Down Expand Up @@ -386,6 +394,7 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kMainFrame;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
Expand All @@ -402,3 +411,40 @@ TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
torrent_viewer_extension_url().spec());
EXPECT_EQ(ret, net::OK);
}

TEST_F(BraveTorrentRedirectNetworkDelegateHelperTest,
BittorrentNonFrameResourceNoRedirect) {
net::TestDelegate test_delegate;
std::unique_ptr<net::URLRequest> request =
context()->CreateRequest(torrent_url(), net::IDLE, &test_delegate,
TRAFFIC_ANNOTATION_FOR_TESTS);

scoped_refptr<net::HttpResponseHeaders> orig_response_headers =
new net::HttpResponseHeaders(std::string());
orig_response_headers->AddHeader(
base::StrCat({"Content-Type: ", kBittorrentMimeType}));
std::string mimeType;
ASSERT_TRUE(orig_response_headers->GetMimeType(&mimeType));
ASSERT_EQ(mimeType, kBittorrentMimeType);

scoped_refptr<net::HttpResponseHeaders> overwrite_response_headers =
new net::HttpResponseHeaders(std::string());
GURL allowed_unsafe_redirect_url = GURL::EmptyGURL();
std::shared_ptr<brave::BraveRequestInfo>
brave_request_info(new brave::BraveRequestInfo());
brave::BraveRequestInfo::FillCTXFromRequest(request.get(),
brave_request_info);
brave_request_info->resource_type = content::ResourceType::kXhr;
brave::ResponseCallback callback;

int ret = webtorrent::OnHeadersReceived_TorrentRedirectWork(
orig_response_headers.get(), &overwrite_response_headers,
&allowed_unsafe_redirect_url, callback, brave_request_info);

EXPECT_EQ(overwrite_response_headers->GetStatusLine(), "HTTP/1.0 200 OK");
std::string location;
EXPECT_FALSE(overwrite_response_headers->EnumerateHeader(nullptr, "Location",
&location));
EXPECT_EQ(allowed_unsafe_redirect_url, GURL::EmptyGURL());
EXPECT_EQ(ret, net::OK);
}

0 comments on commit 03868fe

Please sign in to comment.