blob: 62ade740022649132f685b3a6cb4f565dad59dcc [file] [log] [blame]
// 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 "content/browser/native_io/native_io_context.h"
#include <memory>
#include <utility>
#include "base/files/file_path.h"
#include "content/browser/native_io/native_io_host.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/blink/public/mojom/native_io/native_io.mojom.h"
#include "url/origin.h"
namespace content {
namespace {
constexpr base::FilePath::CharType kNativeIODirectoryName[] =
FILE_PATH_LITERAL("NativeIO");
base::FilePath GetNativeIORootPath(const base::FilePath& profile_root) {
if (profile_root.empty())
return base::FilePath();
return profile_root.Append(kNativeIODirectoryName);
}
} // namespace
NativeIOContext::NativeIOContext(const base::FilePath& profile_root)
: root_path_(GetNativeIORootPath(profile_root)) {}
NativeIOContext::~NativeIOContext() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
}
void NativeIOContext::BindReceiver(
const url::Origin& origin,
mojo::PendingReceiver<blink::mojom::NativeIOHost> receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = hosts_.find(origin);
if (it == hosts_.end()) {
base::FilePath origin_root_path = RootPathForOrigin(origin);
if (origin_root_path.empty()) {
// NativeIO is not supported for the origin.
return;
}
DCHECK(root_path_.IsParent(origin_root_path))
<< "Per-origin data should be in a sub-directory of NativeIO/";
bool insert_succeeded;
std::tie(it, insert_succeeded) =
hosts_.insert({origin, std::make_unique<NativeIOHost>(
this, origin, std::move(origin_root_path))});
}
it->second->BindReceiver(std::move(receiver));
}
void NativeIOContext::OnHostReceiverDisconnect(NativeIOHost* host) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(host != nullptr);
DCHECK(hosts_.count(host->origin()) > 0);
DCHECK_EQ(hosts_[host->origin()].get(), host);
if (!host->has_empty_receiver_set())
return;
hosts_.erase(host->origin());
}
base::FilePath NativeIOContext::RootPathForOrigin(const url::Origin& origin) {
// TODO(pwnall): Implement in-memory files instead of bouncing in incognito.
if (root_path_.empty())
return root_path_;
// This feature is only exposed to secure origins. This typically means https.
// The most notable exception is http://localhost. Command-line flags may
// cause other http origins to be considered secure.
//
// TODO(pwnall): Get consensus on the schemes we want to support. For example,
// maybe chrome-extension:// should get access as well?
if (!origin.GetURL().SchemeIsHTTPOrHTTPS())
return base::FilePath();
std::string origin_identifier = storage::GetIdentifierFromOrigin(origin);
base::FilePath origin_path = root_path_.AppendASCII(origin_identifier);
DCHECK(root_path_.IsParent(origin_path));
return origin_path;
}
} // namespace content