refactor: rename the atom directory to shell

This commit is contained in:
Samuel Attard 2019-06-19 13:43:10 -07:00 committed by Samuel Attard
parent 4575a4aae3
commit d7f07e8a80
631 changed files with 0 additions and 0 deletions

View file

@ -0,0 +1,23 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/accelerator_converter.h"
#include <string>
#include "atom/browser/ui/accelerator_util.h"
namespace mate {
// static
bool Converter<ui::Accelerator>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
ui::Accelerator* out) {
std::string keycode;
if (!ConvertFromV8(isolate, val, &keycode))
return false;
return accelerator_util::StringToAccelerator(keycode, out);
}
} // namespace mate

View file

@ -0,0 +1,25 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_
#include "native_mate/converter.h"
namespace ui {
class Accelerator;
}
namespace mate {
template <>
struct Converter<ui::Accelerator> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
ui::Accelerator* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_ACCELERATOR_CONVERTER_H_

View file

@ -0,0 +1,530 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/blink_converter.h"
#include <algorithm>
#include <string>
#include <vector>
#include "atom/common/keyboard_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "gin/converter.h"
#include "native_mate/dictionary.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_mouse_event.h"
#include "third_party/blink/public/platform/web_mouse_wheel_event.h"
#include "third_party/blink/public/web/web_device_emulation_params.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
namespace {
template <typename T>
int VectorToBitArray(const std::vector<T>& vec) {
int bits = 0;
for (const T& item : vec)
bits |= item;
return bits;
}
} // namespace
namespace mate {
template <>
struct Converter<base::char16> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
base::char16* out) {
base::string16 code = base::UTF8ToUTF16(gin::V8ToString(isolate, val));
if (code.length() != 1)
return false;
*out = code[0];
return true;
}
};
template <>
struct Converter<blink::WebInputEvent::Type> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
blink::WebInputEvent::Type* out) {
std::string type = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (type == "mousedown")
*out = blink::WebInputEvent::kMouseDown;
else if (type == "mouseup")
*out = blink::WebInputEvent::kMouseUp;
else if (type == "mousemove")
*out = blink::WebInputEvent::kMouseMove;
else if (type == "mouseenter")
*out = blink::WebInputEvent::kMouseEnter;
else if (type == "mouseleave")
*out = blink::WebInputEvent::kMouseLeave;
else if (type == "contextmenu")
*out = blink::WebInputEvent::kContextMenu;
else if (type == "mousewheel")
*out = blink::WebInputEvent::kMouseWheel;
else if (type == "keydown")
*out = blink::WebInputEvent::kRawKeyDown;
else if (type == "keyup")
*out = blink::WebInputEvent::kKeyUp;
else if (type == "char")
*out = blink::WebInputEvent::kChar;
else if (type == "touchstart")
*out = blink::WebInputEvent::kTouchStart;
else if (type == "touchmove")
*out = blink::WebInputEvent::kTouchMove;
else if (type == "touchend")
*out = blink::WebInputEvent::kTouchEnd;
else if (type == "touchcancel")
*out = blink::WebInputEvent::kTouchCancel;
return true;
}
};
template <>
struct Converter<blink::WebMouseEvent::Button> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
blink::WebMouseEvent::Button* out) {
std::string button = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (button == "left")
*out = blink::WebMouseEvent::Button::kLeft;
else if (button == "middle")
*out = blink::WebMouseEvent::Button::kMiddle;
else if (button == "right")
*out = blink::WebMouseEvent::Button::kRight;
else
return false;
return true;
}
};
template <>
struct Converter<blink::WebInputEvent::Modifiers> {
static bool FromV8(v8::Isolate* isolate,
v8::Handle<v8::Value> val,
blink::WebInputEvent::Modifiers* out) {
std::string modifier = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (modifier == "shift")
*out = blink::WebInputEvent::kShiftKey;
else if (modifier == "control" || modifier == "ctrl")
*out = blink::WebInputEvent::kControlKey;
else if (modifier == "alt")
*out = blink::WebInputEvent::kAltKey;
else if (modifier == "meta" || modifier == "command" || modifier == "cmd")
*out = blink::WebInputEvent::kMetaKey;
else if (modifier == "iskeypad")
*out = blink::WebInputEvent::kIsKeyPad;
else if (modifier == "isautorepeat")
*out = blink::WebInputEvent::kIsAutoRepeat;
else if (modifier == "leftbuttondown")
*out = blink::WebInputEvent::kLeftButtonDown;
else if (modifier == "middlebuttondown")
*out = blink::WebInputEvent::kMiddleButtonDown;
else if (modifier == "rightbuttondown")
*out = blink::WebInputEvent::kRightButtonDown;
else if (modifier == "capslock")
*out = blink::WebInputEvent::kCapsLockOn;
else if (modifier == "numlock")
*out = blink::WebInputEvent::kNumLockOn;
else if (modifier == "left")
*out = blink::WebInputEvent::kIsLeft;
else if (modifier == "right")
*out = blink::WebInputEvent::kIsRight;
return true;
}
};
blink::WebInputEvent::Type GetWebInputEventType(v8::Isolate* isolate,
v8::Local<v8::Value> val) {
blink::WebInputEvent::Type type = blink::WebInputEvent::kUndefined;
mate::Dictionary dict;
ConvertFromV8(isolate, val, &dict) && dict.Get("type", &type);
return type;
}
bool Converter<blink::WebInputEvent>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebInputEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
blink::WebInputEvent::Type type;
if (!dict.Get("type", &type))
return false;
out->SetType(type);
std::vector<blink::WebInputEvent::Modifiers> modifiers;
if (dict.Get("modifiers", &modifiers))
out->SetModifiers(VectorToBitArray(modifiers));
out->SetTimeStamp(base::TimeTicks::Now());
return true;
}
bool Converter<blink::WebKeyboardEvent>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebKeyboardEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
return false;
std::string str;
if (!dict.Get("keyCode", &str))
return false;
bool shifted = false;
ui::KeyboardCode keyCode = atom::KeyboardCodeFromStr(str, &shifted);
out->windows_key_code = keyCode;
if (shifted)
out->SetModifiers(out->GetModifiers() | blink::WebInputEvent::kShiftKey);
ui::DomCode domCode = ui::UsLayoutKeyboardCodeToDomCode(keyCode);
out->dom_code = static_cast<int>(domCode);
ui::DomKey domKey;
ui::KeyboardCode dummy_code;
int flags = atom::WebEventModifiersToEventFlags(out->GetModifiers());
if (ui::DomCodeToUsLayoutDomKey(domCode, flags, &domKey, &dummy_code))
out->dom_key = static_cast<int>(domKey);
if ((out->GetType() == blink::WebInputEvent::kChar ||
out->GetType() == blink::WebInputEvent::kRawKeyDown)) {
// Make sure to not read beyond the buffer in case some bad code doesn't
// NULL-terminate it (this is called from plugins).
size_t text_length_cap = blink::WebKeyboardEvent::kTextLengthCap;
base::string16 text16 = base::UTF8ToUTF16(str);
memset(out->text, 0, text_length_cap);
memset(out->unmodified_text, 0, text_length_cap);
for (size_t i = 0; i < std::min(text_length_cap, text16.size()); ++i) {
out->text[i] = text16[i];
out->unmodified_text[i] = text16[i];
}
}
return true;
}
bool Converter<content::NativeWebKeyboardEvent>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::NativeWebKeyboardEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebKeyboardEvent*>(out)))
return false;
dict.Get("skipInBrowser", &out->skip_in_browser);
return true;
}
v8::Local<v8::Value> Converter<content::NativeWebKeyboardEvent>::ToV8(
v8::Isolate* isolate,
const content::NativeWebKeyboardEvent& in) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
if (in.GetType() == blink::WebInputEvent::Type::kRawKeyDown)
dict.Set("type", "keyDown");
else if (in.GetType() == blink::WebInputEvent::Type::kKeyUp)
dict.Set("type", "keyUp");
dict.Set("key", ui::KeycodeConverter::DomKeyToKeyString(in.dom_key));
dict.Set("code", ui::KeycodeConverter::DomCodeToCodeString(
static_cast<ui::DomCode>(in.dom_code)));
using Modifiers = blink::WebInputEvent::Modifiers;
dict.Set("isAutoRepeat", (in.GetModifiers() & Modifiers::kIsAutoRepeat) != 0);
dict.Set("shift", (in.GetModifiers() & Modifiers::kShiftKey) != 0);
dict.Set("control", (in.GetModifiers() & Modifiers::kControlKey) != 0);
dict.Set("alt", (in.GetModifiers() & Modifiers::kAltKey) != 0);
dict.Set("meta", (in.GetModifiers() & Modifiers::kMetaKey) != 0);
return dict.GetHandle();
}
bool Converter<blink::WebMouseEvent>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebMouseEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
return false;
float x = 0.f;
float y = 0.f;
if (!dict.Get("x", &x) || !dict.Get("y", &y))
return false;
out->SetPositionInWidget(x, y);
if (!dict.Get("button", &out->button))
out->button = blink::WebMouseEvent::Button::kLeft;
float global_x = 0.f;
float global_y = 0.f;
dict.Get("globalX", &global_x);
dict.Get("globalY", &global_y);
out->SetPositionInScreen(global_x, global_y);
dict.Get("movementX", &out->movement_x);
dict.Get("movementY", &out->movement_y);
dict.Get("clickCount", &out->click_count);
return true;
}
bool Converter<blink::WebMouseWheelEvent>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebMouseWheelEvent* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!ConvertFromV8(isolate, val, static_cast<blink::WebMouseEvent*>(out)))
return false;
dict.Get("deltaX", &out->delta_x);
dict.Get("deltaY", &out->delta_y);
dict.Get("wheelTicksX", &out->wheel_ticks_x);
dict.Get("wheelTicksY", &out->wheel_ticks_y);
dict.Get("accelerationRatioX", &out->acceleration_ratio_x);
dict.Get("accelerationRatioY", &out->acceleration_ratio_y);
dict.Get("hasPreciseScrollingDeltas", &out->has_precise_scrolling_deltas);
#if defined(USE_AURA)
// Matches the behavior of ui/events/blink/web_input_event_traits.cc:
bool can_scroll = true;
if (dict.Get("canScroll", &can_scroll) && !can_scroll) {
out->has_precise_scrolling_deltas = false;
out->SetModifiers(out->GetModifiers() & ~blink::WebInputEvent::kControlKey);
}
#endif
return true;
}
bool Converter<blink::WebFloatPoint>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebFloatPoint* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
return dict.Get("x", &out->x) && dict.Get("y", &out->y);
}
template <>
struct Converter<base::Optional<blink::WebPoint>> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::Optional<blink::WebPoint>* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
blink::WebPoint point;
bool success = dict.Get("x", &point.x) && dict.Get("y", &point.y);
if (!success)
return false;
out->emplace(point);
return true;
}
};
bool Converter<blink::WebSize>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebSize* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
return dict.Get("width", &out->width) && dict.Get("height", &out->height);
}
bool Converter<blink::WebDeviceEmulationParams>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebDeviceEmulationParams* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
std::string screen_position;
if (dict.Get("screenPosition", &screen_position)) {
screen_position = base::ToLowerASCII(screen_position);
if (screen_position == "mobile")
out->screen_position = blink::WebDeviceEmulationParams::kMobile;
else if (screen_position == "desktop")
out->screen_position = blink::WebDeviceEmulationParams::kDesktop;
else
return false;
}
dict.Get("screenSize", &out->screen_size);
dict.Get("viewPosition", &out->view_position);
dict.Get("deviceScaleFactor", &out->device_scale_factor);
dict.Get("viewSize", &out->view_size);
dict.Get("scale", &out->scale);
return true;
}
// static
v8::Local<v8::Value> Converter<blink::WebContextMenuData::MediaType>::ToV8(
v8::Isolate* isolate,
const blink::WebContextMenuData::MediaType& in) {
switch (in) {
case blink::WebContextMenuData::kMediaTypeImage:
return mate::StringToV8(isolate, "image");
case blink::WebContextMenuData::kMediaTypeVideo:
return mate::StringToV8(isolate, "video");
case blink::WebContextMenuData::kMediaTypeAudio:
return mate::StringToV8(isolate, "audio");
case blink::WebContextMenuData::kMediaTypeCanvas:
return mate::StringToV8(isolate, "canvas");
case blink::WebContextMenuData::kMediaTypeFile:
return mate::StringToV8(isolate, "file");
case blink::WebContextMenuData::kMediaTypePlugin:
return mate::StringToV8(isolate, "plugin");
default:
return mate::StringToV8(isolate, "none");
}
}
// static
v8::Local<v8::Value> Converter<blink::WebContextMenuData::InputFieldType>::ToV8(
v8::Isolate* isolate,
const blink::WebContextMenuData::InputFieldType& in) {
switch (in) {
case blink::WebContextMenuData::kInputFieldTypePlainText:
return mate::StringToV8(isolate, "plainText");
case blink::WebContextMenuData::kInputFieldTypePassword:
return mate::StringToV8(isolate, "password");
case blink::WebContextMenuData::kInputFieldTypeOther:
return mate::StringToV8(isolate, "other");
default:
return mate::StringToV8(isolate, "none");
}
}
v8::Local<v8::Value> EditFlagsToV8(v8::Isolate* isolate, int editFlags) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("canUndo", !!(editFlags & blink::WebContextMenuData::kCanUndo));
dict.Set("canRedo", !!(editFlags & blink::WebContextMenuData::kCanRedo));
dict.Set("canCut", !!(editFlags & blink::WebContextMenuData::kCanCut));
dict.Set("canCopy", !!(editFlags & blink::WebContextMenuData::kCanCopy));
bool pasteFlag = false;
if (editFlags & blink::WebContextMenuData::kCanPaste) {
std::vector<base::string16> types;
bool ignore;
ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes(
ui::CLIPBOARD_TYPE_COPY_PASTE, &types, &ignore);
pasteFlag = !types.empty();
}
dict.Set("canPaste", pasteFlag);
dict.Set("canDelete", !!(editFlags & blink::WebContextMenuData::kCanDelete));
dict.Set("canSelectAll",
!!(editFlags & blink::WebContextMenuData::kCanSelectAll));
return mate::ConvertToV8(isolate, dict);
}
v8::Local<v8::Value> MediaFlagsToV8(v8::Isolate* isolate, int mediaFlags) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("inError",
!!(mediaFlags & blink::WebContextMenuData::kMediaInError));
dict.Set("isPaused",
!!(mediaFlags & blink::WebContextMenuData::kMediaPaused));
dict.Set("isMuted", !!(mediaFlags & blink::WebContextMenuData::kMediaMuted));
dict.Set("hasAudio",
!!(mediaFlags & blink::WebContextMenuData::kMediaHasAudio));
dict.Set("isLooping",
(mediaFlags & blink::WebContextMenuData::kMediaLoop) != 0);
dict.Set("isControlsVisible",
(mediaFlags & blink::WebContextMenuData::kMediaControls) != 0);
dict.Set("canToggleControls",
!!(mediaFlags & blink::WebContextMenuData::kMediaCanToggleControls));
dict.Set("canRotate",
!!(mediaFlags & blink::WebContextMenuData::kMediaCanRotate));
return mate::ConvertToV8(isolate, dict);
}
v8::Local<v8::Value> Converter<blink::WebCache::ResourceTypeStat>::ToV8(
v8::Isolate* isolate,
const blink::WebCache::ResourceTypeStat& stat) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("count", static_cast<uint32_t>(stat.count));
dict.Set("size", static_cast<double>(stat.size));
dict.Set("liveSize", static_cast<double>(stat.decoded_size));
return dict.GetHandle();
}
v8::Local<v8::Value> Converter<blink::WebCache::ResourceTypeStats>::ToV8(
v8::Isolate* isolate,
const blink::WebCache::ResourceTypeStats& stats) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("images", stats.images);
dict.Set("scripts", stats.scripts);
dict.Set("cssStyleSheets", stats.css_style_sheets);
dict.Set("xslStyleSheets", stats.xsl_style_sheets);
dict.Set("fonts", stats.fonts);
dict.Set("other", stats.other);
return dict.GetHandle();
}
// static
v8::Local<v8::Value> Converter<network::mojom::ReferrerPolicy>::ToV8(
v8::Isolate* isolate,
const network::mojom::ReferrerPolicy& in) {
switch (in) {
case network::mojom::ReferrerPolicy::kDefault:
return mate::StringToV8(isolate, "default");
case network::mojom::ReferrerPolicy::kAlways:
return mate::StringToV8(isolate, "unsafe-url");
case network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
return mate::StringToV8(isolate, "no-referrer-when-downgrade");
case network::mojom::ReferrerPolicy::kNever:
return mate::StringToV8(isolate, "no-referrer");
case network::mojom::ReferrerPolicy::kOrigin:
return mate::StringToV8(isolate, "origin");
case network::mojom::ReferrerPolicy::
kNoReferrerWhenDowngradeOriginWhenCrossOrigin:
return mate::StringToV8(isolate, "strict-origin-when-cross-origin");
case network::mojom::ReferrerPolicy::kSameOrigin:
return mate::StringToV8(isolate, "same-origin");
case network::mojom::ReferrerPolicy::kStrictOrigin:
return mate::StringToV8(isolate, "strict-origin");
default:
return mate::StringToV8(isolate, "no-referrer");
}
}
// static
bool Converter<network::mojom::ReferrerPolicy>::FromV8(
v8::Isolate* isolate,
v8::Handle<v8::Value> val,
network::mojom::ReferrerPolicy* out) {
std::string policy = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (policy == "default")
*out = network::mojom::ReferrerPolicy::kDefault;
else if (policy == "unsafe-url")
*out = network::mojom::ReferrerPolicy::kAlways;
else if (policy == "no-referrer-when-downgrade")
*out = network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade;
else if (policy == "no-referrer")
*out = network::mojom::ReferrerPolicy::kNever;
else if (policy == "origin")
*out = network::mojom::ReferrerPolicy::kOrigin;
else if (policy == "strict-origin-when-cross-origin")
*out = network::mojom::ReferrerPolicy::
kNoReferrerWhenDowngradeOriginWhenCrossOrigin;
else if (policy == "same-origin")
*out = network::mojom::ReferrerPolicy::kSameOrigin;
else if (policy == "strict-origin")
*out = network::mojom::ReferrerPolicy::kStrictOrigin;
else
return false;
return true;
}
} // namespace mate

