Commit ec2e2f99 authored by Eric Willigers's avatar Eric Willigers Committed by Commit Bot

Web Share: Protect against attempts to share many files, or large files

As in ShareServiceImpl.java, the browser process rejects attempts to
share more than 10 files at once, or share any file larger than
50 megabytes.

Browser enforcement of these limits is only relevant in the event a
renderer process is compromised, as NavigatorShare::share also
imposes limits.


Bug: 1035527,1110119
Change-Id: I3a9d5a5df528616b2512a3d9efdfe54ffa320b36
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2386937Reviewed-by: default avatarEric Willigers <ericwilligers@chromium.org>
Reviewed-by: default avatarGlen Robertson <glenrob@chromium.org>
Auto-Submit: Eric Willigers <ericwilligers@chromium.org>
Commit-Queue: Eric Willigers <ericwilligers@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803735}
parent 57222af9
......@@ -4,13 +4,17 @@
#include "chrome/browser/webshare/share_service_impl.h"
#include "base/feature_list.h"
#include "chrome/common/chrome_features.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
ShareServiceImpl::ShareServiceImpl(content::RenderFrameHost& render_frame_host)
: content::WebContentsObserver(
content::WebContents::FromRenderFrameHost(&render_frame_host)),
render_frame_host_(&render_frame_host) {}
render_frame_host_(&render_frame_host) {
DCHECK(base::FeatureList::IsEnabled(features::kWebShare));
}
ShareServiceImpl::~ShareServiceImpl() = default;
......@@ -28,6 +32,25 @@ void ShareServiceImpl::Share(const std::string& title,
const GURL& share_url,
std::vector<blink::mojom::SharedFilePtr> files,
ShareCallback callback) {
if (files.size() > kMaxSharedFileCount) {
std::move(callback).Run(blink::mojom::ShareError::PERMISSION_DENIED);
return;
}
uint64_t total_bytes = 0;
for (auto& file : files) {
if (!file || !file->blob) {
mojo::ReportBadMessage("Invalid file to share()");
return;
}
total_bytes += file->blob->size;
}
if (total_bytes > kMaxSharedFileBytes) {
std::move(callback).Run(blink::mojom::ShareError::PERMISSION_DENIED);
return;
}
// TODO(crbug.com/1035527): Add implementation for OS_WIN
// TODO(crbug.com/1110119): Add implementation for OS_CHROMEOS
NOTIMPLEMENTED();
......
......@@ -17,6 +17,9 @@ namespace content {
class RenderFrameHost;
}
constexpr size_t kMaxSharedFileCount = 10;
constexpr uint64_t kMaxSharedFileBytes = 50 * 1024 * 1024;
class ShareServiceImpl : public blink::mojom::ShareService,
public content::WebContentsObserver {
public:
......
// 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 <memory>
#include <string>
#include <vector>
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/webshare/share_service_impl.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "url/gurl.h"
using blink::mojom::ShareError;
class ShareServiceUnitTest : public ChromeRenderViewHostTestHarness {
public:
ShareServiceUnitTest() {
feature_list_.InitAndEnableFeature(features::kWebShare);
}
~ShareServiceUnitTest() override = default;
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
share_service_ = std::make_unique<ShareServiceImpl>(*main_rfh());
}
ShareError ShareGeneratedFileData(const std::string& extension,
const std::string& mime_type,
unsigned file_length,
unsigned file_count = 1) {
const std::string kTitle;
const std::string kText;
const GURL kUrl;
std::vector<blink::mojom::SharedFilePtr> files;
files.reserve(file_count);
for (unsigned index = 0; index < file_count; ++index) {
const std::string name =
base::StringPrintf("share%d%s", index, extension.c_str());
auto blob = blink::mojom::SerializedBlob::New();
blob->content_type = mime_type;
blob->size = file_length;
files.push_back(blink::mojom::SharedFile::New(name, std::move(blob)));
}
ShareError result;
base::RunLoop run_loop;
share_service_->Share(
kTitle, kText, kUrl, std::move(files),
base::BindLambdaForTesting([&result, &run_loop](ShareError error) {
result = error;
run_loop.Quit();
}));
run_loop.Run();
return result;
}
private:
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<ShareServiceImpl> share_service_;
};
TEST_F(ShareServiceUnitTest, FileCount) {
EXPECT_EQ(
ShareError::CANCELED,
ShareGeneratedFileData(".txt", "text/plain", 1234, kMaxSharedFileCount));
EXPECT_EQ(ShareError::PERMISSION_DENIED,
ShareGeneratedFileData(".txt", "text/plain", 1234,
kMaxSharedFileCount + 1));
}
TEST_F(ShareServiceUnitTest, TotalBytes) {
EXPECT_EQ(ShareError::CANCELED,
ShareGeneratedFileData(".txt", "text/plain",
kMaxSharedFileBytes / kMaxSharedFileCount,
kMaxSharedFileCount));
EXPECT_EQ(
ShareError::PERMISSION_DENIED,
ShareGeneratedFileData(".txt", "text/plain",
(kMaxSharedFileBytes / kMaxSharedFileCount) + 1,
kMaxSharedFileCount));
}
TEST_F(ShareServiceUnitTest, FileBytes) {
EXPECT_EQ(ShareError::CANCELED,
ShareGeneratedFileData(".txt", "text/plain", kMaxSharedFileBytes));
EXPECT_EQ(
ShareError::PERMISSION_DENIED,
ShareGeneratedFileData(".txt", "text/plain", kMaxSharedFileBytes + 1));
}
......@@ -3732,6 +3732,10 @@ test("unit_tests") {
}
}
if (is_win || is_chromeos) {
sources += [ "../browser/webshare/share_service_unittest.cc" ]
}
if (enable_library_cdms) {
sources += [ "../common/media/cdm_manifest_unittest.cc" ]
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment