blob: c193a35392b3ab8ef70ee68ac868eed24053f5b6 [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/embedded_fetcher.h"
#include <algorithm>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "cobalt/base/localized_strings.h"
#include "cobalt/loader/embedded_resources.h" // Generated.
namespace cobalt {
namespace loader {
namespace {
bool EmbeddedURLToKey(const GURL& url, std::string* key) {
DCHECK(url.is_valid() && url.SchemeIs(kEmbeddedScheme));
*key = url.path();
DCHECK_EQ('/', (*key)[0]);
DCHECK_EQ('/', (*key)[1]);
(*key).erase(0, 2);
return !key->empty();
}
} // namespace
const char kEmbeddedScheme[] = "h5vcc-embedded";
EmbeddedFetcher::EmbeddedFetcher(const GURL& url,
const csp::SecurityCallback& security_callback,
Handler* handler, const Options& options)
: Fetcher(handler),
url_(url),
security_callback_(security_callback),
ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
// Embedded assets are available in-memory and can be loaded synchronously.
Fetch(options);
}
EmbeddedFetcher::~EmbeddedFetcher() {}
void EmbeddedFetcher::Fetch(const Options& options) {
if (!IsAllowedByCsp()) {
std::string msg(base::StringPrintf("URL %s rejected by security policy.",
url_.spec().c_str()));
handler()->OnError(this, msg);
return;
}
std::string key;
if (!EmbeddedURLToKey(url_, &key)) {
std::string msg(
base::StringPrintf("Invalid embedded URL: %s.", url_.spec().c_str()));
handler()->OnError(this, msg);
return;
}
GetEmbeddedData(key, options.start_offset, options.bytes_to_read);
}
void EmbeddedFetcher::GetEmbeddedData(const std::string& key,
int64 start_offset, int64 bytes_to_read) {
const char kDataNotFoundError[] = "Embedded data not found.";
GeneratedResourceMap resource_map;
LoaderEmbeddedResources::GenerateMap(resource_map);
if (resource_map.find(key) == resource_map.end()) {
handler()->OnError(this, kDataNotFoundError);
return;
}
FileContents file_contents = resource_map[key];
const char* data = reinterpret_cast<const char*>(file_contents.data);
size_t size = static_cast<size_t>(file_contents.size);
data += start_offset;
// If the key is a template file, localized the strings in the file data.
if (base::EndsWith(key, ".template", base::CompareCase::SENSITIVE)) {
std::string output_file(data);
LocalizeFileData(&output_file);
const char* final_data = output_file.c_str();
size = std::min(static_cast<size_t>(output_file.size()),
static_cast<size_t>(bytes_to_read));
handler()->OnReceived(this, final_data, size);
} else {
size = std::min(size, static_cast<size_t>(bytes_to_read));
handler()->OnReceived(this, data, size);
}
handler()->OnDone(this);
}
bool EmbeddedFetcher::IsAllowedByCsp() {
bool did_redirect = false;
if (security_callback_.is_null() ||
security_callback_.Run(url_, did_redirect)) {
return true;
} else {
return false;
}
}
void EmbeddedFetcher::LocalizeFileData(std::string* output_file) {
base::LocalizedStrings* localized_strings =
base::LocalizedStrings::GetInstance();
std::string opening_delimiter = "[[";
std::vector<std::string> parts =
base::SplitStringUsingSubstr(*output_file, opening_delimiter,
base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
for (size_t idx = 1; idx < parts.size(); ++idx) {
std::string& value = parts[idx];
std::string closing_delimiter = "]]";
std::vector<std::string> key_result = base::SplitStringUsingSubstr(
value, closing_delimiter, base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
size_t key_results = key_result.size();
if (key_results > 1) {
std::string& message_postfix = key_result[1];
std::string localized_message =
localized_strings->GetString(key_result[0], "");
value = localized_message + message_postfix;
} else {
value = key_result[0];
}
}
*output_file = base::JoinString(parts, std::string());
}
} // namespace loader
} // namespace cobalt