View file

@ -0,0 +1,139 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_
#include "native_mate/converter.h"
#include "third_party/blink/public/platform/web_cache.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/web/web_context_menu_data.h"
namespace blink {
class WebMouseEvent;
class WebMouseWheelEvent;
class WebKeyboardEvent;
struct WebDeviceEmulationParams;
struct WebFloatPoint;
struct WebPoint;
struct WebSize;
} // namespace blink
namespace content {
struct NativeWebKeyboardEvent;
}
namespace mate {
blink::WebInputEvent::Type GetWebInputEventType(v8::Isolate* isolate,
v8::Local<v8::Value> val);
template <>
struct Converter<blink::WebInputEvent> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebInputEvent* out);
};
template <>
struct Converter<blink::WebKeyboardEvent> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebKeyboardEvent* out);
};
template <>
struct Converter<content::NativeWebKeyboardEvent> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::NativeWebKeyboardEvent* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const content::NativeWebKeyboardEvent& in);
};
template <>
struct Converter<blink::WebMouseEvent> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebMouseEvent* out);
};
template <>
struct Converter<blink::WebMouseWheelEvent> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebMouseWheelEvent* out);
};
template <>
struct Converter<blink::WebFloatPoint> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebFloatPoint* out);
};
template <>
struct Converter<blink::WebPoint> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebPoint* out);
};
template <>
struct Converter<blink::WebSize> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebSize* out);
};
template <>
struct Converter<blink::WebDeviceEmulationParams> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::WebDeviceEmulationParams* out);
};
template <>
struct Converter<blink::WebContextMenuData::MediaType> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const blink::WebContextMenuData::MediaType& in);
};
template <>
struct Converter<blink::WebContextMenuData::InputFieldType> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const blink::WebContextMenuData::InputFieldType& in);
};
template <>
struct Converter<blink::WebCache::ResourceTypeStat> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const blink::WebCache::ResourceTypeStat& stat);
};
template <>
struct Converter<blink::WebCache::ResourceTypeStats> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const blink::WebCache::ResourceTypeStats& stats);
};
template <>
struct Converter<network::mojom::ReferrerPolicy> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const network::mojom::ReferrerPolicy& in);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
network::mojom::ReferrerPolicy* out);
};
v8::Local<v8::Value> EditFlagsToV8(v8::Isolate* isolate, int editFlags);
v8::Local<v8::Value> MediaFlagsToV8(v8::Isolate* isolate, int mediaFlags);
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_BLINK_CONVERTER_H_

View file

@ -0,0 +1,163 @@
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/callback.h"
#include "base/stl_util.h"
#include "content/public/browser/browser_thread.h"
#include "native_mate/dictionary.h"
using content::BrowserThread;
namespace mate {
namespace internal {
namespace {
struct TranslaterHolder {
explicit TranslaterHolder(v8::Isolate* isolate)
: handle(isolate, v8::External::New(isolate, this)) {
handle.SetWeak(this, &GC, v8::WeakCallbackType::kFinalizer);
}
~TranslaterHolder() {
if (!handle.IsEmpty()) {
handle.ClearWeak();
handle.Reset();
}
}
static void GC(const v8::WeakCallbackInfo<TranslaterHolder>& data) {
delete data.GetParameter();
}
v8::Global<v8::External> handle;
Translater translater;
};
// Cached JavaScript version of |CallTranslater|.
v8::Persistent<v8::FunctionTemplate> g_call_translater;
void CallTranslater(v8::Local<v8::External> external,
v8::Local<v8::Object> state,
mate::Arguments* args) {
// Whether the callback should only be called for once.
v8::Isolate* isolate = args->isolate();
auto context = isolate->GetCurrentContext();
bool one_time =
state->Has(context, mate::StringToSymbol(isolate, "oneTime")).ToChecked();
// Check if the callback has already been called.
if (one_time) {
auto called_symbol = mate::StringToSymbol(isolate, "called");
if (state->Has(context, called_symbol).ToChecked()) {
args->ThrowError("callback can only be called for once");
return;
} else {
state->Set(context, called_symbol, v8::Boolean::New(isolate, true))
.ToChecked();
}
}
TranslaterHolder* holder = static_cast<TranslaterHolder*>(external->Value());
holder->translater.Run(args);
// Free immediately for one-time callback.
if (one_time)
delete holder;
}
} // namespace
// Destroy the class on UI thread when possible.
struct DeleteOnUIThread {
template <typename T>
static void Destruct(const T* x) {
if (Locker::IsBrowserProcess() &&
!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x);
} else {
delete x;
}
}
};
// Like v8::Global, but ref-counted.
template <typename T>
class RefCountedGlobal
: public base::RefCountedThreadSafe<RefCountedGlobal<T>, DeleteOnUIThread> {
public:
RefCountedGlobal(v8::Isolate* isolate, v8::Local<v8::Value> value)
: handle_(isolate, v8::Local<T>::Cast(value)) {}
bool IsAlive() const { return !handle_.IsEmpty(); }
v8::Local<T> NewHandle(v8::Isolate* isolate) const {
return v8::Local<T>::New(isolate, handle_);
}
private:
v8::Global<T> handle_;
DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal);
};
SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value)
: v8_function_(new RefCountedGlobal<v8::Function>(isolate, value)) {}
SafeV8Function::SafeV8Function(const SafeV8Function& other)
: v8_function_(other.v8_function_) {}
SafeV8Function::~SafeV8Function() {}
bool SafeV8Function::IsAlive() const {
return v8_function_.get() && v8_function_->IsAlive();
}
v8::Local<v8::Function> SafeV8Function::NewHandle(v8::Isolate* isolate) const {
return v8_function_->NewHandle(isolate);
}
v8::Local<v8::Value> CreateFunctionFromTranslater(v8::Isolate* isolate,
const Translater& translater,
bool one_time) {
// The FunctionTemplate is cached.
if (g_call_translater.IsEmpty())
g_call_translater.Reset(isolate,
mate::CreateFunctionTemplate(
isolate, base::BindRepeating(&CallTranslater)));
v8::Local<v8::FunctionTemplate> call_translater =
v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
auto* holder = new TranslaterHolder(isolate);
holder->translater = translater;
Dictionary state = mate::Dictionary::CreateEmpty(isolate);
if (one_time)
state.Set("oneTime", true);
auto context = isolate->GetCurrentContext();
return BindFunctionWith(
isolate, context, call_translater->GetFunction(context).ToLocalChecked(),
holder->handle.Get(isolate), state.GetHandle());
}
// func.bind(func, arg1).
// NB(zcbenz): Using C++11 version crashes VS.
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
v8::Local<v8::Context> context,
v8::Local<v8::Function> func,
v8::Local<v8::Value> arg1,
v8::Local<v8::Value> arg2) {
v8::MaybeLocal<v8::Value> bind =
func->Get(context, mate::StringToV8(isolate, "bind"));
CHECK(!bind.IsEmpty());
v8::Local<v8::Function> bind_func =
v8::Local<v8::Function>::Cast(bind.ToLocalChecked());
v8::Local<v8::Value> converted[] = {func, arg1, arg2};
return bind_func->Call(context, func, base::size(converted), converted)
.ToLocalChecked();
}
} // namespace internal
} // namespace mate

View file

@ -0,0 +1,181 @@
// Copyright (c) 2015 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_
#include <utility>
#include <vector>
#include "atom/common/api/locker.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "native_mate/function_template.h"
#include "native_mate/scoped_persistent.h"
namespace mate {
namespace internal {
template <typename T>
class RefCountedGlobal;
// Manages the V8 function with RAII.
class SafeV8Function {
public:
SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value);
SafeV8Function(const SafeV8Function& other);
~SafeV8Function();
bool IsAlive() const;
v8::Local<v8::Function> NewHandle(v8::Isolate* isolate) const;
private:
scoped_refptr<RefCountedGlobal<v8::Function>> v8_function_;
};
// Helper to invoke a V8 function with C++ parameters.
template <typename Sig>
struct V8FunctionInvoker {};
template <typename... ArgTypes>
struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
static v8::Local<v8::Value> Go(v8::Isolate* isolate,
const SafeV8Function& function,
ArgTypes... raw) {
Locker locker(isolate);
v8::EscapableHandleScope handle_scope(isolate);
if (!function.IsAlive())
return v8::Null(isolate);
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args{
ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
v8::MaybeLocal<v8::Value> ret = holder->Call(
context, holder, args.size(), args.empty() ? nullptr : &args.front());
if (ret.IsEmpty())
return v8::Undefined(isolate);
else
return handle_scope.Escape(ret.ToLocalChecked());
}
};
template <typename... ArgTypes>
struct V8FunctionInvoker<void(ArgTypes...)> {
static void Go(v8::Isolate* isolate,
const SafeV8Function& function,
ArgTypes... raw) {
Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!function.IsAlive())
return;
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args{
ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
holder
->Call(context, holder, args.size(),
args.empty() ? nullptr : &args.front())
.IsEmpty();
}
};
template <typename ReturnType, typename... ArgTypes>
struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
static ReturnType Go(v8::Isolate* isolate,
const SafeV8Function& function,
ArgTypes... raw) {
Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
ReturnType ret = ReturnType();
if (!function.IsAlive())
return ret;
v8::MicrotasksScope script_scope(isolate,
v8::MicrotasksScope::kRunMicrotasks);
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args{
ConvertToV8(isolate, std::forward<ArgTypes>(raw))...};
v8::Local<v8::Value> result;
auto maybe_result = holder->Call(context, holder, args.size(),
args.empty() ? nullptr : &args.front());
if (maybe_result.ToLocal(&result))
Converter<ReturnType>::FromV8(isolate, result, &ret);
return ret;
}
};
// Helper to pass a C++ funtion to JavaScript.
using Translater = base::Callback<void(Arguments* args)>;
v8::Local<v8::Value> CreateFunctionFromTranslater(v8::Isolate* isolate,
const Translater& translater,
bool one_time);
v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
v8::Local<v8::Context> context,
v8::Local<v8::Function> func,
v8::Local<v8::Value> arg1,
v8::Local<v8::Value> arg2);
// Calls callback with Arguments.
template <typename Sig>
struct NativeFunctionInvoker {};
template <typename ReturnType, typename... ArgTypes>
struct NativeFunctionInvoker<ReturnType(ArgTypes...)> {
static void Go(base::Callback<ReturnType(ArgTypes...)> val, Arguments* args) {
using Indices = typename IndicesGenerator<sizeof...(ArgTypes)>::type;
Invoker<Indices, ArgTypes...> invoker(args, 0);
if (invoker.IsOK())
invoker.DispatchToCallback(val);
}
};
} // namespace internal
template <typename Sig>
struct Converter<base::RepeatingCallback<Sig>> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::RepeatingCallback<Sig>& val) {
// We don't use CreateFunctionTemplate here because it creates a new
// FunctionTemplate everytime, which is cached by V8 and causes leaks.
internal::Translater translater =
base::Bind(&internal::NativeFunctionInvoker<Sig>::Go, val);
// To avoid memory leak, we ensure that the callback can only be called
// for once.
return internal::CreateFunctionFromTranslater(isolate, translater, true);
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::RepeatingCallback<Sig>* out) {
if (!val->IsFunction())
return false;
*out = base::BindRepeating(&internal::V8FunctionInvoker<Sig>::Go, isolate,
internal::SafeV8Function(isolate, val));
return true;
}
};
// Convert a callback to V8 without the call number limitation, this can easily
// cause memory leaks so use it with caution.
template <typename Sig>
v8::Local<v8::Value> CallbackToV8(v8::Isolate* isolate,
const base::Callback<Sig>& val) {
internal::Translater translater =
base::Bind(&internal::NativeFunctionInvoker<Sig>::Go, val);
return internal::CreateFunctionFromTranslater(isolate, translater, false);
}
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CALLBACK_H_

View file

@ -0,0 +1,251 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/content_converter.h"
#include <string>
#include <vector>
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/web_contents_permission_helper.h"
#include "atom/common/native_mate_converters/blink_converter.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/ui_base_types_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/context_menu_params.h"
#include "native_mate/dictionary.h"
namespace {
void ExecuteCommand(content::WebContents* web_contents,
int action,
const content::CustomContextMenuContext& context) {
web_contents->ExecuteCustomContextMenuCommand(action, context);
}
// Forward declaration for nested recursive call.
v8::Local<v8::Value> MenuToV8(v8::Isolate* isolate,
content::WebContents* web_contents,
const content::CustomContextMenuContext& context,
const std::vector<content::MenuItem>& menu);
v8::Local<v8::Value> MenuItemToV8(
v8::Isolate* isolate,
content::WebContents* web_contents,
const content::CustomContextMenuContext& context,
const content::MenuItem& item) {
mate::Dictionary v8_item = mate::Dictionary::CreateEmpty(isolate);
switch (item.type) {
case content::MenuItem::CHECKABLE_OPTION:
case content::MenuItem::GROUP:
v8_item.Set("checked", item.checked);
FALLTHROUGH;
case content::MenuItem::OPTION:
case content::MenuItem::SUBMENU:
v8_item.Set("label", item.label);
v8_item.Set("enabled", item.enabled);
FALLTHROUGH;
default:
v8_item.Set("type", item.type);
}
if (item.type == content::MenuItem::SUBMENU)
v8_item.Set("submenu",
MenuToV8(isolate, web_contents, context, item.submenu));
else if (item.action > 0)
v8_item.Set("click", base::BindRepeating(ExecuteCommand, web_contents,
item.action, context));
return v8_item.GetHandle();
}
v8::Local<v8::Value> MenuToV8(v8::Isolate* isolate,
content::WebContents* web_contents,
const content::CustomContextMenuContext& context,
const std::vector<content::MenuItem>& menu) {
std::vector<v8::Local<v8::Value>> v8_menu;
for (const auto& menu_item : menu)
v8_menu.push_back(MenuItemToV8(isolate, web_contents, context, menu_item));
return mate::ConvertToV8(isolate, v8_menu);
}
} // namespace
namespace mate {
// static
v8::Local<v8::Value> Converter<content::MenuItem::Type>::ToV8(
v8::Isolate* isolate,
const content::MenuItem::Type& val) {
switch (val) {
case content::MenuItem::CHECKABLE_OPTION:
return StringToV8(isolate, "checkbox");
case content::MenuItem::GROUP:
return StringToV8(isolate, "radio");
case content::MenuItem::SEPARATOR:
return StringToV8(isolate, "separator");
case content::MenuItem::SUBMENU:
return StringToV8(isolate, "submenu");
case content::MenuItem::OPTION:
default:
return StringToV8(isolate, "normal");
}
}
// static
v8::Local<v8::Value> Converter<ContextMenuParamsWithWebContents>::ToV8(
v8::Isolate* isolate,
const ContextMenuParamsWithWebContents& val) {
const auto& params = val.first;
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("x", params.x);
dict.Set("y", params.y);
dict.Set("linkURL", params.link_url);
dict.Set("linkText", params.link_text);
dict.Set("pageURL", params.page_url);
dict.Set("frameURL", params.frame_url);
dict.Set("srcURL", params.src_url);
dict.Set("mediaType", params.media_type);
dict.Set("mediaFlags", MediaFlagsToV8(isolate, params.media_flags));
bool has_image_contents =
(params.media_type == blink::WebContextMenuData::kMediaTypeImage) &&
params.has_image_contents;
dict.Set("hasImageContents", has_image_contents);
dict.Set("isEditable", params.is_editable);
dict.Set("editFlags", EditFlagsToV8(isolate, params.edit_flags));
dict.Set("selectionText", params.selection_text);
dict.Set("titleText", params.title_text);
dict.Set("misspelledWord", params.misspelled_word);
dict.Set("frameCharset", params.frame_charset);
dict.Set("inputFieldType", params.input_field_type);
dict.Set("menuSourceType", params.source_type);
if (params.custom_context.is_pepper_menu)
dict.Set("menu", MenuToV8(isolate, val.second, params.custom_context,
params.custom_items));
return mate::ConvertToV8(isolate, dict);
}
// static
bool Converter<blink::mojom::PermissionStatus>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::mojom::PermissionStatus* out) {
bool result;
if (!ConvertFromV8(isolate, val, &result))
return false;
if (result)
*out = blink::mojom::PermissionStatus::GRANTED;
else
*out = blink::mojom::PermissionStatus::DENIED;
return true;
}
// static
v8::Local<v8::Value> Converter<content::PermissionType>::ToV8(
v8::Isolate* isolate,
const content::PermissionType& val) {
using PermissionType = atom::WebContentsPermissionHelper::PermissionType;
switch (val) {
case content::PermissionType::MIDI_SYSEX:
return StringToV8(isolate, "midiSysex");
case content::PermissionType::NOTIFICATIONS:
return StringToV8(isolate, "notifications");
case content::PermissionType::GEOLOCATION:
return StringToV8(isolate, "geolocation");
case content::PermissionType::AUDIO_CAPTURE:
case content::PermissionType::VIDEO_CAPTURE:
return StringToV8(isolate, "media");
case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
return StringToV8(isolate, "mediaKeySystem");
case content::PermissionType::MIDI:
return StringToV8(isolate, "midi");
default:
break;
}
if (val == static_cast<content::PermissionType>(PermissionType::POINTER_LOCK))
return StringToV8(isolate, "pointerLock");
else if (val ==
static_cast<content::PermissionType>(PermissionType::FULLSCREEN))
return StringToV8(isolate, "fullscreen");
else if (val ==
static_cast<content::PermissionType>(PermissionType::OPEN_EXTERNAL))
return StringToV8(isolate, "openExternal");
return StringToV8(isolate, "unknown");
}
// static
bool Converter<content::StopFindAction>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::StopFindAction* out) {
std::string action;
if (!ConvertFromV8(isolate, val, &action))
return false;
if (action == "clearSelection")
*out = content::STOP_FIND_ACTION_CLEAR_SELECTION;
else if (action == "keepSelection")
*out = content::STOP_FIND_ACTION_KEEP_SELECTION;
else if (action == "activateSelection")
*out = content::STOP_FIND_ACTION_ACTIVATE_SELECTION;
else
return false;
return true;
}
// static
v8::Local<v8::Value> Converter<content::WebContents*>::ToV8(
v8::Isolate* isolate,
content::WebContents* val) {
if (!val)
return v8::Null(isolate);
return atom::api::WebContents::FromOrCreate(isolate, val).ToV8();
}
// static
bool Converter<content::WebContents*>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::WebContents** out) {
atom::api::WebContents* web_contents = nullptr;
if (!ConvertFromV8(isolate, val, &web_contents) || !web_contents)
return false;
*out = web_contents->web_contents();
return true;
}
// static
v8::Local<v8::Value> Converter<content::Referrer>::ToV8(
v8::Isolate* isolate,
const content::Referrer& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("url", ConvertToV8(isolate, val.url));
dict.Set("policy", ConvertToV8(isolate, val.policy));
return mate::ConvertToV8(isolate, dict);
}
// static
bool Converter<content::Referrer>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::Referrer* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("url", &out->url))
return false;
if (!dict.Get("policy", &out->policy))
return false;
return true;
}
} // namespace mate

