blob: d7b96013baa54b4f8e9f6a27b1241b96dfd190f8 [file] [log] [blame]
// Copyright 2015 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 "mojo/fetcher/data_fetcher.h"
#include <stdint.h>
#include <utility>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/thread_task_runner_handle.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/data_url.h"
namespace mojo {
namespace fetcher {
ScopedDataPipeConsumerHandle CreateConsumerHandleForString(
const std::string& data) {
if (data.size() > std::numeric_limits<uint32_t>::max())
return ScopedDataPipeConsumerHandle();
uint32_t num_bytes = static_cast<uint32_t>(data.size());
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
options.element_num_bytes = 1;
options.capacity_num_bytes = num_bytes;
mojo::DataPipe data_pipe(options);
MojoResult result =
WriteDataRaw(data_pipe.producer_handle.get(), data.data(), &num_bytes,
MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
CHECK_EQ(MOJO_RESULT_OK, result);
return std::move(data_pipe.consumer_handle);
}
// static
void DataFetcher::Start(const GURL& url, const FetchCallback& loader_callback) {
// The object manages its own lifespan.
new DataFetcher(url, loader_callback);
}
DataFetcher::DataFetcher(const GURL& url, const FetchCallback& loader_callback)
: Fetcher(loader_callback), url_(url) {
BuildAndDispatchResponse();
}
DataFetcher::~DataFetcher() {}
void DataFetcher::BuildAndDispatchResponse() {
response_ = URLResponse::New();
response_->url = url_.spec();
response_->status_code = 400; // Bad request
if (url_.SchemeIs(url::kDataScheme)) {
std::string mime_type, charset, data;
if (net::DataURL::Parse(url_, &mime_type, &charset, &data)) {
response_->status_code = 200;
response_->mime_type = mime_type;
response_->charset = charset;
if (!data.empty())
response_->body = CreateConsumerHandleForString(data);
}
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(loader_callback_,
base::Passed(make_scoped_ptr<Fetcher>(this))));
}
const GURL& DataFetcher::GetURL() const {
return url_;
}
GURL DataFetcher::GetRedirectURL() const {
return GURL::EmptyGURL();
}
GURL DataFetcher::GetRedirectReferer() const {
return GURL::EmptyGURL();
}
URLResponsePtr DataFetcher::AsURLResponse(base::TaskRunner* task_runner,
uint32_t skip) {
DCHECK(response_);
return std::move(response_);
}
void DataFetcher::AsPath(
base::TaskRunner* task_runner,
base::Callback<void(const base::FilePath&, bool)> callback) {
NOTIMPLEMENTED();
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(callback, base::FilePath(), false));
}
std::string DataFetcher::MimeType() {
DCHECK(response_);
return response_->mime_type;
}
bool DataFetcher::HasMojoMagic() {
return false;
}
bool DataFetcher::PeekFirstLine(std::string* line) {
// This is only called for 'mojo magic' (i.e. detecting shebang'ed
// content-handler. Since HasMojoMagic() returns false above, this should
// never be reached.
NOTREACHED();
return false;
}
} // namespace fetcher
} // namespace mojo