blob: 83531c6ec2b8e52e9300d011ae239179637246ad [file] [log] [blame]
// Copyright 2015 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "cobalt/loader/fetcher_factory.h"
#include <memory>
#include <sstream>
#include <string>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "cobalt/loader/about_fetcher.h"
#include "cobalt/loader/blob_fetcher.h"
#include "cobalt/loader/cache_fetcher.h"
#include "cobalt/loader/embedded_fetcher.h"
#include "cobalt/loader/error_fetcher.h"
#include "cobalt/loader/file_fetcher.h"
#include "cobalt/loader/net_fetcher.h"
#include "cobalt/network/network_module.h"
namespace cobalt {
namespace loader {
namespace {
#if defined(ENABLE_ABOUT_SCHEME)
const char kAboutScheme[] = "about";
#endif
bool FileURLToFilePath(const GURL& url, base::FilePath* file_path) {
DCHECK(url.is_valid() && url.SchemeIsFile());
std::string path = url.path();
DCHECK_EQ('/', path[0]);
path.erase(0, 1);
*file_path = base::FilePath(path);
return !file_path->empty();
}
std::string ClipUrl(const GURL& url, size_t length) {
const std::string& spec = url.possibly_invalid_spec();
if (spec.size() < length) {
return spec;
}
size_t remain = length - 5;
size_t head = remain / 2;
size_t tail = remain - head;
return spec.substr(0, head) + "[...]" + spec.substr(spec.size() - tail);
}
} // namespace
FetcherFactory::FetcherFactory(network::NetworkModule* network_module)
: file_thread_("File"),
network_module_(network_module),
read_cache_callback_() {
file_thread_.Start();
}
FetcherFactory::FetcherFactory(network::NetworkModule* network_module,
const base::FilePath& extra_search_dir)
: file_thread_("File"),
network_module_(network_module),
extra_search_dir_(extra_search_dir),
read_cache_callback_() {
file_thread_.Start();
}
FetcherFactory::FetcherFactory(
network::NetworkModule* network_module,
const base::FilePath& extra_search_dir,
const BlobFetcher::ResolverCallback& blob_resolver,
const base::Callback<int(const std::string&, std::unique_ptr<char[]>*)>&
read_cache_callback)
: file_thread_("File"),
network_module_(network_module),
extra_search_dir_(extra_search_dir),
blob_resolver_(blob_resolver),
read_cache_callback_(read_cache_callback) {
file_thread_.Start();
}
std::unique_ptr<Fetcher> FetcherFactory::CreateFetcher(
const GURL& url, Fetcher::Handler* handler) {
return CreateSecureFetcher(url, csp::SecurityCallback(), kNoCORSMode,
Origin(), handler);
}
std::unique_ptr<Fetcher> FetcherFactory::CreateSecureFetcher(
const GURL& url, const csp::SecurityCallback& url_security_callback,
RequestMode request_mode, const Origin& origin, Fetcher::Handler* handler) {
LOG(INFO) << "Fetching: " << ClipUrl(url, 200);
if (!url.is_valid()) {
std::stringstream error_message;
error_message << "URL is invalid: " << url;
return std::unique_ptr<Fetcher>(
new ErrorFetcher(handler, error_message.str()));
}
if ((url.SchemeIs("https") || url.SchemeIs("http") || url.SchemeIs("data")) &&
network_module_) {
NetFetcher::Options options;
return std::unique_ptr<Fetcher>(
new NetFetcher(url, url_security_callback, handler, network_module_,
options, request_mode, origin));
}
if (url.SchemeIs("blob") && !blob_resolver_.is_null()) {
return std::unique_ptr<Fetcher>(
new BlobFetcher(url, handler, blob_resolver_));
}
if (url.SchemeIs(kEmbeddedScheme)) {
EmbeddedFetcher::Options options;
return std::unique_ptr<Fetcher>(
new EmbeddedFetcher(url, url_security_callback, handler, options));
}
// h5vcc-cache: scheme requires read_cache_callback_ which is not available
// in the main WebModule.
if (url.SchemeIs(kCacheScheme) && !read_cache_callback_.is_null()) {
return std::unique_ptr<Fetcher>(new CacheFetcher(
url, url_security_callback, handler, read_cache_callback_));
}
if (url.SchemeIsFile()) {
base::FilePath file_path;
if (!FileURLToFilePath(url, &file_path)) {
std::stringstream error_message;
error_message << "File URL cannot be converted to file path: " << url;
return std::unique_ptr<Fetcher>(
new ErrorFetcher(handler, error_message.str()));
}
FileFetcher::Options options;
options.message_loop_proxy = file_thread_.task_runner();
options.extra_search_dir = extra_search_dir_;
return std::unique_ptr<Fetcher>(
new FileFetcher(file_path, handler, options));
}
#if defined(ENABLE_ABOUT_SCHEME)
if (url.SchemeIs(kAboutScheme)) {
return std::unique_ptr<Fetcher>(new AboutFetcher(handler));
}
#endif
std::stringstream error_message;
error_message << "Scheme " << url.scheme() << ": is not supported";
return std::unique_ptr<Fetcher>(
new ErrorFetcher(handler, error_message.str()));
}
} // namespace loader
} // namespace cobalt