View file

@ -0,0 +1,79 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
#include <utility>
#include "content/public/browser/permission_type.h"
#include "content/public/common/menu_item.h"
#include "content/public/common/referrer.h"
#include "content/public/common/stop_find_action.h"
#include "native_mate/converter.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
namespace content {
struct ContextMenuParams;
class WebContents;
} // namespace content
using ContextMenuParamsWithWebContents =
std::pair<content::ContextMenuParams, content::WebContents*>;
namespace mate {
template <>
struct Converter<content::MenuItem::Type> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const content::MenuItem::Type& val);
};
template <>
struct Converter<ContextMenuParamsWithWebContents> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const ContextMenuParamsWithWebContents& val);
};
template <>
struct Converter<blink::mojom::PermissionStatus> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
blink::mojom::PermissionStatus* out);
};
template <>
struct Converter<content::PermissionType> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const content::PermissionType& val);
};
template <>
struct Converter<content::StopFindAction> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::StopFindAction* out);
};
template <>
struct Converter<content::WebContents*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
content::WebContents* val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::WebContents** out);
};
template <>
struct Converter<content::Referrer> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const content::Referrer& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
content::Referrer* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_

View file

@ -0,0 +1,76 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/file_dialog_converter.h"
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/browser/ui/file_dialog.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "native_mate/dictionary.h"
namespace mate {
bool Converter<file_dialog::Filter>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::Filter* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
if (!dict.Get("name", &(out->first)))
return false;
if (!dict.Get("extensions", &(out->second)))
return false;
return true;
}
v8::Local<v8::Value> Converter<file_dialog::Filter>::ToV8(
v8::Isolate* isolate,
const file_dialog::Filter& in) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("name", in.first);
dict.Set("extensions", in.second);
return dict.GetHandle();
}
bool Converter<file_dialog::DialogSettings>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::DialogSettings* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("window", &(out->parent_window));
dict.Get("title", &(out->title));
dict.Get("message", &(out->message));
dict.Get("buttonLabel", &(out->button_label));
dict.Get("nameFieldLabel", &(out->name_field_label));
dict.Get("defaultPath", &(out->default_path));
dict.Get("filters", &(out->filters));
dict.Get("properties", &(out->properties));
dict.Get("showsTagField", &(out->shows_tag_field));
dict.Get("securityScopedBookmarks", &(out->security_scoped_bookmarks));
return true;
}
v8::Local<v8::Value> Converter<file_dialog::DialogSettings>::ToV8(
v8::Isolate* isolate,
const file_dialog::DialogSettings& in) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("window", atom::api::BrowserWindow::From(isolate, in.parent_window));
dict.Set("title", in.title);
dict.Set("message", in.message);
dict.Set("buttonLabel", in.button_label);
dict.Set("nameFieldLabel", in.name_field_label);
dict.Set("defaultPath", in.default_path);
dict.Set("filters", in.filters);
dict.Set("showsTagField", in.shows_tag_field);
dict.Set("securityScopedBookmarks", in.security_scoped_bookmarks);
return dict.GetHandle();
}
} // namespace mate

View file

@ -0,0 +1,33 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_DIALOG_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_DIALOG_CONVERTER_H_
#include "atom/browser/ui/file_dialog.h"
#include "native_mate/converter.h"
namespace mate {
template <>
struct Converter<file_dialog::Filter> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const file_dialog::Filter& in);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::Filter* out);
};
template <>
struct Converter<file_dialog::DialogSettings> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const file_dialog::DialogSettings& in);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
file_dialog::DialogSettings* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_DIALOG_CONVERTER_H_

View file

@ -0,0 +1,57 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_PATH_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_PATH_CONVERTER_H_
#include <string>
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/files/file_path.h"
namespace gin {
template <>
struct Converter<base::FilePath> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::FilePath& val) {
return Converter<base::FilePath::StringType>::ToV8(isolate, val.value());
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::FilePath* out) {
if (val->IsNull())
return true;
base::FilePath::StringType path;
if (Converter<base::FilePath::StringType>::FromV8(isolate, val, &path)) {
*out = base::FilePath(path);
return true;
} else {
return false;
}
}
};
} // namespace gin
namespace mate {
template <>
struct Converter<base::FilePath> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::FilePath& val) {
return gin::Converter<base::FilePath::StringType>::ToV8(isolate,
val.value());
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::FilePath* out) {
return gin::Converter<base::FilePath>::FromV8(isolate, val, out);
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_FILE_PATH_CONVERTER_H_

View file

@ -0,0 +1,161 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "native_mate/dictionary.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
namespace mate {
v8::Local<v8::Value> Converter<gfx::Point>::ToV8(v8::Isolate* isolate,
const gfx::Point& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("x", val.x());
dict.Set("y", val.y());
return dict.GetHandle();
}
bool Converter<gfx::Point>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Point* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
double x, y;
if (!dict.Get("x", &x) || !dict.Get("y", &y))
return false;
*out = gfx::Point(static_cast<int>(std::round(x)),
static_cast<int>(std::round(y)));
return true;
}
v8::Local<v8::Value> Converter<gfx::PointF>::ToV8(v8::Isolate* isolate,
const gfx::PointF& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("x", val.x());
dict.Set("y", val.y());
return dict.GetHandle();
}
bool Converter<gfx::PointF>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::PointF* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
float x, y;
if (!dict.Get("x", &x) || !dict.Get("y", &y))
return false;
*out = gfx::PointF(x, y);
return true;
}
v8::Local<v8::Value> Converter<gfx::Size>::ToV8(v8::Isolate* isolate,
const gfx::Size& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
bool Converter<gfx::Size>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Size* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int width, height;
if (!dict.Get("width", &width) || !dict.Get("height", &height))
return false;
*out = gfx::Size(width, height);
return true;
}
v8::Local<v8::Value> Converter<gfx::Rect>::ToV8(v8::Isolate* isolate,
const gfx::Rect& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("x", val.x());
dict.Set("y", val.y());
dict.Set("width", val.width());
dict.Set("height", val.height());
return dict.GetHandle();
}
bool Converter<gfx::Rect>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Rect* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
int x, y, width, height;
if (!dict.Get("x", &x) || !dict.Get("y", &y) || !dict.Get("width", &width) ||
!dict.Get("height", &height))
return false;
*out = gfx::Rect(x, y, width, height);
return true;
}
template <>
struct Converter<display::Display::AccelerometerSupport> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const display::Display::AccelerometerSupport& val) {
switch (val) {
case display::Display::AccelerometerSupport::AVAILABLE:
return StringToV8(isolate, "available");
case display::Display::AccelerometerSupport::UNAVAILABLE:
return StringToV8(isolate, "unavailable");
default:
return StringToV8(isolate, "unknown");
}
}
};
template <>
struct Converter<display::Display::TouchSupport> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const display::Display::TouchSupport& val) {
switch (val) {
case display::Display::TouchSupport::AVAILABLE:
return StringToV8(isolate, "available");
case display::Display::TouchSupport::UNAVAILABLE:
return StringToV8(isolate, "unavailable");
default:
return StringToV8(isolate, "unknown");
}
}
};
v8::Local<v8::Value> Converter<display::Display>::ToV8(
v8::Isolate* isolate,
const display::Display& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.SetHidden("simple", true);
dict.Set("id", val.id());
dict.Set("bounds", val.bounds());
dict.Set("workArea", val.work_area());
dict.Set("accelerometerSupport", val.accelerometer_support());
dict.Set("monochrome", val.is_monochrome());
dict.Set("colorDepth", val.color_depth());
dict.Set("colorSpace", val.color_space().ToString());
dict.Set("depthPerComponent", val.depth_per_component());
dict.Set("size", val.size());
dict.Set("workAreaSize", val.work_area_size());
dict.Set("scaleFactor", val.device_scale_factor());
dict.Set("rotation", val.RotationAsDegree());
dict.Set("internal", val.IsInternal());
dict.Set("touchSupport", val.touch_support());
return dict.GetHandle();
}
} // namespace mate

View file

@ -0,0 +1,67 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_
#include "native_mate/converter.h"
#include "ui/gfx/geometry/point_f.h"
namespace display {
class Display;
}
namespace gfx {
class Point;
class Size;
class Rect;
} // namespace gfx
namespace mate {
template <>
struct Converter<gfx::Point> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, const gfx::Point& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Point* out);
};
template <>
struct Converter<gfx::PointF> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::PointF& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::PointF* out);
};
template <>
struct Converter<gfx::Size> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, const gfx::Size& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Size* out);
};
template <>
struct Converter<gfx::Rect> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, const gfx::Rect& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Rect* out);
};
template <>
struct Converter<display::Display> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const display::Display& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
display::Display* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_GFX_CONVERTER_H_

