Merge branch 'master' into desktop-capture-api
This commit is contained in:
commit
04f7ceab73
464 changed files with 18563 additions and 4629 deletions
|
@ -30,6 +30,12 @@ IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync,
|
|||
base::ListValue /* arguments */,
|
||||
base::string16 /* result (in JSON) */)
|
||||
|
||||
IPC_MESSAGE_ROUTED1(AtomViewHostMsg_ZoomLevelChanged,
|
||||
double /* level */)
|
||||
|
||||
IPC_MESSAGE_ROUTED1(AtomViewMsg_SetZoomLevel,
|
||||
double /* level */)
|
||||
|
||||
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message,
|
||||
base::string16 /* channel */,
|
||||
base::ListValue /* arguments */)
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
|
||||
namespace {
|
||||
|
||||
v8::Persistent<v8::ObjectTemplate> template_;
|
||||
|
||||
class Archive : public mate::Wrappable {
|
||||
public:
|
||||
static v8::Local<v8::Value> Create(v8::Isolate* isolate,
|
||||
|
@ -101,15 +103,20 @@ class Archive : public mate::Wrappable {
|
|||
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||
return mate::ObjectTemplateBuilder(isolate)
|
||||
.SetValue("path", archive_->path())
|
||||
.SetMethod("getFileInfo", &Archive::GetFileInfo)
|
||||
.SetMethod("stat", &Archive::Stat)
|
||||
.SetMethod("readdir", &Archive::Readdir)
|
||||
.SetMethod("realpath", &Archive::Realpath)
|
||||
.SetMethod("copyFileOut", &Archive::CopyFileOut)
|
||||
.SetMethod("getFd", &Archive::GetFD)
|
||||
.SetMethod("destroy", &Archive::Destroy);
|
||||
if (template_.IsEmpty())
|
||||
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
|
||||
.SetValue("path", archive_->path())
|
||||
.SetMethod("getFileInfo", &Archive::GetFileInfo)
|
||||
.SetMethod("stat", &Archive::Stat)
|
||||
.SetMethod("readdir", &Archive::Readdir)
|
||||
.SetMethod("realpath", &Archive::Realpath)
|
||||
.SetMethod("copyFileOut", &Archive::CopyFileOut)
|
||||
.SetMethod("getFd", &Archive::GetFD)
|
||||
.SetMethod("destroy", &Archive::Destroy)
|
||||
.Build());
|
||||
|
||||
return mate::ObjectTemplateBuilder(
|
||||
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
79
atom/common/api/atom_api_id_weak_map.cc
Normal file
79
atom/common/api/atom_api_id_weak_map.cc
Normal 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.
|
||||
|
||||
#include "atom/common/api/atom_api_id_weak_map.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/constructor.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
IDWeakMap::IDWeakMap() {
|
||||
}
|
||||
|
||||
IDWeakMap::~IDWeakMap() {
|
||||
}
|
||||
|
||||
void IDWeakMap::Set(v8::Isolate* isolate,
|
||||
int32_t id,
|
||||
v8::Local<v8::Object> object) {
|
||||
id_weak_map_.Set(isolate, id, object);
|
||||
}
|
||||
|
||||
v8::Local<v8::Object> IDWeakMap::Get(v8::Isolate* isolate, int32_t id) {
|
||||
return id_weak_map_.Get(isolate, id).ToLocalChecked();
|
||||
}
|
||||
|
||||
bool IDWeakMap::Has(int32_t id) {
|
||||
return id_weak_map_.Has(id);
|
||||
}
|
||||
|
||||
void IDWeakMap::Remove(int32_t id) {
|
||||
id_weak_map_.Remove(id);
|
||||
}
|
||||
|
||||
void IDWeakMap::Clear() {
|
||||
id_weak_map_.Clear();
|
||||
}
|
||||
|
||||
// static
|
||||
void IDWeakMap::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
mate::ObjectTemplateBuilder(isolate, prototype)
|
||||
.SetMethod("set", &IDWeakMap::Set)
|
||||
.SetMethod("get", &IDWeakMap::Get)
|
||||
.SetMethod("has", &IDWeakMap::Has)
|
||||
.SetMethod("remove", &IDWeakMap::Remove)
|
||||
.SetMethod("clear", &IDWeakMap::Clear);
|
||||
}
|
||||
|
||||
// static
|
||||
mate::Wrappable* IDWeakMap::Create(v8::Isolate* isolate) {
|
||||
return new IDWeakMap;
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
using atom::api::IDWeakMap;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
v8::Local<v8::Function> constructor = mate::CreateConstructor<IDWeakMap>(
|
||||
isolate, "IDWeakMap", base::Bind(&IDWeakMap::Create));
|
||||
mate::Dictionary id_weak_map(isolate, constructor);
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.Set("IDWeakMap", id_weak_map);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_id_weak_map, Initialize)
|
44
atom/common/api/atom_api_id_weak_map.h
Normal file
44
atom/common/api/atom_api_id_weak_map.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// 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_API_ATOM_API_ID_WEAK_MAP_H_
|
||||
#define ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_
|
||||
|
||||
#include "atom/common/id_weak_map.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "native_mate/handle.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
|
||||
class IDWeakMap : public mate::Wrappable {
|
||||
public:
|
||||
static mate::Wrappable* Create(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
protected:
|
||||
IDWeakMap();
|
||||
~IDWeakMap();
|
||||
|
||||
private:
|
||||
// Api for IDWeakMap.
|
||||
void Set(v8::Isolate* isolate, int32_t id, v8::Local<v8::Object> object);
|
||||
v8::Local<v8::Object> Get(v8::Isolate* isolate, int32_t id);
|
||||
bool Has(int32_t id);
|
||||
void Remove(int32_t id);
|
||||
void Clear();
|
||||
|
||||
atom::IDWeakMap id_weak_map_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(IDWeakMap);
|
||||
};
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_COMMON_API_ATOM_API_ID_WEAK_MAP_H_
|
|
@ -63,7 +63,8 @@ float GetScaleFactorFromPath(const base::FilePath& path) {
|
|||
// We don't try to convert string to float here because it is very very
|
||||
// expensive.
|
||||
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i) {
|
||||
if (base::EndsWith(filename, kScaleFactorPairs[i].name, true))
|
||||
if (base::EndsWith(filename, kScaleFactorPairs[i].name,
|
||||
base::CompareCase::INSENSITIVE_ASCII))
|
||||
return kScaleFactorPairs[i].scale;
|
||||
}
|
||||
|
||||
|
@ -168,7 +169,8 @@ mate::ObjectTemplateBuilder NativeImage::GetObjectTemplateBuilder(
|
|||
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("toPng", &NativeImage::ToPNG)
|
||||
.SetMethod("toJpeg", &NativeImage::ToJPEG)
|
||||
.SetMethod("toDataUrl", &NativeImage::ToDataURL)
|
||||
.SetMethod("toDataURL", &NativeImage::ToDataURL)
|
||||
.SetMethod("toDataUrl", &NativeImage::ToDataURL) // deprecated.
|
||||
.SetMethod("isEmpty", &NativeImage::IsEmpty)
|
||||
.SetMethod("getSize", &NativeImage::GetSize)
|
||||
.SetMethod("setTemplateImage", &NativeImage::SetTemplateImage)
|
||||
|
@ -309,7 +311,7 @@ void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
|||
dict.SetMethod("createEmpty", &atom::api::NativeImage::CreateEmpty);
|
||||
dict.SetMethod("createFromPath", &atom::api::NativeImage::CreateFromPath);
|
||||
dict.SetMethod("createFromBuffer", &atom::api::NativeImage::CreateFromBuffer);
|
||||
dict.SetMethod("createFromDataUrl",
|
||||
dict.SetMethod("createFromDataURL",
|
||||
&atom::api::NativeImage::CreateFromDataURL);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "atom/common/atom_version.h"
|
||||
#include "atom/common/chrome_version.h"
|
||||
|
@ -40,7 +41,7 @@ void FatalErrorCallback(const char* location, const char* message) {
|
|||
}
|
||||
|
||||
void Log(const base::string16& message) {
|
||||
logging::LogMessage("CONSOLE", 0, 0).stream() << message;
|
||||
std::cout << message << std::flush;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -68,8 +69,9 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
|||
dict.SetMethod("activateUvLoop",
|
||||
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));
|
||||
|
||||
// Do not warn about deprecated APIs.
|
||||
dict.Set("noDeprecation", true);
|
||||
#if defined(MAS_BUILD)
|
||||
dict.Set("mas", true);
|
||||
#endif
|
||||
|
||||
mate::Dictionary versions;
|
||||
if (dict.Get("versions", &versions)) {
|
||||
|
|
|
@ -19,7 +19,7 @@ v8::Local<v8::Value> CallEmitWithArgs(v8::Isolate* isolate,
|
|||
// Perform microtask checkpoint after running JavaScript.
|
||||
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
|
||||
Locker::IsBrowserProcess() ?
|
||||
nullptr : new blink::WebScopedRunV8Script(isolate));
|
||||
nullptr : new blink::WebScopedRunV8Script);
|
||||
// Use node::MakeCallback to call the callback, and it will also run pending
|
||||
// tasks in Node.js.
|
||||
return node::MakeCallback(
|
||||
|
|
|
@ -1,27 +1,43 @@
|
|||
savedGlobal = global # the "global.global" might be deleted later
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
|
||||
module.exports =
|
||||
class CallbacksRegistry
|
||||
constructor: ->
|
||||
@emptyFunc = -> throw new Error "Browser trying to call a non-exist callback
|
||||
in renderer, this usually happens when renderer code forgot to release
|
||||
a callback installed on objects in browser when renderer was going to be
|
||||
unloaded or released."
|
||||
@nextId = 0
|
||||
@callbacks = {}
|
||||
|
||||
add: (callback) ->
|
||||
id = Math.random().toString()
|
||||
# The callback is already added.
|
||||
id = v8Util.getHiddenValue callback, 'callbackId'
|
||||
return id if id?
|
||||
|
||||
id = ++@nextId
|
||||
|
||||
# Capture the location of the function and put it in the ID string,
|
||||
# so that release errors can be tracked down easily.
|
||||
regexp = /at (.*)/gi
|
||||
stackString = (new Error).stack
|
||||
|
||||
while (match = regexp.exec(stackString)) isnt null
|
||||
[x, location] = match
|
||||
continue if location.indexOf('(native)') isnt -1
|
||||
continue if location.indexOf('atom.asar') isnt -1
|
||||
[x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location)
|
||||
break
|
||||
|
||||
@callbacks[id] = callback
|
||||
v8Util.setHiddenValue callback, 'callbackId', id
|
||||
v8Util.setHiddenValue callback, 'location', filenameAndLine
|
||||
id
|
||||
|
||||
get: (id) ->
|
||||
@callbacks[id] ? ->
|
||||
|
||||
call: (id, args...) ->
|
||||
@get(id).call savedGlobal, args...
|
||||
@get(id).call global, args...
|
||||
|
||||
apply: (id, args...) ->
|
||||
@get(id).apply savedGlobal, args...
|
||||
@get(id).apply global, args...
|
||||
|
||||
remove: (id) ->
|
||||
delete @callbacks[id]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
if process.platform is 'linux' and process.type is 'renderer'
|
||||
# On Linux we could not access clipboard in renderer process.
|
||||
module.exports = require('remote').require 'clipboard'
|
||||
module.exports = require('electron').remote.clipboard
|
||||
else
|
||||
module.exports = process.atomBinding 'clipboard'
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
binding = process.atomBinding 'crash_reporter'
|
||||
fs = require 'fs'
|
||||
os = require 'os'
|
||||
path = require 'path'
|
||||
{spawn} = require 'child_process'
|
||||
|
||||
electron = require 'electron'
|
||||
binding = process.atomBinding 'crash_reporter'
|
||||
|
||||
class CrashReporter
|
||||
start: (options={}) ->
|
||||
{@productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra} = options
|
||||
{@productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra} = options
|
||||
|
||||
app =
|
||||
if process.type is 'browser'
|
||||
require 'app'
|
||||
else
|
||||
require('remote').require 'app'
|
||||
# Deprecated.
|
||||
{deprecate} = electron
|
||||
if options.submitUrl
|
||||
submitURL ?= options.submitUrl
|
||||
deprecate.warn 'submitUrl', 'submitURL'
|
||||
|
||||
{app} = if process.type is 'browser' then electron else electron.remote
|
||||
|
||||
@productName ?= app.getName()
|
||||
companyName ?= 'GitHub, Inc'
|
||||
submitUrl ?= 'http://54.249.141.255:1127/post'
|
||||
submitURL ?= 'http://54.249.141.255:1127/post'
|
||||
autoSubmit ?= true
|
||||
ignoreSystemCrashHandler ?= false
|
||||
extra ?= {}
|
||||
|
@ -25,11 +29,11 @@ class CrashReporter
|
|||
extra._companyName ?= companyName
|
||||
extra._version ?= app.getVersion()
|
||||
|
||||
start = => binding.start @productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra
|
||||
start = => binding.start @productName, companyName, submitURL, autoSubmit, ignoreSystemCrashHandler, extra
|
||||
|
||||
if process.platform is 'win32'
|
||||
args = [
|
||||
"--reporter-url=#{submitUrl}"
|
||||
"--reporter-url=#{submitURL}"
|
||||
"--application-name=#{@productName}"
|
||||
"--v=1"
|
||||
]
|
||||
|
|
65
atom/common/api/lib/deprecate.coffee
Normal file
65
atom/common/api/lib/deprecate.coffee
Normal file
|
@ -0,0 +1,65 @@
|
|||
# Deprecate a method.
|
||||
deprecate = (oldName, newName, fn) ->
|
||||
warned = false
|
||||
->
|
||||
unless warned or process.noDeprecation
|
||||
warned = true
|
||||
deprecate.warn oldName, newName
|
||||
fn.apply this, arguments
|
||||
|
||||
# The method is renamed.
|
||||
deprecate.rename = (object, oldName, newName) ->
|
||||
warned = false
|
||||
newMethod = ->
|
||||
unless warned or process.noDeprecation
|
||||
warned = true
|
||||
deprecate.warn oldName, newName
|
||||
this[newName].apply this, arguments
|
||||
if typeof object is 'function'
|
||||
object.prototype[oldName] = newMethod
|
||||
else
|
||||
object[oldName] = newMethod
|
||||
|
||||
# Forward the method to member.
|
||||
deprecate.member = (object, method, member) ->
|
||||
warned = false
|
||||
object.prototype[method] = ->
|
||||
unless warned or process.noDeprecation
|
||||
warned = true
|
||||
deprecate.warn method, "#{member}.#{method}"
|
||||
this[member][method].apply this[member], arguments
|
||||
|
||||
# Deprecate a property.
|
||||
deprecate.property = (object, property, method) ->
|
||||
Object.defineProperty object, property,
|
||||
get: ->
|
||||
warned = false
|
||||
unless warned or process.noDeprecation
|
||||
warned = true
|
||||
deprecate.warn "#{property} property", "#{method} method"
|
||||
this[method]()
|
||||
|
||||
# Deprecate an event.
|
||||
deprecate.event = (emitter, oldName, newName, fn) ->
|
||||
warned = false
|
||||
emitter.on newName, (args...) ->
|
||||
if @listenerCount(oldName) > 0 # there is listeners for old API.
|
||||
unless warned or process.noDeprecation
|
||||
warned = true
|
||||
deprecate.warn "'#{oldName}' event", "'#{newName}' event"
|
||||
if fn?
|
||||
fn.apply this, arguments
|
||||
else
|
||||
@emit oldName, args...
|
||||
|
||||
# Print deprecate warning.
|
||||
deprecate.warn = (oldName, newName) ->
|
||||
message = "#{oldName} is deprecated. Use #{newName} instead."
|
||||
if process.throwDeprecation
|
||||
throw new Error(message)
|
||||
else if process.traceDeprecation
|
||||
console.trace message
|
||||
else
|
||||
console.warn "(electron) #{message}"
|
||||
|
||||
module.exports = deprecate
|
27
atom/common/api/lib/exports/electron.coffee
Normal file
27
atom/common/api/lib/exports/electron.coffee
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Do not expose the internal modules to `require`.
|
||||
exports.hideInternalModules = ->
|
||||
{globalPaths} = require 'module'
|
||||
if globalPaths.length is 3
|
||||
# Remove the "common/api/lib" and "browser-or-renderer/api/lib".
|
||||
globalPaths.splice 0, 2
|
||||
|
||||
Object.defineProperties exports,
|
||||
# Common modules, please sort with alphabet order.
|
||||
clipboard:
|
||||
# Must be enumerable, otherwise it woulde be invisible to remote module.
|
||||
enumerable: true
|
||||
get: -> require '../clipboard'
|
||||
crashReporter:
|
||||
enumerable: true
|
||||
get: -> require '../crash-reporter'
|
||||
nativeImage:
|
||||
enumerable: true
|
||||
get: -> require '../native-image'
|
||||
shell:
|
||||
enumerable: true
|
||||
get: -> require '../shell'
|
||||
# The internal modules, invisible unless you know their names.
|
||||
CallbacksRegistry:
|
||||
get: -> require '../callbacks-registry'
|
||||
deprecate:
|
||||
get: -> require '../deprecate'
|
|
@ -1 +1,7 @@
|
|||
module.exports = process.atomBinding 'native_image'
|
||||
{deprecate} = require 'electron'
|
||||
nativeImage = process.atomBinding 'native_image'
|
||||
|
||||
# Deprecated.
|
||||
deprecate.rename nativeImage, 'createFromDataUrl', 'createFromDataURL'
|
||||
|
||||
module.exports = nativeImage
|
||||
|
|
|
@ -1,4 +1 @@
|
|||
module.exports = process.atomBinding 'shell'
|
||||
|
||||
if process.platform is 'win32' and process.type is 'renderer'
|
||||
module.exports.showItemInFolder = require('remote').process.atomBinding('shell').showItemInFolder
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "atom/common/asar/scoped_temporary_file.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/pickle.h"
|
||||
#include "base/json/json_reader.h"
|
||||
|
@ -96,7 +97,6 @@ bool FillFileInfoWithNode(Archive::FileInfo* info,
|
|||
return false;
|
||||
info->size = static_cast<uint32>(size);
|
||||
|
||||
info->unpacked = false;
|
||||
if (node->GetBoolean("unpacked", &info->unpacked) && info->unpacked)
|
||||
return true;
|
||||
|
||||
|
@ -107,6 +107,8 @@ bool FillFileInfoWithNode(Archive::FileInfo* info,
|
|||
return false;
|
||||
info->offset += header_size;
|
||||
|
||||
node->GetBoolean("executable", &info->executable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -270,9 +272,17 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
|||
}
|
||||
|
||||
scoped_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
|
||||
if (!temp_file->InitFromFile(&file_, info.offset, info.size))
|
||||
base::FilePath::StringType ext = path.Extension();
|
||||
if (!temp_file->InitFromFile(&file_, ext, info.offset, info.size))
|
||||
return false;
|
||||
|
||||
#if defined(OS_POSIX)
|
||||
if (info.executable) {
|
||||
// chmod a+x temp_file;
|
||||
base::SetPosixFilePermissions(temp_file->path(), 0755);
|
||||
}
|
||||
#endif
|
||||
|
||||
*out = temp_file->path();
|
||||
external_files_.set(path, temp_file.Pass());
|
||||
return true;
|
||||
|
|
|
@ -25,8 +25,9 @@ class ScopedTemporaryFile;
|
|||
class Archive {
|
||||
public:
|
||||
struct FileInfo {
|
||||
FileInfo() : size(0), offset(0) {}
|
||||
FileInfo() : unpacked(false), executable(false), size(0), offset(0) {}
|
||||
bool unpacked;
|
||||
bool executable;
|
||||
uint32 size;
|
||||
uint64 offset;
|
||||
};
|
||||
|
|
|
@ -28,20 +28,34 @@ ScopedTemporaryFile::~ScopedTemporaryFile() {
|
|||
}
|
||||
}
|
||||
|
||||
bool ScopedTemporaryFile::Init() {
|
||||
bool ScopedTemporaryFile::Init(const base::FilePath::StringType& ext) {
|
||||
if (!path_.empty())
|
||||
return true;
|
||||
|
||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||
return base::CreateTemporaryFile(&path_);
|
||||
if (!base::CreateTemporaryFile(&path_))
|
||||
return false;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Keep the original extension.
|
||||
if (!ext.empty()) {
|
||||
base::FilePath new_path = path_.AddExtension(ext);
|
||||
if (!base::Move(path_, new_path))
|
||||
return false;
|
||||
path_ = new_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScopedTemporaryFile::InitFromFile(base::File* src,
|
||||
const base::FilePath::StringType& ext,
|
||||
uint64 offset, uint64 size) {
|
||||
if (!src->IsValid())
|
||||
return false;
|
||||
|
||||
if (!Init())
|
||||
if (!Init(ext))
|
||||
return false;
|
||||
|
||||
std::vector<char> buf(size);
|
||||
|
|
|
@ -22,11 +22,13 @@ class ScopedTemporaryFile {
|
|||
ScopedTemporaryFile();
|
||||
virtual ~ScopedTemporaryFile();
|
||||
|
||||
// Init an empty temporary file.
|
||||
bool Init();
|
||||
// Init an empty temporary file with a certain extension.
|
||||
bool Init(const base::FilePath::StringType& ext);
|
||||
|
||||
// Init an temporary file and fill it with content of |path|.
|
||||
bool InitFromFile(base::File* src, uint64 offset, uint64 size);
|
||||
bool InitFromFile(base::File* src,
|
||||
const base::FilePath::StringType& ext,
|
||||
uint64 offset, uint64 size);
|
||||
|
||||
base::FilePath path() const { return path_; }
|
||||
|
||||
|
|
11
atom/common/atom_constants.cc
Normal file
11
atom/common/atom_constants.cc
Normal file
|
@ -0,0 +1,11 @@
|
|||
// 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/atom_constants.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
const char* kCORSHeader = "Access-Control-Allow-Origin: *";
|
||||
|
||||
} // namespace atom
|
15
atom/common/atom_constants.h
Normal file
15
atom/common/atom_constants.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
// 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_ATOM_CONSTANTS_H_
|
||||
#define ATOM_COMMON_ATOM_CONSTANTS_H_
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Header to ignore CORS.
|
||||
extern const char* kCORSHeader;
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_COMMON_ATOM_CONSTANTS_H_
|
|
@ -6,8 +6,8 @@
|
|||
#define ATOM_VERSION_H
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 33
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_MINOR_VERSION 35
|
||||
#define ATOM_PATCH_VERSION 4
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#ifndef ATOM_COMMON_CHROME_VERSION_H_
|
||||
#define ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
#define CHROME_VERSION_STRING "45.0.2454.85"
|
||||
#define CHROME_VERSION_STRING "47.0.2526.73"
|
||||
#define CHROME_VERSION "v" CHROME_VERSION_STRING
|
||||
|
||||
#endif // ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
|
|
@ -48,11 +48,11 @@ CrashReporter::GetUploadedReports(const std::string& path) {
|
|||
std::vector<CrashReporter::UploadReportResult> result;
|
||||
if (base::ReadFileToString(base::FilePath::FromUTF8Unsafe(path),
|
||||
&file_content)) {
|
||||
std::vector<std::string> reports;
|
||||
base::SplitString(file_content, '\n', &reports);
|
||||
std::vector<std::string> reports = base::SplitString(
|
||||
file_content, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
for (const std::string& report : reports) {
|
||||
std::vector<std::string> report_item;
|
||||
base::SplitString(report, ',', &report_item);
|
||||
std::vector<std::string> report_item = base::SplitString(
|
||||
report, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
|
||||
int report_time = 0;
|
||||
if (report_item.size() >= 2 && base::StringToInt(report_item[0],
|
||||
&report_time)) {
|
||||
|
@ -64,4 +64,23 @@ CrashReporter::GetUploadedReports(const std::string& path) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void CrashReporter::InitBreakpad(const std::string& product_name,
|
||||
const std::string& version,
|
||||
const std::string& company_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) {
|
||||
}
|
||||
|
||||
void CrashReporter::SetUploadParameters() {
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) && defined(MAS_BUILD)
|
||||
// static
|
||||
CrashReporter* CrashReporter::GetInstance() {
|
||||
static CrashReporter crash_reporter;
|
||||
return &crash_reporter;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace crash_reporter
|
||||
|
|
|
@ -40,8 +40,8 @@ class CrashReporter {
|
|||
const std::string& company_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) = 0;
|
||||
virtual void SetUploadParameters() = 0;
|
||||
bool skip_system_crash_handler);
|
||||
virtual void SetUploadParameters();
|
||||
|
||||
StringMap upload_parameters_;
|
||||
bool is_browser_;
|
||||
|
|
|
@ -130,7 +130,7 @@ bool CrashReporterLinux::CrashDone(const MinidumpDescriptor& minidump,
|
|||
|
||||
// static
|
||||
CrashReporterLinux* CrashReporterLinux::GetInstance() {
|
||||
return Singleton<CrashReporterLinux>::get();
|
||||
return base::Singleton<CrashReporterLinux>::get();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
|
||||
namespace base {
|
||||
template <typename T> struct DefaultSingletonTraits;
|
||||
}
|
||||
|
||||
namespace google_breakpad {
|
||||
class ExceptionHandler;
|
||||
|
@ -34,7 +36,7 @@ class CrashReporterLinux : public CrashReporter {
|
|||
void SetUploadParameters() override;
|
||||
|
||||
private:
|
||||
friend struct DefaultSingletonTraits<CrashReporterLinux>;
|
||||
friend struct base::DefaultSingletonTraits<CrashReporterLinux>;
|
||||
|
||||
CrashReporterLinux();
|
||||
virtual ~CrashReporterLinux();
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
#include "base/strings/string_piece.h"
|
||||
#include "vendor/crashpad/client/simple_string_dictionary.h"
|
||||
|
||||
namespace base {
|
||||
template <typename T> struct DefaultSingletonTraits;
|
||||
}
|
||||
|
||||
namespace crash_reporter {
|
||||
|
||||
|
@ -31,7 +33,7 @@ class CrashReporterMac : public CrashReporter {
|
|||
void SetUploadParameters() override;
|
||||
|
||||
private:
|
||||
friend struct DefaultSingletonTraits<CrashReporterMac>;
|
||||
friend struct base::DefaultSingletonTraits<CrashReporterMac>;
|
||||
|
||||
CrashReporterMac();
|
||||
virtual ~CrashReporterMac();
|
||||
|
|
|
@ -126,7 +126,7 @@ CrashReporterMac::GetUploadedReports(const std::string& path) {
|
|||
|
||||
// static
|
||||
CrashReporterMac* CrashReporterMac::GetInstance() {
|
||||
return Singleton<CrashReporterMac>::get();
|
||||
return base::Singleton<CrashReporterMac>::get();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -11,6 +11,25 @@
|
|||
#include "base/memory/singleton.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "content/public/common/result_codes.h"
|
||||
#include "gin/public/debug.h"
|
||||
#include "sandbox/win/src/nt_internals.h"
|
||||
|
||||
#pragma intrinsic(_AddressOfReturnAddress)
|
||||
#pragma intrinsic(_ReturnAddress)
|
||||
|
||||
#ifdef _WIN64
|
||||
// See http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
|
||||
typedef struct _UNWIND_INFO {
|
||||
unsigned char Version : 3;
|
||||
unsigned char Flags : 5;
|
||||
unsigned char SizeOfProlog;
|
||||
unsigned char CountOfCodes;
|
||||
unsigned char FrameRegister : 4;
|
||||
unsigned char FrameOffset : 4;
|
||||
ULONG ExceptionHandler;
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
#endif
|
||||
|
||||
namespace crash_reporter {
|
||||
|
||||
|
@ -24,6 +43,94 @@ const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
|
|||
const wchar_t kWaitEventFormat[] = L"$1CrashServiceWaitEvent";
|
||||
const wchar_t kPipeNameFormat[] = L"\\\\.\\pipe\\$1 Crash Service";
|
||||
|
||||
typedef NTSTATUS (WINAPI* NtTerminateProcessPtr)(HANDLE ProcessHandle,
|
||||
NTSTATUS ExitStatus);
|
||||
char* g_real_terminate_process_stub = NULL;
|
||||
|
||||
void TerminateProcessWithoutDump() {
|
||||
// Patched stub exists based on conditions (See InitCrashReporter).
|
||||
// As a side note this function also gets called from
|
||||
// WindowProcExceptionFilter.
|
||||
if (g_real_terminate_process_stub == NULL) {
|
||||
::TerminateProcess(::GetCurrentProcess(), content::RESULT_CODE_KILLED);
|
||||
} else {
|
||||
NtTerminateProcessPtr real_terminate_proc =
|
||||
reinterpret_cast<NtTerminateProcessPtr>(
|
||||
static_cast<char*>(g_real_terminate_process_stub));
|
||||
real_terminate_proc(::GetCurrentProcess(), content::RESULT_CODE_KILLED);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
int CrashForExceptionInNonABICompliantCodeRange(
|
||||
PEXCEPTION_RECORD ExceptionRecord,
|
||||
ULONG64 EstablisherFrame,
|
||||
PCONTEXT ContextRecord,
|
||||
PDISPATCHER_CONTEXT DispatcherContext) {
|
||||
EXCEPTION_POINTERS info = { ExceptionRecord, ContextRecord };
|
||||
if (!CrashReporter::GetInstance())
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
return static_cast<CrashReporterWin*>(CrashReporter::GetInstance())->
|
||||
CrashForException(&info);
|
||||
}
|
||||
|
||||
struct ExceptionHandlerRecord {
|
||||
RUNTIME_FUNCTION runtime_function;
|
||||
UNWIND_INFO unwind_info;
|
||||
unsigned char thunk[12];
|
||||
};
|
||||
|
||||
bool RegisterNonABICompliantCodeRange(void* start, size_t size_in_bytes) {
|
||||
ExceptionHandlerRecord* record =
|
||||
reinterpret_cast<ExceptionHandlerRecord*>(start);
|
||||
|
||||
// We assume that the first page of the code range is executable and
|
||||
// committed and reserved for breakpad. What could possibly go wrong?
|
||||
|
||||
// All addresses are 32bit relative offsets to start.
|
||||
record->runtime_function.BeginAddress = 0;
|
||||
record->runtime_function.EndAddress =
|
||||
base::checked_cast<DWORD>(size_in_bytes);
|
||||
record->runtime_function.UnwindData =
|
||||
offsetof(ExceptionHandlerRecord, unwind_info);
|
||||
|
||||
// Create unwind info that only specifies an exception handler.
|
||||
record->unwind_info.Version = 1;
|
||||
record->unwind_info.Flags = UNW_FLAG_EHANDLER;
|
||||
record->unwind_info.SizeOfProlog = 0;
|
||||
record->unwind_info.CountOfCodes = 0;
|
||||
record->unwind_info.FrameRegister = 0;
|
||||
record->unwind_info.FrameOffset = 0;
|
||||
record->unwind_info.ExceptionHandler =
|
||||
offsetof(ExceptionHandlerRecord, thunk);
|
||||
|
||||
// Hardcoded thunk.
|
||||
// mov imm64, rax
|
||||
record->thunk[0] = 0x48;
|
||||
record->thunk[1] = 0xb8;
|
||||
void* handler = &CrashForExceptionInNonABICompliantCodeRange;
|
||||
memcpy(&record->thunk[2], &handler, 8);
|
||||
|
||||
// jmp rax
|
||||
record->thunk[10] = 0xff;
|
||||
record->thunk[11] = 0xe0;
|
||||
|
||||
// Protect reserved page against modifications.
|
||||
DWORD old_protect;
|
||||
return VirtualProtect(start, sizeof(ExceptionHandlerRecord),
|
||||
PAGE_EXECUTE_READ, &old_protect) &&
|
||||
RtlAddFunctionTable(&record->runtime_function, 1,
|
||||
reinterpret_cast<DWORD64>(start));
|
||||
}
|
||||
|
||||
void UnregisterNonABICompliantCodeRange(void* start) {
|
||||
ExceptionHandlerRecord* record =
|
||||
reinterpret_cast<ExceptionHandlerRecord*>(start);
|
||||
|
||||
RtlDeleteFunctionTable(&record->runtime_function);
|
||||
}
|
||||
#endif // _WIN64
|
||||
|
||||
} // namespace
|
||||
|
||||
CrashReporterWin::CrashReporterWin() {
|
||||
|
@ -46,9 +153,9 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name,
|
|||
return;
|
||||
}
|
||||
|
||||
base::string16 pipe_name = ReplaceStringPlaceholders(
|
||||
base::string16 pipe_name = base::ReplaceStringPlaceholders(
|
||||
kPipeNameFormat, base::UTF8ToUTF16(product_name), NULL);
|
||||
base::string16 wait_name = ReplaceStringPlaceholders(
|
||||
base::string16 wait_name = base::ReplaceStringPlaceholders(
|
||||
kWaitEventFormat, base::UTF8ToUTF16(product_name), NULL);
|
||||
|
||||
// Wait until the crash service is started.
|
||||
|
@ -63,26 +170,48 @@ void CrashReporterWin::InitBreakpad(const std::string& product_name,
|
|||
// to allow any previous handler to detach in the correct order.
|
||||
breakpad_.reset();
|
||||
|
||||
int handler_types = google_breakpad::ExceptionHandler::HANDLER_EXCEPTION |
|
||||
google_breakpad::ExceptionHandler::HANDLER_PURECALL;
|
||||
breakpad_.reset(new google_breakpad::ExceptionHandler(
|
||||
temp_dir.value(),
|
||||
FilterCallback,
|
||||
MinidumpCallback,
|
||||
this,
|
||||
handler_types,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||
kSmallDumpType,
|
||||
pipe_name.c_str(),
|
||||
GetCustomInfo(product_name, version, company_name)));
|
||||
|
||||
if (!breakpad_->IsOutOfProcess())
|
||||
LOG(ERROR) << "Cannot initialize out-of-process crash handler";
|
||||
|
||||
#ifdef _WIN64
|
||||
bool registered = false;
|
||||
// Hook up V8 to breakpad.
|
||||
{
|
||||
// gin::Debug::SetCodeRangeCreatedCallback only runs the callback when
|
||||
// Isolate is just created, so we have to manually run following code here.
|
||||
void* code_range = nullptr;
|
||||
size_t size = 0;
|
||||
v8::Isolate::GetCurrent()->GetCodeRange(&code_range, &size);
|
||||
if (code_range && size)
|
||||
registered = RegisterNonABICompliantCodeRange(code_range, size);
|
||||
}
|
||||
if (registered)
|
||||
gin::Debug::SetCodeRangeDeletedCallback(UnregisterNonABICompliantCodeRange);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CrashReporterWin::SetUploadParameters() {
|
||||
upload_parameters_["platform"] = "win32";
|
||||
}
|
||||
|
||||
int CrashReporterWin::CrashForException(EXCEPTION_POINTERS* info) {
|
||||
if (breakpad_) {
|
||||
breakpad_->WriteMinidumpForException(info);
|
||||
TerminateProcessWithoutDump();
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
// static
|
||||
bool CrashReporterWin::FilterCallback(void* context,
|
||||
EXCEPTION_POINTERS* exinfo,
|
||||
|
@ -130,7 +259,7 @@ google_breakpad::CustomClientInfo* CrashReporterWin::GetCustomInfo(
|
|||
|
||||
// static
|
||||
CrashReporterWin* CrashReporterWin::GetInstance() {
|
||||
return Singleton<CrashReporterWin>::get();
|
||||
return base::Singleton<CrashReporterWin>::get();
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
#include "base/memory/scoped_ptr.h"
|
||||
#include "vendor/breakpad/src/client/windows/handler/exception_handler.h"
|
||||
|
||||
namespace base {
|
||||
template <typename T> struct DefaultSingletonTraits;
|
||||
}
|
||||
|
||||
namespace crash_reporter {
|
||||
|
||||
|
@ -29,8 +31,11 @@ class CrashReporterWin : public CrashReporter {
|
|||
bool skip_system_crash_handler) override;
|
||||
void SetUploadParameters() override;
|
||||
|
||||
// Crashes the process after generating a dump for the provided exception.
|
||||
int CrashForException(EXCEPTION_POINTERS* info);
|
||||
|
||||
private:
|
||||
friend struct DefaultSingletonTraits<CrashReporterWin>;
|
||||
friend struct base::DefaultSingletonTraits<CrashReporterWin>;
|
||||
|
||||
CrashReporterWin();
|
||||
virtual ~CrashReporterWin();
|
||||
|
|
|
@ -118,7 +118,7 @@ HWND g_top_window = NULL;
|
|||
bool CreateTopWindow(HINSTANCE instance,
|
||||
const base::string16& application_name,
|
||||
bool visible) {
|
||||
base::string16 class_name = ReplaceStringPlaceholders(
|
||||
base::string16 class_name = base::ReplaceStringPlaceholders(
|
||||
kClassNameFormat, application_name, NULL);
|
||||
|
||||
WNDCLASSEXW wcx = {0};
|
||||
|
@ -309,9 +309,9 @@ bool CrashService::Initialize(const base::string16& application_name,
|
|||
|
||||
// Create or open an event to signal the browser process that the crash
|
||||
// service is initialized.
|
||||
base::string16 wait_name = ReplaceStringPlaceholders(
|
||||
base::string16 wait_name = base::ReplaceStringPlaceholders(
|
||||
kWaitEventFormat, application_name, NULL);
|
||||
HANDLE wait_event = ::CreateEventW(NULL, TRUE, FALSE, wait_name.c_str());
|
||||
HANDLE wait_event = ::CreateEventW(NULL, TRUE, TRUE, wait_name.c_str());
|
||||
::SetEvent(wait_event);
|
||||
|
||||
return true;
|
||||
|
@ -524,4 +524,3 @@ PSECURITY_DESCRIPTOR CrashService::GetSecurityDescriptorForLowIntegrity() {
|
|||
}
|
||||
|
||||
} // namespace breakpad
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ int Main(const wchar_t* cmd) {
|
|||
VLOG(1) << "Session start. cmdline is [" << cmd << "]";
|
||||
|
||||
// Setting the crash reporter.
|
||||
base::string16 pipe_name = ReplaceStringPlaceholders(kPipeNameFormat,
|
||||
base::string16 pipe_name = base::ReplaceStringPlaceholders(kPipeNameFormat,
|
||||
application_name,
|
||||
NULL);
|
||||
cmd_line.AppendSwitch("no-window");
|
||||
|
|
|
@ -32,12 +32,18 @@ IDWeakMap::IDWeakMap() : next_id_(0) {
|
|||
IDWeakMap::~IDWeakMap() {
|
||||
}
|
||||
|
||||
int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
|
||||
int32_t id = GetNextID();
|
||||
void IDWeakMap::Set(v8::Isolate* isolate,
|
||||
int32_t id,
|
||||
v8::Local<v8::Object> object) {
|
||||
auto global = make_linked_ptr(new v8::Global<v8::Object>(isolate, object));
|
||||
ObjectKey* key = new ObjectKey(id, this);
|
||||
global->SetWeak(key, OnObjectGC, v8::WeakCallbackType::kParameter);
|
||||
map_[id] = global;
|
||||
}
|
||||
|
||||
int32_t IDWeakMap::Add(v8::Isolate* isolate, v8::Local<v8::Object> object) {
|
||||
int32_t id = GetNextID();
|
||||
Set(isolate, id, object);
|
||||
return id;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ class IDWeakMap {
|
|||
IDWeakMap();
|
||||
~IDWeakMap();
|
||||
|
||||
// Sets the object to WeakMap with the given |id|.
|
||||
void Set(v8::Isolate* isolate, int32_t id, v8::Local<v8::Object> object);
|
||||
|
||||
// Adds |object| to WeakMap and returns its allocated |id|.
|
||||
int32_t Add(v8::Isolate* isolate, v8::Local<v8::Object> object);
|
||||
|
||||
|
|
|
@ -2,17 +2,19 @@
|
|||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <string>
|
||||
#include "atom/common/keyboad_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted) {
|
||||
*shifted = false;
|
||||
switch (c) {
|
||||
case 8: case 0x7F: return ui::VKEY_BACK;
|
||||
case 9: return ui::VKEY_TAB;
|
||||
case 0xD: case 3: return ui::VKEY_RETURN;
|
||||
case 0x08: return ui::VKEY_BACK;
|
||||
case 0x7F: return ui::VKEY_DELETE;
|
||||
case 0x09: return ui::VKEY_TAB;
|
||||
case 0x0D: return ui::VKEY_RETURN;
|
||||
case 0x1B: return ui::VKEY_ESCAPE;
|
||||
case ' ': return ui::VKEY_SPACE;
|
||||
|
||||
|
@ -70,4 +72,28 @@ ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted) {
|
|||
}
|
||||
}
|
||||
|
||||
// Return key code of the char.
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr) {
|
||||
if (chr == "enter") return ui::VKEY_RETURN;
|
||||
if (chr == "backspace") return ui::VKEY_BACK;
|
||||
if (chr == "delete") return ui::VKEY_DELETE;
|
||||
if (chr == "tab") return ui::VKEY_TAB;
|
||||
if (chr == "escape") return ui::VKEY_ESCAPE;
|
||||
if (chr == "control") return ui::VKEY_CONTROL;
|
||||
if (chr == "alt") return ui::VKEY_MENU;
|
||||
if (chr == "shift") return ui::VKEY_SHIFT;
|
||||
if (chr == "end") return ui::VKEY_END;
|
||||
if (chr == "home") return ui::VKEY_HOME;
|
||||
if (chr == "insert") return ui::VKEY_INSERT;
|
||||
if (chr == "left") return ui::VKEY_LEFT;
|
||||
if (chr == "up") return ui::VKEY_UP;
|
||||
if (chr == "right") return ui::VKEY_RIGHT;
|
||||
if (chr == "down") return ui::VKEY_DOWN;
|
||||
if (chr == "pageup") return ui::VKEY_PRIOR;
|
||||
if (chr == "pagedown") return ui::VKEY_NEXT;
|
||||
if (chr == "printscreen") return ui::VKEY_SNAPSHOT;
|
||||
|
||||
return ui::VKEY_UNKNOWN;
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -5,13 +5,18 @@
|
|||
#ifndef ATOM_COMMON_KEYBOAD_UTIL_H_
|
||||
#define ATOM_COMMON_KEYBOAD_UTIL_H_
|
||||
|
||||
#include <string>
|
||||
#include "ui/events/keycodes/keyboard_codes.h"
|
||||
#include "base/strings/string_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Return key code of the char, and also determine whether the SHIFT key is
|
||||
// pressed.
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(char c, bool* shifted);
|
||||
ui::KeyboardCode KeyboardCodeFromCharCode(base::char16 c, bool* shifted);
|
||||
|
||||
// Return key code of the char from a string representation of the char
|
||||
ui::KeyboardCode KeyboardCodeFromKeyIdentifier(const std::string& chr);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ process.on 'exit', ->
|
|||
|
||||
# Separate asar package's path from full path.
|
||||
splitPath = (p) ->
|
||||
return [false] if process.noAsar # shortcut to disable asar.
|
||||
return [false] if typeof p isnt 'string'
|
||||
return [true, p, ''] if p.substr(-5) is '.asar'
|
||||
p = path.normalize p
|
||||
|
@ -254,7 +255,8 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
|
||||
openSync = fs.openSync
|
||||
readFileSync = fs.readFileSync
|
||||
fs.readFileSync = (p, options) ->
|
||||
fs.readFileSync = (p, opts) ->
|
||||
options = opts # this allows v8 to optimize this function
|
||||
[isAsar, asarPath, filePath] = splitPath p
|
||||
return readFileSync.apply this, arguments unless isAsar
|
||||
|
||||
|
@ -263,7 +265,9 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
|
||||
info = archive.getFileInfo filePath
|
||||
notFoundError asarPath, filePath unless info
|
||||
return new Buffer(0) if info.size is 0
|
||||
|
||||
if info.size is 0
|
||||
return if options then '' else new Buffer(0)
|
||||
|
||||
if info.unpacked
|
||||
realPath = archive.copyFileOut filePath
|
||||
|
@ -352,3 +356,4 @@ exports.wrapFsWithAsar = (fs) ->
|
|||
overrideAPISync process, 'dlopen', 1
|
||||
overrideAPISync require('module')._extensions, '.node', 1
|
||||
overrideAPISync fs, 'openSync'
|
||||
overrideAPISync child_process, 'execFileSync'
|
||||
|
|
|
@ -9,21 +9,9 @@ process.atomBinding = (name) ->
|
|||
catch e
|
||||
process.binding "atom_common_#{name}" if /No such module/.test e.message
|
||||
|
||||
# Global module search paths.
|
||||
globalPaths = Module.globalPaths
|
||||
|
||||
# Don't lookup modules in user-defined search paths, see http://git.io/vf8sF.
|
||||
homeDir =
|
||||
if process.platform is 'win32'
|
||||
process.env.USERPROFILE
|
||||
else
|
||||
process.env.HOME
|
||||
if homeDir # Node only add user-defined search paths when $HOME is defined.
|
||||
userModulePath = path.resolve homeDir, '.node_modules'
|
||||
globalPaths.splice globalPaths.indexOf(userModulePath), 2
|
||||
|
||||
# Add common/api/lib to module search paths.
|
||||
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
unless process.env.ELECTRON_HIDE_INTERNAL_MODULES
|
||||
# Add common/api/lib to module search paths.
|
||||
Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
|
||||
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to
|
||||
# run the callbacks, however since we only run uv loop on requests, the
|
||||
|
|
29
atom/common/lib/reset-search-paths.coffee
Normal file
29
atom/common/lib/reset-search-paths.coffee
Normal file
|
@ -0,0 +1,29 @@
|
|||
path = require 'path'
|
||||
Module = require 'module'
|
||||
|
||||
# Clear Node's global search paths.
|
||||
Module.globalPaths.length = 0
|
||||
|
||||
# Clear current and parent(init.coffee)'s search paths.
|
||||
module.paths = []
|
||||
module.parent.paths = []
|
||||
|
||||
# Prevent Node from adding paths outside this app to search paths.
|
||||
Module._nodeModulePaths = (from) ->
|
||||
from = path.resolve from
|
||||
|
||||
# If "from" is outside the app then we do nothing.
|
||||
skipOutsidePaths = from.startsWith process.resourcesPath
|
||||
|
||||
# Following logoic is copied from module.js.
|
||||
splitRe = if process.platform is 'win32' then /[\/\\]/ else /\//
|
||||
paths = []
|
||||
|
||||
parts = from.split splitRe
|
||||
for part, tip in parts by -1
|
||||
continue if part is 'node_modules'
|
||||
dir = parts.slice(0, tip + 1).join path.sep
|
||||
break if skipOutsidePaths and not dir.startsWith process.resourcesPath
|
||||
paths.push path.join(dir, 'node_modules')
|
||||
|
||||
paths
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "atom/common/keyboad_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 "native_mate/dictionary.h"
|
||||
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
|
||||
|
@ -29,10 +30,10 @@ int VectorToBitArray(const std::vector<T>& vec) {
|
|||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<char> {
|
||||
struct Converter<base::char16> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||
char* out) {
|
||||
std::string code = base::StringToLowerASCII(V8ToString(val));
|
||||
base::char16* out) {
|
||||
base::string16 code = base::UTF8ToUTF16(V8ToString(val));
|
||||
if (code.length() != 1)
|
||||
return false;
|
||||
*out = code[0];
|
||||
|
@ -44,7 +45,7 @@ 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::StringToLowerASCII(V8ToString(val));
|
||||
std::string type = base::ToLowerASCII(V8ToString(val));
|
||||
if (type == "mousedown")
|
||||
*out = blink::WebInputEvent::MouseDown;
|
||||
else if (type == "mouseup")
|
||||
|
@ -60,7 +61,7 @@ struct Converter<blink::WebInputEvent::Type> {
|
|||
else if (type == "mousewheel")
|
||||
*out = blink::WebInputEvent::MouseWheel;
|
||||
else if (type == "keydown")
|
||||
*out = blink::WebInputEvent::KeyDown;
|
||||
*out = blink::WebInputEvent::RawKeyDown;
|
||||
else if (type == "keyup")
|
||||
*out = blink::WebInputEvent::KeyUp;
|
||||
else if (type == "char")
|
||||
|
@ -77,11 +78,26 @@ struct Converter<blink::WebInputEvent::Type> {
|
|||
}
|
||||
};
|
||||
|
||||
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(V8ToString(val));
|
||||
if (button == "left")
|
||||
*out = blink::WebMouseEvent::Button::ButtonLeft;
|
||||
else if (button == "middle")
|
||||
*out = blink::WebMouseEvent::Button::ButtonMiddle;
|
||||
else if (button == "right")
|
||||
*out = blink::WebMouseEvent::Button::ButtonRight;
|
||||
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::StringToLowerASCII(V8ToString(val));
|
||||
std::string modifier = base::ToLowerASCII(V8ToString(val));
|
||||
if (modifier == "shift")
|
||||
*out = blink::WebInputEvent::ShiftKey;
|
||||
else if (modifier == "control" || modifier == "ctrl")
|
||||
|
@ -142,16 +158,26 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(
|
|||
return false;
|
||||
if (!ConvertFromV8(isolate, val, static_cast<blink::WebInputEvent*>(out)))
|
||||
return false;
|
||||
char code;
|
||||
if (!dict.Get("keyCode", &code))
|
||||
return false;
|
||||
base::char16 code;
|
||||
std::string identifier;
|
||||
bool shifted = false;
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
|
||||
if (out->windowsKeyCode == ui::VKEY_UNKNOWN)
|
||||
|
||||
if (dict.Get("keyCode", &code))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromCharCode(code, &shifted);
|
||||
else if (dict.Get("keyCode", &identifier))
|
||||
out->windowsKeyCode = atom::KeyboardCodeFromKeyIdentifier(
|
||||
base::ToLowerASCII(identifier));
|
||||
else
|
||||
return false;
|
||||
|
||||
if (shifted)
|
||||
out->modifiers |= blink::WebInputEvent::ShiftKey;
|
||||
out->setKeyIdentifierFromWindowsKeyCode();
|
||||
if (out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) {
|
||||
out->text[0] = code;
|
||||
out->unmodifiedText[0] = code;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -176,6 +202,7 @@ bool Converter<blink::WebMouseEvent>::FromV8(
|
|||
return false;
|
||||
if (!dict.Get("x", &out->x) || !dict.Get("y", &out->y))
|
||||
return false;
|
||||
dict.Get("button", &out->button);
|
||||
dict.Get("globalX", &out->globalX);
|
||||
dict.Get("globalY", &out->globalY);
|
||||
dict.Get("movementX", &out->movementX);
|
||||
|
@ -236,7 +263,7 @@ bool Converter<blink::WebDeviceEmulationParams>::FromV8(
|
|||
|
||||
std::string screen_position;
|
||||
if (dict.Get("screenPosition", &screen_position)) {
|
||||
screen_position = base::StringToLowerASCII(screen_position);
|
||||
screen_position = base::ToLowerASCII(screen_position);
|
||||
if (screen_position == "mobile")
|
||||
out->screenPosition = blink::WebDeviceEmulationParams::Mobile;
|
||||
else if (screen_position == "desktop")
|
||||
|
|
137
atom/common/native_mate_converters/callback.cc
Normal file
137
atom/common/native_mate_converters/callback.cc
Normal file
|
@ -0,0 +1,137 @@
|
|||
// 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 "content/public/browser/browser_thread.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace mate {
|
||||
|
||||
namespace internal {
|
||||
|
||||
namespace {
|
||||
|
||||
struct TranslaterHolder {
|
||||
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) {
|
||||
v8::Isolate* isolate = args->isolate();
|
||||
|
||||
// Check if the callback has already been called.
|
||||
v8::Local<v8::String> called_symbol = mate::StringToSymbol(isolate, "called");
|
||||
if (state->Has(called_symbol)) {
|
||||
args->ThrowError("callback can only be called for once");
|
||||
return;
|
||||
} else {
|
||||
state->Set(called_symbol, v8::Boolean::New(isolate, true));
|
||||
}
|
||||
|
||||
TranslaterHolder* holder = static_cast<TranslaterHolder*>(external->Value());
|
||||
holder->translater.Run(args);
|
||||
delete holder;
|
||||
}
|
||||
|
||||
// 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(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, arraysize(converted), converted).ToLocalChecked();
|
||||
}
|
||||
|
||||
} // 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) {
|
||||
// The FunctionTemplate is cached.
|
||||
if (g_call_translater.IsEmpty())
|
||||
g_call_translater.Reset(
|
||||
isolate,
|
||||
mate::CreateFunctionTemplate(isolate, base::Bind(&CallTranslater)));
|
||||
|
||||
v8::Local<v8::FunctionTemplate> call_translater =
|
||||
v8::Local<v8::FunctionTemplate>::New(isolate, g_call_translater);
|
||||
TranslaterHolder* holder = new TranslaterHolder;
|
||||
holder->translater = translater;
|
||||
return BindFunctionWith(isolate,
|
||||
isolate->GetCurrentContext(),
|
||||
call_translater->GetFunction(),
|
||||
v8::External::New(isolate, holder),
|
||||
v8::Object::New(isolate));
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace mate
|
|
@ -10,6 +10,7 @@
|
|||
#include "atom/common/api/locker.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "native_mate/function_template.h"
|
||||
#include "native_mate/scoped_persistent.h"
|
||||
#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
|
||||
|
@ -18,21 +19,40 @@ namespace mate {
|
|||
|
||||
namespace internal {
|
||||
|
||||
typedef scoped_refptr<RefCountedPersistent<v8::Function> > SafeV8Function;
|
||||
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, SafeV8Function function,
|
||||
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);
|
||||
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
|
||||
Locker::IsBrowserProcess() ?
|
||||
nullptr : new blink::WebScopedRunV8Script(isolate));
|
||||
v8::Local<v8::Function> holder = function->NewHandle();
|
||||
nullptr : new blink::WebScopedRunV8Script);
|
||||
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, raw)... };
|
||||
|
@ -43,14 +63,17 @@ struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
|
|||
|
||||
template <typename... ArgTypes>
|
||||
struct V8FunctionInvoker<void(ArgTypes...)> {
|
||||
static void Go(v8::Isolate* isolate, SafeV8Function function,
|
||||
static void Go(v8::Isolate* isolate,
|
||||
const SafeV8Function& function,
|
||||
ArgTypes... raw) {
|
||||
Locker locker(isolate);
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
if (!function.IsAlive())
|
||||
return;
|
||||
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
|
||||
Locker::IsBrowserProcess() ?
|
||||
nullptr : new blink::WebScopedRunV8Script(isolate));
|
||||
v8::Local<v8::Function> holder = function->NewHandle();
|
||||
nullptr : new blink::WebScopedRunV8Script);
|
||||
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, raw)... };
|
||||
|
@ -60,31 +83,60 @@ struct V8FunctionInvoker<void(ArgTypes...)> {
|
|||
|
||||
template <typename ReturnType, typename... ArgTypes>
|
||||
struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
|
||||
static ReturnType Go(v8::Isolate* isolate, SafeV8Function function,
|
||||
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;
|
||||
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
|
||||
Locker::IsBrowserProcess() ?
|
||||
nullptr : new blink::WebScopedRunV8Script(isolate));
|
||||
v8::Local<v8::Function> holder = function->NewHandle();
|
||||
nullptr : new blink::WebScopedRunV8Script);
|
||||
v8::Local<v8::Function> holder = function.NewHandle(isolate);
|
||||
v8::Local<v8::Context> context = holder->CreationContext();
|
||||
v8::Context::Scope context_scope(context);
|
||||
ReturnType ret;
|
||||
std::vector<v8::Local<v8::Value>> args = { ConvertToV8(isolate, raw)... };
|
||||
v8::Local<v8::Value> val(holder->Call(holder, args.size(), &args.front()));
|
||||
Converter<ReturnType>::FromV8(isolate, val, &ret);
|
||||
v8::Local<v8::Value> result;
|
||||
auto maybe_result =
|
||||
holder->Call(context, holder, args.size(), &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);
|
||||
|
||||
// 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::Callback<Sig> > {
|
||||
struct Converter<base::Callback<Sig>> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const base::Callback<Sig>& val) {
|
||||
return CreateFunctionTemplate(isolate, val)->GetFunction();
|
||||
const base::Callback<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);
|
||||
return internal::CreateFunctionFromTranslater(isolate, translater);
|
||||
}
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
|
@ -92,9 +144,8 @@ struct Converter<base::Callback<Sig> > {
|
|||
if (!val->IsFunction())
|
||||
return false;
|
||||
|
||||
internal::SafeV8Function function(
|
||||
new RefCountedPersistent<v8::Function>(isolate, val));
|
||||
*out = base::Bind(&internal::V8FunctionInvoker<Sig>::Go, isolate, function);
|
||||
*out = base::Bind(&internal::V8FunctionInvoker<Sig>::Go,
|
||||
isolate, internal::SafeV8Function(isolate, val));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
100
atom/common/native_mate_converters/content_converter.cc
Normal file
100
atom/common/native_mate_converters/content_converter.cc
Normal file
|
@ -0,0 +1,100 @@
|
|||
// 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 <vector>
|
||||
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/string16_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);
|
||||
case content::MenuItem::OPTION:
|
||||
case content::MenuItem::SUBMENU:
|
||||
v8_item.Set("label", item.label);
|
||||
v8_item.Set("enabled", item.enabled);
|
||||
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::Bind(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);
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace mate
|
37
atom/common/native_mate_converters/content_converter.h
Normal file
37
atom/common/native_mate_converters/content_converter.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
// 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/common/menu_item.h"
|
||||
#include "native_mate/converter.h"
|
||||
|
||||
namespace content {
|
||||
struct ContextMenuParams;
|
||||
class WebContents;
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_CONTENT_CONVERTER_H_
|
|
@ -21,6 +21,9 @@ struct Converter<base::FilePath> {
|
|||
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);
|
||||
|
|
53
atom/common/native_mate_converters/net_converter.cc
Normal file
53
atom/common/native_mate_converters/net_converter.cc
Normal file
|
@ -0,0 +1,53 @@
|
|||
// 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 <string>
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "net/cert/x509_certificate.h"
|
||||
#include "net/url_request/url_request.h"
|
||||
|
||||
namespace mate {
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Converter<const net::URLRequest*>::ToV8(
|
||||
v8::Isolate* isolate, const net::URLRequest* val) {
|
||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("method", val->method());
|
||||
dict.Set("url", val->url().spec());
|
||||
dict.Set("referrer", val->referrer());
|
||||
return mate::ConvertToV8(isolate, dict);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Converter<const 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->os_cert_handle(), &encoded_data);
|
||||
auto buffer = node::Buffer::Copy(isolate,
|
||||
encoded_data.data(),
|
||||
encoded_data.size()).ToLocalChecked();
|
||||
dict.Set("data", buffer);
|
||||
dict.Set("issuerName", val->issuer().GetDisplayName());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
|
||||
} // namespace mate
|
39
atom/common/native_mate_converters/net_converter.h
Normal file
39
atom/common/native_mate_converters/net_converter.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
// 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 net {
|
||||
class AuthChallengeInfo;
|
||||
class URLRequest;
|
||||
class X509Certificate;
|
||||
}
|
||||
|
||||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<const net::URLRequest*> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const net::URLRequest* val);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<const 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);
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_
|
|
@ -152,6 +152,10 @@ v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
|
|||
return ToV8Object(isolate,
|
||||
static_cast<const base::DictionaryValue*>(value));
|
||||
|
||||
case base::Value::TYPE_BINARY:
|
||||
return ToArrayBuffer(isolate,
|
||||
static_cast<const base::BinaryValue*>(value));
|
||||
|
||||
default:
|
||||
LOG(ERROR) << "Unexpected value type: " << value->GetType();
|
||||
return v8::Null(isolate);
|
||||
|
@ -200,6 +204,13 @@ v8::Local<v8::Value> V8ValueConverter::ToV8Object(
|
|||
return result.GetHandle();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> V8ValueConverter::ToArrayBuffer(
|
||||
v8::Isolate* isolate, const base::BinaryValue* value) const {
|
||||
return node::Buffer::Copy(isolate,
|
||||
value->GetBuffer(),
|
||||
value->GetSize()).ToLocalChecked();
|
||||
}
|
||||
|
||||
base::Value* V8ValueConverter::FromV8ValueImpl(
|
||||
FromV8ValueState* state,
|
||||
v8::Local<v8::Value> val,
|
||||
|
|
|
@ -41,6 +41,9 @@ class V8ValueConverter {
|
|||
v8::Local<v8::Value> ToV8Object(
|
||||
v8::Isolate* isolate,
|
||||
const base::DictionaryValue* dictionary) const;
|
||||
v8::Local<v8::Value> ToArrayBuffer(
|
||||
v8::Isolate* isolate,
|
||||
const base::BinaryValue* value) const;
|
||||
|
||||
base::Value* FromV8ValueImpl(FromV8ValueState* state,
|
||||
v8::Local<v8::Value> value,
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "atom/common/node_includes.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/base_paths.h"
|
||||
#include "base/environment.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "base/path_service.h"
|
||||
|
@ -49,6 +50,7 @@ REFERENCE_MODULE(atom_browser_window);
|
|||
REFERENCE_MODULE(atom_common_asar);
|
||||
REFERENCE_MODULE(atom_common_clipboard);
|
||||
REFERENCE_MODULE(atom_common_crash_reporter);
|
||||
REFERENCE_MODULE(atom_common_id_weak_map);
|
||||
REFERENCE_MODULE(atom_common_native_image);
|
||||
REFERENCE_MODULE(atom_common_screen);
|
||||
REFERENCE_MODULE(atom_common_shell);
|
||||
|
@ -141,6 +143,14 @@ void NodeBindings::Initialize() {
|
|||
// Init node.
|
||||
// (we assume node::Init would not modify the parameters under embedded mode).
|
||||
node::Init(nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// uv_init overrides error mode to suppress the default crash dialog, bring
|
||||
// it back if user wants to show it.
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (env->HasVar("ELECTRON_DEFAULT_ERROR_MODE"))
|
||||
SetErrorMode(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
node::Environment* NodeBindings::CreateEnvironment(
|
||||
|
@ -218,7 +228,7 @@ void NodeBindings::UvRunOnce() {
|
|||
|
||||
// Perform microtask checkpoint after running JavaScript.
|
||||
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
|
||||
is_browser_ ? nullptr : new blink::WebScopedRunV8Script(env->isolate()));
|
||||
is_browser_ ? nullptr : new blink::WebScopedRunV8Script);
|
||||
|
||||
// Deal with uv events.
|
||||
int r = uv_run(uv_loop_, UV_RUN_NOWAIT);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace switches {
|
||||
namespace options {
|
||||
|
||||
const char kTitle[] = "title";
|
||||
const char kIcon[] = "icon";
|
||||
|
@ -17,51 +17,89 @@ const char kX[] = "x";
|
|||
const char kY[] = "y";
|
||||
const char kWidth[] = "width";
|
||||
const char kHeight[] = "height";
|
||||
const char kMinWidth[] = "min-width";
|
||||
const char kMinHeight[] = "min-height";
|
||||
const char kMaxWidth[] = "max-width";
|
||||
const char kMaxHeight[] = "max-height";
|
||||
const char kMinWidth[] = "minWidth";
|
||||
const char kMinHeight[] = "minHeight";
|
||||
const char kMaxWidth[] = "maxWidth";
|
||||
const char kMaxHeight[] = "maxHeight";
|
||||
const char kResizable[] = "resizable";
|
||||
const char kFullscreen[] = "fullscreen";
|
||||
|
||||
// Whether the window should show in taskbar.
|
||||
const char kSkipTaskbar[] = "skip-taskbar";
|
||||
const char kSkipTaskbar[] = "skipTaskbar";
|
||||
|
||||
// Start with the kiosk mode, see Opera's page for description:
|
||||
// http://www.opera.com/support/mastering/kiosk/
|
||||
const char kKiosk[] = "kiosk";
|
||||
|
||||
// Make windows stays on the top of all other windows.
|
||||
const char kAlwaysOnTop[] = "always-on-top";
|
||||
|
||||
const char kNodeIntegration[] = "node-integration";
|
||||
const char kAlwaysOnTop[] = "alwaysOnTop";
|
||||
|
||||
// Enable the NSView to accept first mouse event.
|
||||
const char kAcceptFirstMouse[] = "accept-first-mouse";
|
||||
const char kAcceptFirstMouse[] = "acceptFirstMouse";
|
||||
|
||||
// Whether window size should include window frame.
|
||||
const char kUseContentSize[] = "use-content-size";
|
||||
const char kUseContentSize[] = "useContentSize";
|
||||
|
||||
// The requested title bar style for the window
|
||||
const char kTitleBarStyle[] = "title-bar-style";
|
||||
|
||||
// The WebPreferences.
|
||||
const char kWebPreferences[] = "web-preferences";
|
||||
|
||||
// The factor of which page should be zoomed.
|
||||
const char kZoomFactor[] = "zoom-factor";
|
||||
const char kTitleBarStyle[] = "titleBarStyle";
|
||||
|
||||
// The menu bar is hidden unless "Alt" is pressed.
|
||||
const char kAutoHideMenuBar[] = "auto-hide-menu-bar";
|
||||
const char kAutoHideMenuBar[] = "autoHideMenuBar";
|
||||
|
||||
// Enable window to be resized larger than screen.
|
||||
const char kEnableLargerThanScreen[] = "enable-larger-than-screen";
|
||||
const char kEnableLargerThanScreen[] = "enableLargerThanScreen";
|
||||
|
||||
// Forces to use dark theme on Linux.
|
||||
const char kDarkTheme[] = "dark-theme";
|
||||
const char kDarkTheme[] = "darkTheme";
|
||||
|
||||
// Whether the window should be transparent.
|
||||
const char kTransparent[] = "transparent";
|
||||
|
||||
// Window type hint.
|
||||
const char kType[] = "type";
|
||||
|
||||
// Disable auto-hiding cursor.
|
||||
const char kDisableAutoHideCursor[] = "disableAutoHideCursor";
|
||||
|
||||
// Use the OS X's standard window instead of the textured window.
|
||||
const char kStandardWindow[] = "standardWindow";
|
||||
|
||||
// Default browser window background color.
|
||||
const char kBackgroundColor[] = "backgroundColor";
|
||||
|
||||
// The WebPreferences.
|
||||
const char kWebPreferences[] = "webPreferences";
|
||||
|
||||
// The factor of which page should be zoomed.
|
||||
const char kZoomFactor[] = "zoomFactor";
|
||||
|
||||
// Script that will be loaded by guest WebContents before other scripts.
|
||||
const char kPreloadScript[] = "preload";
|
||||
|
||||
// Like --preload, but the passed argument is an URL.
|
||||
const char kPreloadURL[] = "preloadURL";
|
||||
|
||||
// Enable the node integration.
|
||||
const char kNodeIntegration[] = "nodeIntegration";
|
||||
|
||||
// Instancd ID of guest WebContents.
|
||||
const char kGuestInstanceID[] = "guestInstanceId";
|
||||
|
||||
// Set page visiblity to always visible.
|
||||
const char kPageVisibility[] = "pageVisibility";
|
||||
|
||||
// Enable DirectWrite on Windows.
|
||||
const char kDirectWrite[] = "direct-write";
|
||||
const char kDirectWrite[] = "directWrite";
|
||||
|
||||
// Web runtime features.
|
||||
const char kExperimentalFeatures[] = "experimentalFeatures";
|
||||
const char kExperimentalCanvasFeatures[] = "experimentalCanvasFeatures";
|
||||
const char kOverlayScrollbars[] = "overlayScrollbars";
|
||||
const char kSharedWorker[] = "sharedWorker";
|
||||
|
||||
} // namespace options
|
||||
|
||||
namespace switches {
|
||||
|
||||
// Enable plugins.
|
||||
const char kEnablePlugins[] = "enable-plugins";
|
||||
|
@ -72,41 +110,9 @@ const char kPpapiFlashPath[] = "ppapi-flash-path";
|
|||
// Ppapi Flash version.
|
||||
const char kPpapiFlashVersion[] = "ppapi-flash-version";
|
||||
|
||||
// Instancd ID of guest WebContents.
|
||||
const char kGuestInstanceID[] = "guest-instance-id";
|
||||
|
||||
// Script that will be loaded by guest WebContents before other scripts.
|
||||
const char kPreloadScript[] = "preload";
|
||||
|
||||
// Like --preload, but the passed argument is an URL.
|
||||
const char kPreloadUrl[] = "preload-url";
|
||||
|
||||
// Whether the window should be transparent.
|
||||
const char kTransparent[] = "transparent";
|
||||
|
||||
// Window type hint.
|
||||
const char kType[] = "type";
|
||||
|
||||
// Disable auto-hiding cursor.
|
||||
const char kDisableAutoHideCursor[] = "disable-auto-hide-cursor";
|
||||
|
||||
// Use the OS X's standard window instead of the textured window.
|
||||
const char kStandardWindow[] = "standard-window";
|
||||
|
||||
// Path to client certificate.
|
||||
const char kClientCertificate[] = "client-certificate";
|
||||
|
||||
// Web runtime features.
|
||||
const char kExperimentalFeatures[] = "experimental-features";
|
||||
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
||||
const char kSubpixelFontScaling[] = "subpixel-font-scaling";
|
||||
const char kOverlayScrollbars[] = "overlay-scrollbars";
|
||||
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
|
||||
const char kSharedWorker[] = "shared-worker";
|
||||
|
||||
// Set page visiblity to always visible.
|
||||
const char kPageVisibility[] = "page-visibility";
|
||||
|
||||
// Disable HTTP cache.
|
||||
const char kDisableHttpCache[] = "disable-http-cache";
|
||||
|
||||
|
@ -117,9 +123,24 @@ const char kRegisterStandardSchemes[] = "register-standard-schemes";
|
|||
// TLS fallback will accept.
|
||||
const char kSSLVersionFallbackMin[] = "ssl-version-fallback-min";
|
||||
|
||||
// Comma-separated list of SSL cipher suites to disable.
|
||||
const char kCipherSuiteBlacklist[] = "cipher-suite-blacklist";
|
||||
|
||||
// The browser process app model ID
|
||||
const char kAppUserModelId[] = "app-user-model-id";
|
||||
|
||||
// The command line switch versions of the options.
|
||||
const char kZoomFactor[] = "zoom-factor";
|
||||
const char kPreloadScript[] = "preload";
|
||||
const char kPreloadURL[] = "preload-url";
|
||||
const char kNodeIntegration[] = "node-integration";
|
||||
const char kGuestInstanceID[] = "guest-instance-id";
|
||||
const char kExperimentalFeatures[] = "experimental-features";
|
||||
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
||||
const char kOverlayScrollbars[] = "overlay-scrollbars";
|
||||
const char kSharedWorker[] = "shared-worker";
|
||||
const char kPageVisibility[] = "page-visiblity";
|
||||
|
||||
} // namespace switches
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace switches {
|
||||
namespace options {
|
||||
|
||||
extern const char kTitle[];
|
||||
extern const char kIcon[];
|
||||
|
@ -27,42 +27,60 @@ extern const char kFullscreen[];
|
|||
extern const char kSkipTaskbar[];
|
||||
extern const char kKiosk[];
|
||||
extern const char kAlwaysOnTop[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kAcceptFirstMouse[];
|
||||
extern const char kUseContentSize[];
|
||||
extern const char kTitleBarStyle[];
|
||||
extern const char kWebPreferences[];
|
||||
extern const char kZoomFactor[];
|
||||
extern const char kAutoHideMenuBar[];
|
||||
extern const char kEnableLargerThanScreen[];
|
||||
extern const char kDarkTheme[];
|
||||
extern const char kDirectWrite[];
|
||||
extern const char kEnablePlugins[];
|
||||
extern const char kPpapiFlashPath[];
|
||||
extern const char kPpapiFlashVersion[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadUrl[];
|
||||
extern const char kTransparent[];
|
||||
extern const char kType[];
|
||||
extern const char kDisableAutoHideCursor[];
|
||||
extern const char kStandardWindow[];
|
||||
extern const char kClientCertificate[];
|
||||
extern const char kBackgroundColor[];
|
||||
extern const char kWebPreferences[];
|
||||
|
||||
// WebPreferences.
|
||||
extern const char kDirectWrite[];
|
||||
extern const char kZoomFactor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadURL[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kExperimentalFeatures[];
|
||||
extern const char kExperimentalCanvasFeatures[];
|
||||
extern const char kSubpixelFontScaling[];
|
||||
extern const char kOverlayScrollbars[];
|
||||
extern const char kOverlayFullscreenVideo[];
|
||||
extern const char kSharedWorker[];
|
||||
extern const char kPageVisibility[];
|
||||
|
||||
} // namespace options
|
||||
|
||||
|
||||
// Following are actually command line switches, should be moved to other files.
|
||||
|
||||
namespace switches {
|
||||
|
||||
extern const char kEnablePlugins[];
|
||||
extern const char kPpapiFlashPath[];
|
||||
extern const char kPpapiFlashVersion[];
|
||||
extern const char kClientCertificate[];
|
||||
extern const char kDisableHttpCache[];
|
||||
extern const char kRegisterStandardSchemes[];
|
||||
extern const char kSSLVersionFallbackMin[];
|
||||
|
||||
extern const char kCipherSuiteBlacklist[];
|
||||
extern const char kAppUserModelId[];
|
||||
|
||||
extern const char kZoomFactor[];
|
||||
extern const char kPreloadScript[];
|
||||
extern const char kPreloadURL[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kExperimentalFeatures[];
|
||||
extern const char kExperimentalCanvasFeatures[];
|
||||
extern const char kOverlayScrollbars[];
|
||||
extern const char kSharedWorker[];
|
||||
extern const char kPageVisibility[];
|
||||
|
||||
} // namespace switches
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -20,7 +20,7 @@ void ShowItemInFolder(const base::FilePath& full_path) {
|
|||
DCHECK([NSThread isMainThread]);
|
||||
NSString* path_string = base::SysUTF8ToNSString(full_path.value());
|
||||
if (!path_string || ![[NSWorkspace sharedWorkspace] selectFile:path_string
|
||||
inFileViewerRootedAtPath:nil])
|
||||
inFileViewerRootedAtPath:@""])
|
||||
LOG(WARNING) << "NSWorkspace failed to select file " << full_path.value();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
#include "atom/common/platform_util.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <atlbase.h>
|
||||
#include <commdlg.h>
|
||||
#include <comdef.h>
|
||||
#include <dwmapi.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
|
@ -19,6 +21,7 @@
|
|||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/win/registry.h"
|
||||
#include "base/win/scoped_co_mem.h"
|
||||
#include "base/win/scoped_com_initializer.h"
|
||||
#include "base/win/scoped_comptr.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "url/gurl.h"
|
||||
|
@ -42,11 +45,168 @@ bool ValidateShellCommandForScheme(const std::string& scheme) {
|
|||
return true;
|
||||
}
|
||||
|
||||
// Required COM implementation of IFileOperationProgressSink so we can
|
||||
// precheck files before deletion to make sure they can be move to the
|
||||
// Recycle Bin.
|
||||
class DeleteFileProgressSink : public IFileOperationProgressSink {
|
||||
public:
|
||||
DeleteFileProgressSink();
|
||||
|
||||
private:
|
||||
ULONG STDMETHODCALLTYPE AddRef(void);
|
||||
ULONG STDMETHODCALLTYPE Release(void);
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID* ppvObj);
|
||||
HRESULT STDMETHODCALLTYPE StartOperations(void);
|
||||
HRESULT STDMETHODCALLTYPE FinishOperations(HRESULT);
|
||||
HRESULT STDMETHODCALLTYPE PreRenameItem(
|
||||
DWORD, IShellItem*, LPCWSTR);
|
||||
HRESULT STDMETHODCALLTYPE PostRenameItem(
|
||||
DWORD, IShellItem*, LPCWSTR, HRESULT, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE PreMoveItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR);
|
||||
HRESULT STDMETHODCALLTYPE PostMoveItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE PreCopyItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR);
|
||||
HRESULT STDMETHODCALLTYPE PostCopyItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE PreDeleteItem(DWORD, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE PostDeleteItem(
|
||||
DWORD, IShellItem*, HRESULT, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE PreNewItem(
|
||||
DWORD, IShellItem*, LPCWSTR);
|
||||
HRESULT STDMETHODCALLTYPE PostNewItem(
|
||||
DWORD, IShellItem*, LPCWSTR, LPCWSTR, DWORD, HRESULT, IShellItem*);
|
||||
HRESULT STDMETHODCALLTYPE UpdateProgress(UINT, UINT);
|
||||
HRESULT STDMETHODCALLTYPE ResetTimer(void);
|
||||
HRESULT STDMETHODCALLTYPE PauseTimer(void);
|
||||
HRESULT STDMETHODCALLTYPE ResumeTimer(void);
|
||||
|
||||
ULONG m_cRef;
|
||||
};
|
||||
|
||||
DeleteFileProgressSink::DeleteFileProgressSink() {
|
||||
m_cRef = 0;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PreDeleteItem(DWORD dwFlags, IShellItem*) {
|
||||
if (!(dwFlags & TSF_DELETE_RECYCLE_IF_POSSIBLE)) {
|
||||
// TSF_DELETE_RECYCLE_IF_POSSIBLE will not be set for items that cannot be
|
||||
// recycled. In this case, we abort the delete operation. This bubbles
|
||||
// up and stops the Delete in IFileOperation.
|
||||
return E_ABORT;
|
||||
}
|
||||
// Returns S_OK if successful, or an error value otherwise. In the case of an
|
||||
// error value, the delete operation and all subsequent operations pending
|
||||
// from the call to IFileOperation are canceled.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::QueryInterface(REFIID riid, LPVOID* ppvObj) {
|
||||
// Always set out parameter to NULL, validating it first.
|
||||
if (!ppvObj)
|
||||
return E_INVALIDARG;
|
||||
*ppvObj = nullptr;
|
||||
if (riid == IID_IUnknown || riid == IID_IFileOperationProgressSink) {
|
||||
// Increment the reference count and return the pointer.
|
||||
*ppvObj = reinterpret_cast<IUnknown*>(this);
|
||||
AddRef();
|
||||
return NOERROR;
|
||||
}
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
ULONG DeleteFileProgressSink::AddRef() {
|
||||
InterlockedIncrement(&m_cRef);
|
||||
return m_cRef;
|
||||
}
|
||||
|
||||
ULONG DeleteFileProgressSink::Release() {
|
||||
// Decrement the object's internal counter.
|
||||
ULONG ulRefCount = InterlockedDecrement(&m_cRef);
|
||||
if (0 == m_cRef) {
|
||||
delete this;
|
||||
}
|
||||
return ulRefCount;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::StartOperations() {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::FinishOperations(HRESULT) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PreRenameItem(DWORD, IShellItem*, LPCWSTR) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PostRenameItem(
|
||||
DWORD, IShellItem*, __RPC__in_string LPCWSTR, HRESULT, IShellItem*) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PreMoveItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PostMoveItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PreCopyItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PostCopyItem(
|
||||
DWORD, IShellItem*, IShellItem*, LPCWSTR, HRESULT, IShellItem*) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PostDeleteItem(
|
||||
DWORD, IShellItem*, HRESULT, IShellItem*) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PreNewItem(
|
||||
DWORD dwFlags, IShellItem*, LPCWSTR) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PostNewItem(
|
||||
DWORD, IShellItem*, LPCWSTR, LPCWSTR, DWORD, HRESULT, IShellItem*) {
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::UpdateProgress(UINT, UINT) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::ResetTimer() {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::PauseTimer() {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT DeleteFileProgressSink::ResumeTimer() {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace platform_util {
|
||||
|
||||
void ShowItemInFolder(const base::FilePath& full_path) {
|
||||
base::win::ScopedCOMInitializer com_initializer;
|
||||
if (!com_initializer.succeeded())
|
||||
return;
|
||||
|
||||
base::FilePath dir = full_path.DirName().AsEndingWithSeparator();
|
||||
// ParseDisplayName will fail if the directory is "C:", it must be "C:\\".
|
||||
if (dir.empty())
|
||||
|
@ -147,8 +307,8 @@ bool OpenExternal(const GURL& url) {
|
|||
// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
|
||||
// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
|
||||
// support URLS of 2083 chars in length, 2K is safe."
|
||||
const size_t kMaxUrlLength = 2048;
|
||||
if (escaped_url.length() > kMaxUrlLength) {
|
||||
const size_t kMaxURLLength = 2048;
|
||||
if (escaped_url.length() > kMaxURLLength) {
|
||||
NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
@ -170,32 +330,40 @@ bool OpenExternal(const GURL& url) {
|
|||
}
|
||||
|
||||
bool MoveItemToTrash(const base::FilePath& path) {
|
||||
// SHFILEOPSTRUCT wants the path to be terminated with two NULLs,
|
||||
// so we have to use wcscpy because wcscpy_s writes non-NULLs
|
||||
// into the rest of the buffer.
|
||||
wchar_t double_terminated_path[MAX_PATH + 1] = {0};
|
||||
#pragma warning(suppress:4996) // don't complain about wcscpy deprecation
|
||||
wcscpy(double_terminated_path, path.value().c_str());
|
||||
|
||||
SHFILEOPSTRUCT file_operation = {0};
|
||||
file_operation.wFunc = FO_DELETE;
|
||||
file_operation.pFrom = double_terminated_path;
|
||||
file_operation.fFlags = FOF_ALLOWUNDO | FOF_SILENT | FOF_NOCONFIRMATION;
|
||||
int err = SHFileOperation(&file_operation);
|
||||
|
||||
// Since we're passing flags to the operation telling it to be silent,
|
||||
// it's possible for the operation to be aborted/cancelled without err
|
||||
// being set (although MSDN doesn't give any scenarios for how this can
|
||||
// happen). See MSDN for SHFileOperation and SHFILEOPTSTRUCT.
|
||||
if (file_operation.fAnyOperationsAborted)
|
||||
base::win::ScopedCOMInitializer com_initializer;
|
||||
if (!com_initializer.succeeded())
|
||||
return false;
|
||||
|
||||
// Some versions of Windows return ERROR_FILE_NOT_FOUND (0x2) when deleting
|
||||
// an empty directory and some return 0x402 when they should be returning
|
||||
// ERROR_FILE_NOT_FOUND. MSDN says Vista and up won't return 0x402. Windows 7
|
||||
// can return DE_INVALIDFILES (0x7C) for nonexistent directories.
|
||||
return (err == 0 || err == ERROR_FILE_NOT_FOUND || err == 0x402 ||
|
||||
err == 0x7C);
|
||||
base::win::ScopedComPtr<IFileOperation> pfo;
|
||||
if (FAILED(pfo.CreateInstance(CLSID_FileOperation)))
|
||||
return false;
|
||||
|
||||
// Elevation prompt enabled for UAC protected files. This overrides the
|
||||
// SILENT, NO_UI and NOERRORUI flags.
|
||||
if (FAILED(pfo->SetOperationFlags(FOF_NO_UI |
|
||||
FOF_ALLOWUNDO |
|
||||
FOF_NOERRORUI |
|
||||
FOF_SILENT |
|
||||
FOFX_SHOWELEVATIONPROMPT |
|
||||
FOFX_RECYCLEONDELETE)))
|
||||
return false;
|
||||
|
||||
// Create an IShellItem from the supplied source path.
|
||||
base::win::ScopedComPtr<IShellItem> delete_item;
|
||||
if (FAILED(SHCreateItemFromParsingName(path.value().c_str(),
|
||||
NULL,
|
||||
IID_PPV_ARGS(delete_item.Receive()))))
|
||||
return false;
|
||||
|
||||
base::win::ScopedComPtr<IFileOperationProgressSink> delete_sink(
|
||||
new DeleteFileProgressSink);
|
||||
if (!delete_sink)
|
||||
return false;
|
||||
|
||||
// Processes the queued command DeleteItem. This will trigger
|
||||
// the DeleteFileProgressSink to check for Recycle Bin.
|
||||
return SUCCEEDED(pfo->DeleteItem(delete_item.get(), delete_sink.get())) &&
|
||||
SUCCEEDED(pfo->PerformOperations());
|
||||
}
|
||||
|
||||
void Beep() {
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${PRODUCT_NAME} Framework</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>${ATOM_BUNDLE_ID}</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${PRODUCT_NAME} Framework</string>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue