blob: 9d6ac9246d36353b2c637cc7705479b981dece9d [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 "components/html_viewer/html_frame_properties.h"
#include "base/logging.h"
#include "base/pickle.h"
#include "mojo/common/common_type_converters.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "url/origin.h"
#include "url/url_util.h"
namespace html_viewer {
const char kPropertyFrameTreeScope[] = "html-viewer-frame-tree-scope";
const char kPropertyFrameOrigin[] = "html-viewer-replicated-frame-origin";
const char kPropertyFrameName[] = "html-viewer-replicated-frame-name";
const char kPropertyFrameSandboxFlags[] = "html-viewer-sandbox-flags";
namespace {
mojo::Array<uint8_t> IntToClientPropertyArray(int value) {
mojo::Array<uint8_t> value_array(sizeof(value));
memcpy(&(value_array.front()), &value, sizeof(value));
return value_array.Pass();
}
bool IntFromClientPropertyArray(const mojo::Array<uint8_t>& value_array,
int* value) {
if (value_array.is_null())
return false;
CHECK(value_array.size() == sizeof(int));
memcpy(value, &(value_array.front()), sizeof(int));
return true;
}
} // namespace
mojo::Array<uint8_t> FrameNameToClientProperty(const blink::WebString& name) {
mojo::String mojo_name;
if (name.isNull())
return mojo::Array<uint8_t>();
return mojo::Array<uint8_t>::From<std::string>(name.utf8());
}
blink::WebString FrameNameFromClientProperty(
const mojo::Array<uint8_t>& new_data) {
if (new_data.is_null())
return blink::WebString();
return blink::WebString::fromUTF8(new_data.To<std::string>());
}
mojo::Array<uint8_t> FrameTreeScopeToClientProperty(
blink::WebTreeScopeType scope_type) {
return IntToClientPropertyArray(static_cast<int>(scope_type)).Pass();
}
bool FrameTreeScopeFromClientProperty(const mojo::Array<uint8_t>& new_data,
blink::WebTreeScopeType* scope) {
if (new_data.is_null())
return false;
int scope_as_int;
CHECK(IntFromClientPropertyArray(new_data, &scope_as_int));
CHECK(scope_as_int >= 0 &&
scope_as_int <= static_cast<int>(blink::WebTreeScopeType::Last));
*scope = static_cast<blink::WebTreeScopeType>(scope_as_int);
return true;
}
mojo::Array<uint8_t> FrameSandboxFlagsToClientProperty(
blink::WebSandboxFlags flags) {
return IntToClientPropertyArray(static_cast<int>(flags)).Pass();
}
bool FrameSandboxFlagsFromClientProperty(const mojo::Array<uint8_t>& new_data,
blink::WebSandboxFlags* flags) {
if (new_data.is_null())
return false;
// blink::WebSandboxFlags is a bitmask, so not error checking.
int flags_as_int;
CHECK(IntFromClientPropertyArray(new_data, &flags_as_int));
*flags = static_cast<blink::WebSandboxFlags>(flags_as_int);
return true;
}
url::Origin FrameOrigin(blink::WebFrame* frame) {
std::string scheme = frame->document().securityOrigin().protocol().utf8();
if (!url::IsStandard(scheme.c_str(),
url::Component(0, static_cast<int>(scheme.length())))) {
return url::Origin();
}
return frame->document().securityOrigin();
}
mojo::Array<uint8_t> FrameOriginToClientProperty(blink::WebFrame* frame) {
const url::Origin origin = FrameOrigin(frame);
base::Pickle pickle;
pickle.WriteBool(origin.unique());
pickle.WriteString(origin.scheme());
pickle.WriteString(origin.host());
pickle.WriteUInt16(origin.port());
mojo::Array<uint8_t> origin_array(pickle.size());
memcpy(&(origin_array.front()), pickle.data(), pickle.size());
return origin_array.Pass();
}
url::Origin FrameOriginFromClientProperty(const mojo::Array<uint8_t>& data) {
if (data.is_null())
return url::Origin();
CHECK(data.size());
CHECK(data.size() < static_cast<size_t>(std::numeric_limits<int>::max()));
COMPILE_ASSERT(sizeof(uint8_t) == sizeof(unsigned char),
uint8_t_same_size_as_unsigned_char);
const base::Pickle pickle(reinterpret_cast<const char*>(&(data.front())),
static_cast<int>(data.size()));
CHECK(pickle.data());
base::PickleIterator iter(pickle);
bool unique = false;
std::string scheme;
std::string host;
uint16_t port = 0;
CHECK(iter.ReadBool(&unique));
CHECK(iter.ReadString(&scheme));
CHECK(iter.ReadString(&host));
CHECK(iter.ReadUInt16(&port));
const url::Origin result =
unique ? url::Origin()
: url::Origin::UnsafelyCreateOriginWithoutNormalization(
scheme, host, port);
// If a unique origin was created, but the unique flag wasn't set, then
// the values provided to 'UnsafelyCreateOriginWithoutNormalization' were
// invalid; kill the renderer.
CHECK(!(!unique && result.unique()));
return result;
}
void AddToClientPropertiesIfValid(
const std::string& name,
mojo::Array<uint8_t> value,
mojo::Map<mojo::String, mojo::Array<uint8_t>>* client_properties) {
if (!value.is_null())
(*client_properties)[name] = value.Pass();
}
mojo::Array<uint8_t> GetValueFromClientProperties(
const std::string& name,
const mojo::Map<mojo::String, mojo::Array<uint8_t>>& properties) {
auto iter = properties.find(name);
return iter == properties.end() ? mojo::Array<uint8_t>()
: iter.GetValue().Clone().Pass();
}
} // namespace html_viewer