View file

@ -0,0 +1,35 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_GURL_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_GURL_CONVERTER_H_
#include <string>
#include "native_mate/converter.h"
#include "url/gurl.h"
namespace mate {
template <>
struct Converter<GURL> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, const GURL& val) {
return ConvertToV8(isolate, val.spec());
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
GURL* out) {
std::string url;
if (Converter<std::string>::FromV8(isolate, val, &url)) {
*out = GURL(url);
return true;
} else {
return false;
}
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_GURL_CONVERTER_H_

View file

@ -0,0 +1,43 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/api/atom_api_native_image.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "ui/gfx/image/image_skia.h"
namespace mate {
bool Converter<gfx::ImageSkia>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::ImageSkia* out) {
gfx::Image image;
if (!ConvertFromV8(isolate, val, &image))
return false;
*out = image.AsImageSkia();
return true;
}
bool Converter<gfx::Image>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Image* out) {
if (val->IsNull())
return true;
Handle<atom::api::NativeImage> native_image;
if (!ConvertFromV8(isolate, val, &native_image))
return false;
*out = native_image->image();
return true;
}
v8::Local<v8::Value> Converter<gfx::Image>::ToV8(v8::Isolate* isolate,
const gfx::Image& val) {
return ConvertToV8(isolate, atom::api::NativeImage::Create(isolate, val));
}
} // namespace mate

View file

@ -0,0 +1,34 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_IMAGE_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_IMAGE_CONVERTER_H_
#include "native_mate/converter.h"
namespace gfx {
class Image;
class ImageSkia;
} // namespace gfx
namespace mate {
template <>
struct Converter<gfx::ImageSkia> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::ImageSkia* out);
};
template <>
struct Converter<gfx::Image> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Image* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate, const gfx::Image& val);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_IMAGE_CONVERTER_H_

View file

@ -0,0 +1,70 @@
// Copyright (c) 2019 Slack Technologies, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_MAP_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_MAP_CONVERTER_H_
#include <map>
#include <string>
#include <utility>
#include "gin/converter.h"
namespace gin {
template <typename T>
struct Converter<std::map<std::string, T>> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
std::map<std::string, T>* out) {
if (!val->IsObject())
return false;
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Local<v8::Object> dict = val->ToObject(context).ToLocalChecked();
v8::Local<v8::Array> keys =
dict->GetOwnPropertyNames(context).ToLocalChecked();
for (uint32_t i = 0; i < keys->Length(); ++i) {
v8::Local<v8::Value> key = keys->Get(context, i).ToLocalChecked();
T value;
if (Converter<T>::FromV8(
isolate, dict->Get(context, key).ToLocalChecked(), &value))
(*out)[gin::V8ToString(isolate, key)] = std::move(value);
}
return true;
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const std::map<std::string, T>& val) {
v8::Local<v8::Object> result = v8::Object::New(isolate);
auto context = isolate->GetCurrentContext();
for (auto i = val.begin(); i != val.end(); i++) {
result
->Set(context, Converter<T>::ToV8(isolate, i->first),
Converter<T>::ToV8(isolate, i->second))
.Check();
}
return result;
}
};
} // namespace gin
namespace mate {
template <typename T>
struct Converter<std::map<std::string, T>> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
std::map<std::string, T>* out) {
return gin::Converter<std::map<std::string, T>>::FromV8(isolate, val, out);
}
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const std::map<std::string, T>& val) {
return gin::Converter<std::map<std::string, T>>::ToV8(isolate, val);
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_MAP_CONVERTER_H_

View file

@ -0,0 +1,38 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/message_box_converter.h"
#include "atom/browser/api/atom_api_browser_window.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "native_mate/dictionary.h"
namespace mate {
bool Converter<atom::MessageBoxSettings>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::MessageBoxSettings* out) {
mate::Dictionary dict;
int type = 0;
if (!ConvertFromV8(isolate, val, &dict))
return false;
dict.Get("window", &out->parent_window);
dict.Get("type", &type);
out->type = static_cast<atom::MessageBoxType>(type);
dict.Get("buttons", &out->buttons);
dict.Get("defaultId", &out->default_id);
dict.Get("cancelId", &out->cancel_id);
dict.Get("options", &out->options);
dict.Get("title", &out->title);
dict.Get("message", &out->message);
dict.Get("detail", &out->detail);
dict.Get("checkboxLabel", &out->checkbox_label);
dict.Get("checkboxChecked", &out->checkbox_checked);
dict.Get("icon", &out->icon);
return true;
}
} // namespace mate

View file

@ -0,0 +1,22 @@
// Copyright (c) 2019 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_MESSAGE_BOX_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_MESSAGE_BOX_CONVERTER_H_
#include "atom/browser/ui/message_box.h"
#include "native_mate/converter.h"
namespace mate {
template <>
struct Converter<atom::MessageBoxSettings> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
atom::MessageBoxSettings* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_MESSAGE_BOX_CONVERTER_H_

View file

@ -0,0 +1,324 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/net_converter.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
#include "atom/common/node_includes.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "native_mate/dictionary.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_data_stream.h"
#include "net/base/upload_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "net/http/http_response_headers.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request.h"
#include "storage/browser/blob/upload_blob_element_reader.h"
namespace mate {
namespace {
bool CertFromData(const std::string& data,
scoped_refptr<net::X509Certificate>* out) {
auto cert_list = net::X509Certificate::CreateCertificateListFromBytes(
data.c_str(), data.length(),
net::X509Certificate::FORMAT_SINGLE_CERTIFICATE);
if (cert_list.empty())
return false;
auto leaf_cert = cert_list.front();
if (!leaf_cert)
return false;
*out = leaf_cert;
return true;
}
} // namespace
// static
v8::Local<v8::Value> Converter<net::AuthChallengeInfo>::ToV8(
v8::Isolate* isolate,
const net::AuthChallengeInfo& val) {
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
dict.Set("isProxy", val.is_proxy);
dict.Set("scheme", val.scheme);
dict.Set("host", val.challenger.host());
dict.Set("port", static_cast<uint32_t>(val.challenger.port()));
dict.Set("realm", val.realm);
return mate::ConvertToV8(isolate, dict);
}
// static
v8::Local<v8::Value> Converter<scoped_refptr<net::X509Certificate>>::ToV8(
v8::Isolate* isolate,
const scoped_refptr<net::X509Certificate>& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
std::string encoded_data;
net::X509Certificate::GetPEMEncoded(val->cert_buffer(), &encoded_data);
dict.Set("data", encoded_data);
dict.Set("issuer", val->issuer());
dict.Set("issuerName", val->issuer().GetDisplayName());
dict.Set("subject", val->subject());
dict.Set("subjectName", val->subject().GetDisplayName());
dict.Set("serialNumber", base::HexEncode(val->serial_number().data(),
val->serial_number().size()));
dict.Set("validStart", val->valid_start().ToDoubleT());
dict.Set("validExpiry", val->valid_expiry().ToDoubleT());
dict.Set("fingerprint",
net::HashValue(val->CalculateFingerprint256(val->cert_buffer()))
.ToString());
const auto& intermediate_buffers = val->intermediate_buffers();
if (!intermediate_buffers.empty()) {
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> issuer_intermediates;
issuer_intermediates.reserve(intermediate_buffers.size() - 1);
for (size_t i = 1; i < intermediate_buffers.size(); ++i) {
issuer_intermediates.push_back(
bssl::UpRef(intermediate_buffers[i].get()));
}
const scoped_refptr<net::X509Certificate>& issuer_cert =
net::X509Certificate::CreateFromBuffer(
bssl::UpRef(intermediate_buffers[0].get()),
std::move(issuer_intermediates));
dict.Set("issuerCert", issuer_cert);
}
return dict.GetHandle();
}
bool Converter<scoped_refptr<net::X509Certificate>>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
scoped_refptr<net::X509Certificate>* out) {
mate::Dictionary dict;
if (!ConvertFromV8(isolate, val, &dict))
return false;
std::string data;
dict.Get("data", &data);
scoped_refptr<net::X509Certificate> leaf_cert;
if (!CertFromData(data, &leaf_cert))
return false;
scoped_refptr<net::X509Certificate> issuer_cert;
if (dict.Get("issuerCert", &issuer_cert)) {
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
intermediates.push_back(bssl::UpRef(issuer_cert->cert_buffer()));
auto cert = net::X509Certificate::CreateFromBuffer(
bssl::UpRef(leaf_cert->cert_buffer()), std::move(intermediates));
if (!cert)
return false;
*out = cert;
} else {
*out = leaf_cert;
}
return true;
}
// static
v8::Local<v8::Value> Converter<net::CertPrincipal>::ToV8(
v8::Isolate* isolate,
const net::CertPrincipal& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("commonName", val.common_name);
dict.Set("organizations", val.organization_names);
dict.Set("organizationUnits", val.organization_unit_names);
dict.Set("locality", val.locality_name);
dict.Set("state", val.state_or_province_name);
dict.Set("country", val.country_name);
return dict.GetHandle();
}
// static
v8::Local<v8::Value> Converter<net::HttpResponseHeaders*>::ToV8(
v8::Isolate* isolate,
net::HttpResponseHeaders* headers) {
base::DictionaryValue response_headers;
if (headers) {
size_t iter = 0;
std::string key;
std::string value;
while (headers->EnumerateHeaderLines(&iter, &key, &value)) {
key = base::ToLowerASCII(key);
if (response_headers.FindKey(key)) {
base::ListValue* values = nullptr;
if (response_headers.GetList(key, &values))
values->AppendString(value);
} else {
auto values = std::make_unique<base::ListValue>();
values->AppendString(value);
response_headers.Set(key, std::move(values));
}
}
}
return ConvertToV8(isolate, response_headers);
}
bool Converter<net::HttpResponseHeaders*>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
net::HttpResponseHeaders* out) {
if (!val->IsObject()) {
return false;
}
auto addHeaderFromValue = [&isolate, &out](
const std::string& key,
const v8::Local<v8::Value>& localVal) {
auto context = isolate->GetCurrentContext();
v8::Local<v8::String> localStrVal;
if (!localVal->ToString(context).ToLocal(&localStrVal)) {
return false;
}
std::string value;
mate::ConvertFromV8(isolate, localStrVal, &value);
out->AddHeader(key + ": " + value);
return true;
};
auto context = isolate->GetCurrentContext();
auto headers = v8::Local<v8::Object>::Cast(val);
auto keys = headers->GetOwnPropertyNames(context).ToLocalChecked();
for (uint32_t i = 0; i < keys->Length(); i++) {
v8::Local<v8::Value> keyVal;
if (!keys->Get(context, i).ToLocal(&keyVal)) {
return false;
}
std::string key;
mate::ConvertFromV8(isolate, keyVal, &key);
auto localVal = headers->Get(context, keyVal).ToLocalChecked();
if (localVal->IsArray()) {
auto values = v8::Local<v8::Array>::Cast(localVal);
for (uint32_t j = 0; j < values->Length(); j++) {
if (!addHeaderFromValue(key,
values->Get(context, j).ToLocalChecked())) {
return false;
}
}
} else {
if (!addHeaderFromValue(key, localVal)) {
return false;
}
}
}
return true;
}
// static
v8::Local<v8::Value> Converter<network::ResourceRequest>::ToV8(
v8::Isolate* isolate,
const network::ResourceRequest& val) {
mate::Dictionary dict(isolate, v8::Object::New(isolate));
dict.Set("method", val.method);
dict.Set("url", val.url.spec());
dict.Set("referrer", val.referrer.spec());
mate::Dictionary headers(isolate, v8::Object::New(isolate));
for (net::HttpRequestHeaders::Iterator it(val.headers); it.GetNext();)
headers.Set(it.name(), it.value());
dict.Set("headers", headers);
if (val.request_body) {
const auto& elements = *val.request_body->elements();
v8::Local<v8::Array> arr = v8::Array::New(isolate, elements.size());
for (size_t i = 0; i < elements.size(); ++i) {
const auto& element = elements[i];
mate::Dictionary upload_data(isolate, v8::Object::New(isolate));
switch (element.type()) {
case network::mojom::DataElementType::kFile:
upload_data.Set("file", element.path().value());
break;
case network::mojom::DataElementType::kBytes:
upload_data.Set("bytes", node::Buffer::Copy(isolate, element.bytes(),
element.length())
.ToLocalChecked());
break;
case network::mojom::DataElementType::kBlob:
upload_data.Set("blobUUID", element.blob_uuid());
break;
default:
NOTREACHED() << "Found unsupported data element";
}
arr->Set(isolate->GetCurrentContext(), static_cast<uint32_t>(i),
upload_data.GetHandle())
.Check();
}
dict.Set("uploadData", arr);
}
return dict.GetHandle();
}
} // namespace mate
namespace atom {
void FillRequestDetails(base::DictionaryValue* details,
const net::URLRequest* request) {
details->SetString("method", request->method());
std::string url;
if (!request->url_chain().empty())
url = request->url().spec();
details->SetKey("url", base::Value(url));
details->SetString("referrer", request->referrer());
auto list = std::make_unique<base::ListValue>();
GetUploadData(list.get(), request);
if (!list->empty())
details->Set("uploadData", std::move(list));
auto headers_value = std::make_unique<base::DictionaryValue>();
for (net::HttpRequestHeaders::Iterator it(request->extra_request_headers());
it.GetNext();) {
headers_value->SetString(it.name(), it.value());
}
details->Set("headers", std::move(headers_value));
}
void GetUploadData(base::ListValue* upload_data_list,
const net::URLRequest* request) {
const net::UploadDataStream* upload_data = request->get_upload();
if (!upload_data)
return;
const std::vector<std::unique_ptr<net::UploadElementReader>>* readers =
upload_data->GetElementReaders();
for (const auto& reader : *readers) {
auto upload_data_dict = std::make_unique<base::DictionaryValue>();
if (reader->AsBytesReader()) {
const net::UploadBytesElementReader* bytes_reader =
reader->AsBytesReader();
auto bytes = std::make_unique<base::Value>(
std::vector<char>(bytes_reader->bytes(),
bytes_reader->bytes() + bytes_reader->length()));
upload_data_dict->Set("bytes", std::move(bytes));
} else if (reader->AsFileReader()) {
const net::UploadFileElementReader* file_reader = reader->AsFileReader();
auto file_path = file_reader->path().AsUTF8Unsafe();
upload_data_dict->SetKey("file", base::Value(file_path));
} else {
const storage::UploadBlobElementReader* blob_reader =
static_cast<storage::UploadBlobElementReader*>(reader.get());
upload_data_dict->SetString("blobUUID", blob_reader->uuid());
}
upload_data_list->Append(std::move(upload_data_dict));
}
}
} // namespace atom

View file

@ -0,0 +1,80 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_
#include "base/memory/ref_counted.h"
#include "native_mate/converter.h"
namespace base {
class DictionaryValue;
class ListValue;
} // namespace base
namespace net {
class AuthChallengeInfo;
class URLRequest;
class X509Certificate;
class HttpResponseHeaders;
struct CertPrincipal;
} // namespace net
namespace network {
struct ResourceRequest;
}
namespace mate {
template <>
struct Converter<net::AuthChallengeInfo> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::AuthChallengeInfo& val);
};
template <>
struct Converter<scoped_refptr<net::X509Certificate>> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const scoped_refptr<net::X509Certificate>& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
scoped_refptr<net::X509Certificate>* out);
};
template <>
struct Converter<net::CertPrincipal> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::CertPrincipal& val);
};
template <>
struct Converter<net::HttpResponseHeaders*> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
net::HttpResponseHeaders* headers);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
net::HttpResponseHeaders* out);
};
template <>
struct Converter<network::ResourceRequest> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const network::ResourceRequest& val);
};
} // namespace mate
namespace atom {
void FillRequestDetails(base::DictionaryValue* details,
const net::URLRequest* request);
void GetUploadData(base::ListValue* upload_data_list,
const net::URLRequest* request);
} // namespace atom
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_

View file

@ -0,0 +1,94 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/network_converter.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "atom/common/native_mate_converters/value_converter.h"
#include "base/numerics/safe_conversions.h"
#include "native_mate/dictionary.h"
#include "services/network/public/cpp/resource_request_body.h"
namespace mate {
// static
v8::Local<v8::Value>
Converter<scoped_refptr<network::ResourceRequestBody>>::ToV8(
v8::Isolate* isolate,
const scoped_refptr<network::ResourceRequestBody>& val) {
if (!val)
return v8::Null(isolate);
auto list = std::make_unique<base::ListValue>();
for (const auto& element : *(val->elements())) {
auto post_data_dict = std::make_unique<base::DictionaryValue>();
auto type = element.type();
if (type == network::mojom::DataElementType::kBytes) {
auto bytes = std::make_unique<base::Value>(std::vector<char>(
element.bytes(), element.bytes() + (element.length())));
post_data_dict->SetString("type", "rawData");
post_data_dict->Set("bytes", std::move(bytes));
} else if (type == network::mojom::DataElementType::kFile) {
post_data_dict->SetString("type", "file");
post_data_dict->SetKey("filePath",
base::Value(element.path().AsUTF8Unsafe()));
post_data_dict->SetInteger("offset", static_cast<int>(element.offset()));
post_data_dict->SetInteger("length", static_cast<int>(element.length()));
post_data_dict->SetDouble(
"modificationTime", element.expected_modification_time().ToDoubleT());
} else if (type == network::mojom::DataElementType::kBlob) {
post_data_dict->SetString("type", "blob");
post_data_dict->SetString("blobUUID", element.blob_uuid());
}
list->Append(std::move(post_data_dict));
}
return ConvertToV8(isolate, *list);
}
// static
bool Converter<scoped_refptr<network::ResourceRequestBody>>::FromV8(
v8::Isolate* isolate,
v8::Local<v8::Value> val,
scoped_refptr<network::ResourceRequestBody>* out) {
auto list = std::make_unique<base::ListValue>();
if (!ConvertFromV8(isolate, val, list.get()))
return false;
*out = new network::ResourceRequestBody();
for (size_t i = 0; i < list->GetSize(); ++i) {
base::DictionaryValue* dict = nullptr;
std::string type;
if (!list->GetDictionary(i, &dict))
return false;
dict->GetString("type", &type);
if (type == "rawData") {
base::Value* bytes = nullptr;
dict->GetBinary("bytes", &bytes);
(*out)->AppendBytes(
reinterpret_cast<const char*>(bytes->GetBlob().data()),
base::checked_cast<int>(bytes->GetBlob().size()));
} else if (type == "file") {
std::string file;
int offset = 0, length = -1;
double modification_time = 0.0;
dict->GetStringWithoutPathExpansion("filePath", &file);
dict->GetInteger("offset", &offset);
dict->GetInteger("file", &length);
dict->GetDouble("modificationTime", &modification_time);
(*out)->AppendFileRange(base::FilePath::FromUTF8Unsafe(file),
static_cast<uint64_t>(offset),
static_cast<uint64_t>(length),
base::Time::FromDoubleT(modification_time));
} else if (type == "blob") {
std::string uuid;
dict->GetString("blobUUID", &uuid);
(*out)->AppendBlob(uuid);
}
}
return true;
}
} // namespace mate

View file

@ -0,0 +1,29 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_NETWORK_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_NETWORK_CONVERTER_H_
#include "base/memory/scoped_refptr.h"
#include "native_mate/converter.h"
namespace network {
class ResourceRequestBody;
}
namespace mate {
template <>
struct Converter<scoped_refptr<network::ResourceRequestBody>> {
static v8::Local<v8::Value> ToV8(
v8::Isolate* isolate,
const scoped_refptr<network::ResourceRequestBody>& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
scoped_refptr<network::ResourceRequestBody>* out);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NETWORK_CONVERTER_H_

View file

@ -0,0 +1,87 @@
// Copyright (c) 2019 GitHub, Inc. All rights reserved.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_ONCE_CALLBACK_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_ONCE_CALLBACK_H_
#include <utility>
#include "atom/common/native_mate_converters/callback.h"
namespace mate {
namespace internal {
// Manages the OnceCallback with ref-couting.
template <typename Sig>
class RefCountedOnceCallback
: public base::RefCounted<RefCountedOnceCallback<Sig>> {
public:
explicit RefCountedOnceCallback(base::OnceCallback<Sig> callback)
: callback_(std::move(callback)) {}
base::OnceCallback<Sig> GetCallback() { return std::move(callback_); }
private:
friend class base::RefCounted<RefCountedOnceCallback<Sig>>;
~RefCountedOnceCallback() = default;
base::OnceCallback<Sig> callback_;
};
// Invokes the OnceCallback.
template <typename Sig>
struct InvokeOnceCallback {};
template <typename... ArgTypes>
struct InvokeOnceCallback<void(ArgTypes...)> {
static void Go(
scoped_refptr<RefCountedOnceCallback<void(ArgTypes...)>> holder,
ArgTypes... args) {
base::OnceCallback<void(ArgTypes...)> callback = holder->GetCallback();
DCHECK(!callback.is_null());
std::move(callback).Run(std::move(args)...);
}
};
template <typename ReturnType, typename... ArgTypes>
struct InvokeOnceCallback<ReturnType(ArgTypes...)> {
static ReturnType Go(
scoped_refptr<RefCountedOnceCallback<ReturnType(ArgTypes...)>> holder,
ArgTypes... args) {
base::OnceCallback<void(ArgTypes...)> callback = holder->GetCallback();
DCHECK(!callback.is_null());
return std::move(callback).Run(std::move(args)...);
}
};
} // namespace internal
template <typename Sig>
struct Converter<base::OnceCallback<Sig>> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
base::OnceCallback<Sig> val) {
// Reuse the converter of base::RepeatingCallback by storing the callback
// with a RefCounted.
auto holder = base::MakeRefCounted<internal::RefCountedOnceCallback<Sig>>(
std::move(val));
return Converter<base::RepeatingCallback<Sig>>::ToV8(
isolate,
base::BindRepeating(&internal::InvokeOnceCallback<Sig>::Go, holder));
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::OnceCallback<Sig>* out) {
if (!val->IsFunction())
return false;
*out = base::BindOnce(&internal::V8FunctionInvoker<Sig>::Go, isolate,
internal::SafeV8Function(isolate, val));
return true;
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_ONCE_CALLBACK_H_

View file

@ -0,0 +1,64 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING16_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING16_CONVERTER_H_
#include "base/strings/string16.h"
#include "gin/converter.h"
#include "native_mate/converter.h"
namespace gin {
template <>
struct Converter<base::string16> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::string16& val) {
return v8::String::NewFromTwoByte(
isolate, reinterpret_cast<const uint16_t*>(val.data()),
v8::NewStringType::kNormal, val.size())
.ToLocalChecked();
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::string16* out) {
if (!val->IsString())
return false;
v8::String::Value s(isolate, val);
out->assign(reinterpret_cast<const base::char16*>(*s), s.length());
return true;
}
};
inline v8::Local<v8::String> StringToV8(v8::Isolate* isolate,
const base::string16& input) {
return ConvertToV8(isolate, input).As<v8::String>();
}
} // namespace gin
namespace mate {
template <>
struct Converter<base::string16> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::string16& val) {
return gin::Converter<base::string16>::ToV8(isolate, val);
}
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::string16* out) {
return gin::Converter<base::string16>::FromV8(isolate, val, out);
}
};
inline v8::Local<v8::String> StringToV8(v8::Isolate* isolate,
const base::string16& input) {
return ConvertToV8(isolate, input).As<v8::String>();
}
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_STRING16_CONVERTER_H_

View file

@ -0,0 +1,34 @@
// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_UI_BASE_TYPES_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_UI_BASE_TYPES_CONVERTER_H_
#include "native_mate/converter.h"
#include "ui/base/ui_base_types.h"
namespace mate {
template <>
struct Converter<ui::MenuSourceType> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const ui::MenuSourceType& in) {
switch (in) {
case ui::MENU_SOURCE_MOUSE:
return mate::StringToV8(isolate, "mouse");
case ui::MENU_SOURCE_KEYBOARD:
return mate::StringToV8(isolate, "keyboard");
case ui::MENU_SOURCE_TOUCH:
return mate::StringToV8(isolate, "touch");
case ui::MENU_SOURCE_TOUCH_EDIT_MENU:
return mate::StringToV8(isolate, "touchMenu");
default:
return mate::StringToV8(isolate, "none");
}
}
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_UI_BASE_TYPES_CONVERTER_H_

View file

@ -0,0 +1,517 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/v8_value_converter.h"
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/logging.h"
#include "base/values.h"
#include "native_mate/dictionary.h"
#include "atom/common/node_bindings.h"
#include "atom/common/node_includes.h"
namespace atom {
namespace {
const int kMaxRecursionDepth = 100;
} // namespace
// The state of a call to FromV8Value.
class V8ValueConverter::FromV8ValueState {
public:
// Level scope which updates the current depth of some FromV8ValueState.
class Level {
public:
explicit Level(FromV8ValueState* state) : state_(state) {
state_->max_recursion_depth_--;
}
~Level() { state_->max_recursion_depth_++; }
private:
FromV8ValueState* state_;
};
FromV8ValueState() : max_recursion_depth_(kMaxRecursionDepth) {}
// If |handle| is not in |unique_map_|, then add it to |unique_map_| and
// return true.
//
// Otherwise do nothing and return false. Here "A is unique" means that no
// other handle B in the map points to the same object as A. Note that A can
// be unique even if there already is another handle with the same identity
// hash (key) in the map, because two objects can have the same hash.
bool AddToUniquenessCheck(v8::Local<v8::Object> handle) {
int hash;
auto iter = GetIteratorInMap(handle, &hash);
if (iter != unique_map_.end())
return false;
unique_map_.insert(std::make_pair(hash, handle));
return true;
}
bool RemoveFromUniquenessCheck(v8::Local<v8::Object> handle) {
int unused_hash;
auto iter = GetIteratorInMap(handle, &unused_hash);
if (iter == unique_map_.end())
return false;
unique_map_.erase(iter);
return true;
}
bool HasReachedMaxRecursionDepth() { return max_recursion_depth_ < 0; }
private:
using HashToHandleMap = std::multimap<int, v8::Local<v8::Object>>;
using Iterator = HashToHandleMap::const_iterator;
Iterator GetIteratorInMap(v8::Local<v8::Object> handle, int* hash) {
*hash = handle->GetIdentityHash();
// We only compare using == with handles to objects with the same identity
// hash. Different hash obviously means different objects, but two objects
// in a couple of thousands could have the same identity hash.
std::pair<Iterator, Iterator> range = unique_map_.equal_range(*hash);
for (auto it = range.first; it != range.second; ++it) {
// Operator == for handles actually compares the underlying objects.
if (it->second == handle)
return it;
}
// Not found.
return unique_map_.end();
}
HashToHandleMap unique_map_;
int max_recursion_depth_;
};
// A class to ensure that objects/arrays that are being converted by
// this V8ValueConverterImpl do not have cycles.
//
// An example of cycle: var v = {}; v = {key: v};
// Not an example of cycle: var v = {}; a = [v, v]; or w = {a: v, b: v};
class V8ValueConverter::ScopedUniquenessGuard {
public:
ScopedUniquenessGuard(V8ValueConverter::FromV8ValueState* state,
v8::Local<v8::Object> value)
: state_(state),
value_(value),
is_valid_(state_->AddToUniquenessCheck(value_)) {}
~ScopedUniquenessGuard() {
if (is_valid_) {
bool removed = state_->RemoveFromUniquenessCheck(value_);
DCHECK(removed);
}
}
bool is_valid() const { return is_valid_; }
private:
typedef std::multimap<int, v8::Local<v8::Object>> HashToHandleMap;
V8ValueConverter::FromV8ValueState* state_;
v8::Local<v8::Object> value_;
bool is_valid_;
DISALLOW_COPY_AND_ASSIGN(ScopedUniquenessGuard);
};
V8ValueConverter::V8ValueConverter() {}
void V8ValueConverter::SetRegExpAllowed(bool val) {
reg_exp_allowed_ = val;
}
void V8ValueConverter::SetFunctionAllowed(bool val) {
function_allowed_ = val;
}
void V8ValueConverter::SetStripNullFromObjects(bool val) {
strip_null_from_objects_ = val;
}
v8::Local<v8::Value> V8ValueConverter::ToV8Value(
const base::Value* value,
v8::Local<v8::Context> context) const {
v8::Context::Scope context_scope(context);
v8::EscapableHandleScope handle_scope(context->GetIsolate());
return handle_scope.Escape(ToV8ValueImpl(context->GetIsolate(), value));
}
std::unique_ptr<base::Value> V8ValueConverter::FromV8Value(
v8::Local<v8::Value> val,
v8::Local<v8::Context> context) const {
v8::Context::Scope context_scope(context);
v8::HandleScope handle_scope(context->GetIsolate());
FromV8ValueState state;
return FromV8ValueImpl(&state, val, context->GetIsolate());
}
v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
v8::Isolate* isolate,
const base::Value* value) const {
switch (value->type()) {
case base::Value::Type::NONE:
return v8::Null(isolate);
case base::Value::Type::BOOLEAN: {
bool val = value->GetBool();
return v8::Boolean::New(isolate, val);
}
case base::Value::Type::INTEGER: {
int val = value->GetInt();
return v8::Integer::New(isolate, val);
}
case base::Value::Type::DOUBLE: {
double val = value->GetDouble();
return v8::Number::New(isolate, val);
}
case base::Value::Type::STRING: {
std::string val = value->GetString();
return v8::String::NewFromUtf8(isolate, val.c_str(),
v8::NewStringType::kNormal, val.length())
.ToLocalChecked();
}
case base::Value::Type::LIST:
return ToV8Array(isolate, static_cast<const base::ListValue*>(value));
case base::Value::Type::DICTIONARY:
return ToV8Object(isolate,
static_cast<const base::DictionaryValue*>(value));
case base::Value::Type::BINARY:
return ToArrayBuffer(isolate, static_cast<const base::Value*>(value));
default:
LOG(ERROR) << "Unexpected value type: " << value->type();
return v8::Null(isolate);
}
}
v8::Local<v8::Value> V8ValueConverter::ToV8Array(
v8::Isolate* isolate,
const base::ListValue* val) const {
v8::Local<v8::Array> result(v8::Array::New(isolate, val->GetSize()));
auto context = isolate->GetCurrentContext();
for (size_t i = 0; i < val->GetSize(); ++i) {
const base::Value* child = nullptr;
val->Get(i, &child);
v8::Local<v8::Value> child_v8 = ToV8ValueImpl(isolate, child);
v8::TryCatch try_catch(isolate);
result->Set(context, static_cast<uint32_t>(i), child_v8).Check();
if (try_catch.HasCaught())
LOG(ERROR) << "Setter for index " << i << " threw an exception.";
}
return result;
}
v8::Local<v8::Value> V8ValueConverter::ToV8Object(
v8::Isolate* isolate,
const base::DictionaryValue* val) const {
mate::Dictionary result = mate::Dictionary::CreateEmpty(isolate);
result.SetHidden("simple", true);
for (base::DictionaryValue::Iterator iter(*val); !iter.IsAtEnd();
iter.Advance()) {
const std::string& key = iter.key();
v8::Local<v8::Value> child_v8 = ToV8ValueImpl(isolate, &iter.value());
v8::TryCatch try_catch(isolate);
result.Set(key, child_v8);
if (try_catch.HasCaught()) {
LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
<< "exception.";
}
}
return result.GetHandle();
}
v8::Local<v8::Value> V8ValueConverter::ToArrayBuffer(
v8::Isolate* isolate,
const base::Value* value) const {
const auto* data = reinterpret_cast<const char*>(value->GetBlob().data());
size_t length = value->GetBlob().size();
if (NodeBindings::IsInitialized()) {
return node::Buffer::Copy(isolate, data, length).ToLocalChecked();
}
if (length > node::Buffer::kMaxLength) {
return v8::Local<v8::Object>();
}
auto context = isolate->GetCurrentContext();
auto array_buffer = v8::ArrayBuffer::New(isolate, length);
memcpy(array_buffer->GetContents().Data(), data, length);
// From this point, if something goes wrong(can't find Buffer class for
// example) we'll simply return a Uint8Array based on the created ArrayBuffer.
// This can happen if no preload script was specified to the renderer.
mate::Dictionary global(isolate, context->Global());
v8::Local<v8::Value> buffer_value;
// Get the Buffer class stored as a hidden value in the global object. We'll
// use it return a browserified Buffer.
if (!global.GetHidden("Buffer", &buffer_value) ||
!buffer_value->IsFunction()) {
return v8::Uint8Array::New(array_buffer, 0, length);
}
mate::Dictionary buffer_class(
isolate,
buffer_value->ToObject(isolate->GetCurrentContext()).ToLocalChecked());
v8::Local<v8::Value> from_value;
if (!buffer_class.Get("from", &from_value) || !from_value->IsFunction()) {
return v8::Uint8Array::New(array_buffer, 0, length);
}
v8::Local<v8::Value> args[] = {array_buffer};
auto func = v8::Local<v8::Function>::Cast(from_value);
auto result = func->Call(context, v8::Null(isolate), 1, args);
if (!result.IsEmpty()) {
return result.ToLocalChecked();
}
return v8::Uint8Array::New(array_buffer, 0, length);
}
std::unique_ptr<base::Value> V8ValueConverter::FromV8ValueImpl(
FromV8ValueState* state,
v8::Local<v8::Value> val,
v8::Isolate* isolate) const {
FromV8ValueState::Level state_level(state);
if (state->HasReachedMaxRecursionDepth())
return nullptr;
if (val->IsExternal())
return std::make_unique<base::Value>();
if (val->IsNull())
return std::make_unique<base::Value>();
auto context = isolate->GetCurrentContext();
if (val->IsBoolean())
return std::make_unique<base::Value>(val->ToBoolean(isolate)->Value());
if (val->IsInt32())
return std::make_unique<base::Value>(val.As<v8::Int32>()->Value());
if (val->IsNumber()) {
double val_as_double = val.As<v8::Number>()->Value();
if (!std::isfinite(val_as_double))
return nullptr;
return std::make_unique<base::Value>(val_as_double);
}
if (val->IsString()) {
v8::String::Utf8Value utf8(isolate, val);
return std::make_unique<base::Value>(std::string(*utf8, utf8.length()));
}
if (val->IsUndefined())
// JSON.stringify ignores undefined.
return nullptr;
if (val->IsDate()) {
v8::Date* date = v8::Date::Cast(*val);
v8::Local<v8::Value> toISOString =
date->Get(context, v8::String::NewFromUtf8(isolate, "toISOString",
v8::NewStringType::kNormal)
.ToLocalChecked())
.ToLocalChecked();
if (toISOString->IsFunction()) {
v8::MaybeLocal<v8::Value> result =
toISOString.As<v8::Function>()->Call(context, val, 0, nullptr);
if (!result.IsEmpty()) {
v8::String::Utf8Value utf8(isolate, result.ToLocalChecked());
return std::make_unique<base::Value>(std::string(*utf8, utf8.length()));
}
}
}
if (val->IsRegExp()) {
if (!reg_exp_allowed_)
// JSON.stringify converts to an object.
return FromV8Object(val.As<v8::Object>(), state, isolate);
return std::make_unique<base::Value>(*v8::String::Utf8Value(isolate, val));
}
// v8::Value doesn't have a ToArray() method for some reason.
if (val->IsArray())
return FromV8Array(val.As<v8::Array>(), state, isolate);
if (val->IsFunction()) {
if (!function_allowed_)
// JSON.stringify refuses to convert function(){}.
return nullptr;
return FromV8Object(val.As<v8::Object>(), state, isolate);
}
if (node::Buffer::HasInstance(val)) {
return FromNodeBuffer(val, state, isolate);
}
if (val->IsObject()) {
return FromV8Object(val.As<v8::Object>(), state, isolate);
}
LOG(ERROR) << "Unexpected v8 value type encountered.";
return nullptr;
}
std::unique_ptr<base::Value> V8ValueConverter::FromV8Array(
v8::Local<v8::Array> val,
FromV8ValueState* state,
v8::Isolate* isolate) const {
ScopedUniquenessGuard uniqueness_guard(state, val);
if (!uniqueness_guard.is_valid())
return std::make_unique<base::Value>();
std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
val->CreationContext() != isolate->GetCurrentContext())
scope.reset(new v8::Context::Scope(val->CreationContext()));
std::unique_ptr<base::ListValue> result(new base::ListValue());
// Only fields with integer keys are carried over to the ListValue.
for (uint32_t i = 0; i < val->Length(); ++i) {
v8::TryCatch try_catch(isolate);
v8::Local<v8::Value> child_v8;
v8::MaybeLocal<v8::Value> maybe_child =
val->Get(isolate->GetCurrentContext(), i);
if (try_catch.HasCaught() || !maybe_child.ToLocal(&child_v8)) {
LOG(ERROR) << "Getter for index " << i << " threw an exception.";
child_v8 = v8::Null(isolate);
}
if (!val->HasRealIndexedProperty(isolate->GetCurrentContext(), i)
.FromMaybe(false)) {
result->Append(std::make_unique<base::Value>());
continue;
}
std::unique_ptr<base::Value> child =
FromV8ValueImpl(state, child_v8, isolate);
if (child)
result->Append(std::move(child));
else
// JSON.stringify puts null in places where values don't serialize, for
// example undefined and functions. Emulate that behavior.
result->Append(std::make_unique<base::Value>());
}
return std::move(result);
}
std::unique_ptr<base::Value> V8ValueConverter::FromNodeBuffer(
v8::Local<v8::Value> value,
FromV8ValueState* state,
v8::Isolate* isolate) const {
std::vector<char> buffer(
node::Buffer::Data(value),
node::Buffer::Data(value) + node::Buffer::Length(value));
return std::make_unique<base::Value>(std::move(buffer));
}
std::unique_ptr<base::Value> V8ValueConverter::FromV8Object(
v8::Local<v8::Object> val,
FromV8ValueState* state,
v8::Isolate* isolate) const {
ScopedUniquenessGuard uniqueness_guard(state, val);
if (!uniqueness_guard.is_valid())
return std::make_unique<base::Value>();
std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
val->CreationContext() != isolate->GetCurrentContext())
scope.reset(new v8::Context::Scope(val->CreationContext()));
auto result = std::make_unique<base::DictionaryValue>();
v8::Local<v8::Array> property_names;
if (!val->GetOwnPropertyNames(isolate->GetCurrentContext())
.ToLocal(&property_names)) {
return std::move(result);
}
for (uint32_t i = 0; i < property_names->Length(); ++i) {
v8::Local<v8::Value> key =
property_names->Get(isolate->GetCurrentContext(), i).ToLocalChecked();
// Extend this test to cover more types as necessary and if sensible.
if (!key->IsString() && !key->IsNumber()) {
NOTREACHED() << "Key \"" << *v8::String::Utf8Value(isolate, key)
<< "\" "
"is neither a string nor a number";
continue;
}
v8::String::Utf8Value name_utf8(isolate, key);
v8::TryCatch try_catch(isolate);
v8::Local<v8::Value> child_v8;
v8::MaybeLocal<v8::Value> maybe_child =
val->Get(isolate->GetCurrentContext(), key);
if (try_catch.HasCaught() || !maybe_child.ToLocal(&child_v8)) {
LOG(ERROR) << "Getter for property " << *name_utf8
<< " threw an exception.";
child_v8 = v8::Null(isolate);
}
std::unique_ptr<base::Value> child =
FromV8ValueImpl(state, child_v8, isolate);
if (!child)
// JSON.stringify skips properties whose values don't serialize, for
// example undefined and functions. Emulate that behavior.
continue;
// Strip null if asked (and since undefined is turned into null, undefined
// too). The use case for supporting this is JSON-schema support,
// specifically for extensions, where "optional" JSON properties may be
// represented as null, yet due to buggy legacy code elsewhere isn't
// treated as such (potentially causing crashes). For example, the
// "tabs.create" function takes an object as its first argument with an
// optional "windowId" property.
//
// Given just
//
// tabs.create({})
//
// this will work as expected on code that only checks for the existence of
// a "windowId" property (such as that legacy code). However given
//
// tabs.create({windowId: null})
//
// there *is* a "windowId" property, but since it should be an int, code
// on the browser which doesn't additionally check for null will fail.
// We can avoid all bugs related to this by stripping null.
if (strip_null_from_objects_ && child->is_none())
continue;
result->SetWithoutPathExpansion(std::string(*name_utf8, name_utf8.length()),
std::move(child));
}
return std::move(result);
}
} // namespace atom

View file

@ -0,0 +1,77 @@
// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_V8_VALUE_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_V8_VALUE_CONVERTER_H_
#include <memory>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "v8/include/v8.h"
namespace base {
class DictionaryValue;
class ListValue;
class Value;
} // namespace base
namespace atom {
class V8ValueConverter {
public:
V8ValueConverter();
void SetRegExpAllowed(bool val);
void SetFunctionAllowed(bool val);
void SetStripNullFromObjects(bool val);
v8::Local<v8::Value> ToV8Value(const base::Value* value,
v8::Local<v8::Context> context) const;
std::unique_ptr<base::Value> FromV8Value(
v8::Local<v8::Value> value,
v8::Local<v8::Context> context) const;
private:
class FromV8ValueState;
class ScopedUniquenessGuard;
v8::Local<v8::Value> ToV8ValueImpl(v8::Isolate* isolate,
const base::Value* value) const;
v8::Local<v8::Value> ToV8Array(v8::Isolate* isolate,
const base::ListValue* list) const;
v8::Local<v8::Value> ToV8Object(
v8::Isolate* isolate,
const base::DictionaryValue* dictionary) const;
v8::Local<v8::Value> ToArrayBuffer(v8::Isolate* isolate,
const base::Value* value) const;
std::unique_ptr<base::Value> FromV8ValueImpl(FromV8ValueState* state,
v8::Local<v8::Value> value,
v8::Isolate* isolate) const;
std::unique_ptr<base::Value> FromV8Array(v8::Local<v8::Array> array,
FromV8ValueState* state,
v8::Isolate* isolate) const;
std::unique_ptr<base::Value> FromNodeBuffer(v8::Local<v8::Value> value,
FromV8ValueState* state,
v8::Isolate* isolate) const;
std::unique_ptr<base::Value> FromV8Object(v8::Local<v8::Object> object,
FromV8ValueState* state,
v8::Isolate* isolate) const;
// If true, we will convert RegExp JavaScript objects to string.
bool reg_exp_allowed_ = false;
// If true, we will convert Function JavaScript objects to dictionaries.
bool function_allowed_ = false;
// If true, undefined and null values are ignored when converting v8 objects
// into Values.
bool strip_null_from_objects_ = false;
DISALLOW_COPY_AND_ASSIGN(V8ValueConverter);
};
} // namespace atom
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_V8_VALUE_CONVERTER_H_

View file

@ -0,0 +1,76 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/common/native_mate_converters/value_converter.h"
#include <memory>
#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "base/values.h"
namespace mate {
bool Converter<base::DictionaryValue>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::DictionaryValue* out) {
atom::V8ValueConverter converter;
std::unique_ptr<base::Value> value(
converter.FromV8Value(val, isolate->GetCurrentContext()));
if (value && value->is_dict()) {
out->Swap(static_cast<base::DictionaryValue*>(value.get()));
return true;
} else {
return false;
}
}
v8::Local<v8::Value> Converter<base::DictionaryValue>::ToV8(
v8::Isolate* isolate,
const base::DictionaryValue& val) {
atom::V8ValueConverter converter;
return converter.ToV8Value(&val, isolate->GetCurrentContext());
}
bool Converter<base::Value>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::Value* out) {
atom::V8ValueConverter converter;
std::unique_ptr<base::Value> value(
converter.FromV8Value(val, isolate->GetCurrentContext()));
if (value) {
*out = value->Clone();
return true;
} else {
return false;
}
}
v8::Local<v8::Value> Converter<base::Value>::ToV8(v8::Isolate* isolate,
const base::Value& val) {
atom::V8ValueConverter converter;
return converter.ToV8Value(&val, isolate->GetCurrentContext());
}
bool Converter<base::ListValue>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::ListValue* out) {
atom::V8ValueConverter converter;
std::unique_ptr<base::Value> value(
converter.FromV8Value(val, isolate->GetCurrentContext()));
if (value->is_list()) {
out->Swap(static_cast<base::ListValue*>(value.get()));
return true;
} else {
return false;
}
}
v8::Local<v8::Value> Converter<base::ListValue>::ToV8(
v8::Isolate* isolate,
const base::ListValue& val) {
atom::V8ValueConverter converter;
return converter.ToV8Value(&val, isolate->GetCurrentContext());
}
} // namespace mate

View file

@ -0,0 +1,47 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_COMMON_NATIVE_MATE_CONVERTERS_VALUE_CONVERTER_H_
#define ATOM_COMMON_NATIVE_MATE_CONVERTERS_VALUE_CONVERTER_H_
#include "native_mate/converter.h"
namespace base {
class DictionaryValue;
class ListValue;
class Value;
} // namespace base
namespace mate {
template <>
struct Converter<base::DictionaryValue> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::DictionaryValue* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::DictionaryValue& val);
};
template <>
struct Converter<base::Value> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::Value* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::Value& val);
};
template <>
struct Converter<base::ListValue> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
base::ListValue* out);
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const base::ListValue& val);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_VALUE_CONVERTER_H_