Merge remote-tracking branch 'refs/remotes/atom/master'

This commit is contained in:
Plusb Preco 2015-11-04 17:47:03 +09:00
commit 526b2083c4
45 changed files with 671 additions and 96 deletions

View file

@ -20,7 +20,7 @@ unacceptable behavior to atom@github.com.
## Downloads
Prebuilt binaries and debug symbols of Electron for Linux, Windows and Mac can
Prebuilt binaries and debug symbols of Electron for Linux, Windows and OS X can
be found on the [releases](https://github.com/atom/electron/releases) page.
You can also use [`npm`](https://docs.npmjs.com/) to install prebuilt electron

View file

@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.34.1',
'version%': '0.34.2',
},
'includes': [
'filenames.gypi',

View file

@ -7,10 +7,6 @@
#include <string>
#include <vector>
#if defined(OS_WIN)
#include <shlobj.h>
#endif
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/api/atom_api_web_contents.h"
@ -19,7 +15,7 @@
#include "atom/browser/browser.h"
#include "atom/browser/login_handler.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/node_includes.h"
#include "atom/common/options_switches.h"
@ -299,13 +295,6 @@ void App::SetDesktopName(const std::string& desktop_name) {
#endif
}
void App::SetAppUserModelId(const std::string& app_id) {
#if defined(OS_WIN)
base::string16 app_id_utf16 = base::UTF8ToUTF16(app_id);
SetCurrentProcessExplicitAppUserModelID(app_id_utf16.c_str());
#endif
}
void App::AllowNTLMCredentialsForAllDomains(bool should_allow) {
auto browser_context = static_cast<AtomBrowserContext*>(
AtomBrowserMainParts::Get()->browser_context());
@ -360,6 +349,8 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
base::Bind(&Browser::AddRecentDocument, browser))
.SetMethod("clearRecentDocuments",
base::Bind(&Browser::ClearRecentDocuments, browser))
.SetMethod("setAppUserModelId",
base::Bind(&Browser::SetAppUserModelID, browser))
#if defined(OS_WIN)
.SetMethod("setUserTasks",
base::Bind(&Browser::SetUserTasks, browser))
@ -367,7 +358,6 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
.SetMethod("setPath", &App::SetPath)
.SetMethod("getPath", &App::GetPath)
.SetMethod("setDesktopName", &App::SetDesktopName)
.SetMethod("setAppUserModelId", &App::SetAppUserModelId)
.SetMethod("allowNTLMCredentialsForAllDomains",
&App::AllowNTLMCredentialsForAllDomains)
.SetMethod("getLocale", &App::GetLocale)

View file

@ -67,7 +67,6 @@ class App : public mate::EventEmitter,
const base::FilePath& path);
void SetDesktopName(const std::string& desktop_name);
void SetAppUserModelId(const std::string& app_id);
void AllowNTLMCredentialsForAllDomains(bool should_allow);
bool MakeSingleInstance(
const ProcessSingleton::NotificationCallback& callback);

View file

@ -12,7 +12,7 @@
#include "atom/browser/net/url_request_fetch_job.h"
#include "atom/browser/net/url_request_string_job.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/node_includes.h"
#include "native_mate/dictionary.h"

View file

@ -18,6 +18,7 @@
#include "atom/common/api/event_emitter_caller.h"
#include "atom/common/native_mate_converters/blink_converter.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/content_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
@ -46,6 +47,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/context_menu_params.h"
#include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "net/http/http_response_headers.h"
@ -169,11 +171,12 @@ struct Converter<content::SavePageType> {
std::string save_type;
if (!ConvertFromV8(isolate, val, &save_type))
return false;
if (save_type == "HTMLOnly") {
save_type = base::StringToLowerASCII(save_type);
if (save_type == "htmlonly") {
*out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
} else if (save_type == "HTMLComplete") {
} else if (save_type == "htmlcomplete") {
*out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
} else if (save_type == "MHTML") {
} else if (save_type == "mhtml") {
*out = content::SAVE_PAGE_TYPE_AS_MHTML;
} else {
return false;
@ -404,6 +407,15 @@ void WebContents::RendererResponsive(content::WebContents* source) {
owner_window()->RendererResponsive(source);
}
bool WebContents::HandleContextMenu(const content::ContextMenuParams& params) {
if (!params.custom_context.is_pepper_menu)
return false;
Emit("pepper-context-menu", std::make_pair(params, web_contents()));
web_contents()->NotifyContextMenuClosed(params.custom_context);
return true;
}
void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) {
// Do nothing, we override this method just to avoid compilation error since
// there are two virtual functions named BeforeUnloadFired.

View file

@ -189,6 +189,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
void ExitFullscreenModeForTab(content::WebContents* source) override;
void RendererUnresponsive(content::WebContents* source) override;
void RendererResponsive(content::WebContents* source) override;
bool HandleContextMenu(const content::ContextMenuParams& params) override;
// content::WebContentsObserver:
void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;

View file

@ -1,4 +1,5 @@
EventEmitter = require('events').EventEmitter
Menu = require './menu'
NavigationController = require './navigation-controller'
binding = process.atomBinding 'web_contents'
ipc = require 'ipc'
@ -65,6 +66,11 @@ wrapWebContents = (webContents) ->
Object.defineProperty event, 'returnValue', set: (value) -> event.sendReply JSON.stringify(value)
ipc.emit channel, event, args...
# Handle context menu action request from pepper plugin.
webContents.on 'pepper-context-menu', (event, params) ->
menu = Menu.buildFromTemplate params.menu
menu.popup params.x, params.y
webContents.printToPDF = (options, callback) ->
printingSetting =
pageRage: []

View file

@ -89,10 +89,6 @@ std::string Browser::GetName() const {
void Browser::SetName(const std::string& name) {
name_override_ = name;
#if defined(OS_WIN)
SetAppUserModelID(name);
#endif
}
bool Browser::OpenFile(const std::string& file_path) {

View file

@ -11,12 +11,12 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "atom/browser/browser_observer.h"
#include "atom/browser/window_list_observer.h"
#if defined(OS_WIN)
#include "base/files/file_path.h"
#include "base/strings/string16.h"
#endif
namespace base {
@ -66,6 +66,9 @@ class Browser : public WindowListObserver {
// Clear the recent documents list.
void ClearRecentDocuments();
// Set the application user model ID.
void SetAppUserModelID(const base::string16& name);
#if defined(OS_MACOSX)
// Bounce the dock icon.
enum BounceType {
@ -100,8 +103,10 @@ class Browser : public WindowListObserver {
// Add a custom task to jump list.
void SetUserTasks(const std::vector<UserTask>& tasks);
// Set the application user model ID, called when "SetName" is called.
void SetAppUserModelID(const std::string& name);
// Returns the application user model ID, if there isn't one, then create
// one from app's name.
// The returned string managed by Browser, and should not be modified.
PCWSTR GetAppUserModelID();
#endif
// Tell the application to open a file.

View file

@ -31,6 +31,9 @@ void Browser::AddRecentDocument(const base::FilePath& path) {
void Browser::ClearRecentDocuments() {
}
void Browser::SetAppUserModelID(const base::string16& name) {
}
std::string Browser::GetExecutableFileVersion() const {
return brightray::GetApplicationVersion();
}

View file

@ -26,6 +26,9 @@ void Browser::AddRecentDocument(const base::FilePath& path) {
void Browser::ClearRecentDocuments() {
}
void Browser::SetAppUserModelID(const base::string16& name) {
}
std::string Browser::GetExecutableFileVersion() const {
return brightray::GetApplicationVersion();
}

View file

@ -15,6 +15,7 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/win_util.h"
@ -25,6 +26,8 @@ namespace atom {
namespace {
const wchar_t kAppUserModelIDFormat[] = L"electron.app.$1";
BOOL CALLBACK WindowsEnumerationHandler(HWND hwnd, LPARAM param) {
DWORD target_process_id = *reinterpret_cast<DWORD*>(param);
DWORD process_id = 0;
@ -56,7 +59,7 @@ void Browser::AddRecentDocument(const base::FilePath& path) {
if (SUCCEEDED(hr)) {
SHARDAPPIDINFO info;
info.psi = item;
info.pszAppID = app_user_model_id_.c_str();
info.pszAppID = GetAppUserModelID();
SHAddToRecentDocs(SHARD_APPIDINFO, &info);
}
}
@ -66,16 +69,21 @@ void Browser::ClearRecentDocuments() {
if (FAILED(destinations.CoCreateInstance(CLSID_ApplicationDestinations,
NULL, CLSCTX_INPROC_SERVER)))
return;
if (FAILED(destinations->SetAppID(app_user_model_id_.c_str())))
if (FAILED(destinations->SetAppID(GetAppUserModelID())))
return;
destinations->RemoveAllDestinations();
}
void Browser::SetAppUserModelID(const base::string16& name) {
app_user_model_id_ = name;
SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str());
}
void Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
CComPtr<ICustomDestinationList> destinations;
if (FAILED(destinations.CoCreateInstance(CLSID_DestinationList)))
return;
if (FAILED(destinations->SetAppID(app_user_model_id_.c_str())))
if (FAILED(destinations->SetAppID(GetAppUserModelID())))
return;
// Start a transaction that updates the JumpList of this application.
@ -117,10 +125,13 @@ void Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
destinations->CommitList();
}
void Browser::SetAppUserModelID(const std::string& name) {
app_user_model_id_ = base::string16(L"electron.app.");
app_user_model_id_ += base::UTF8ToUTF16(name);
SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str());
PCWSTR Browser::GetAppUserModelID() {
if (app_user_model_id_.empty()) {
SetAppUserModelID(ReplaceStringPlaceholders(
kAppUserModelIDFormat, base::UTF8ToUTF16(GetName()), nullptr));
}
return app_user_model_id_.c_str();
}
std::string Browser::GetExecutableFileVersion() const {

View file

@ -2,6 +2,7 @@ ipc = require 'ipc'
path = require 'path'
objectsRegistry = require './objects-registry.js'
v8Util = process.atomBinding 'v8_util'
IDWeakMap = process.atomBinding('id_weak_map').IDWeakMap
# Convert a real value into meta data.
valueToMeta = (sender, value, optimizeSimpleObject=false) ->
@ -32,14 +33,13 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
# it.
meta.id = objectsRegistry.add sender.getId(), value
meta.members = []
meta.members.push {name: prop, type: typeof field} for prop, field of value
meta.members = ({name, type: typeof field} for name, field of value)
else if meta.type is 'buffer'
meta.value = Array::slice.call value, 0
else if meta.type is 'promise'
meta.then = valueToMeta(sender, value.then.bind(value))
meta.then = valueToMeta sender, value.then.bind(value)
else if meta.type is 'error'
meta.message = value.message
meta.members = plainObjectToMeta value
else if meta.type is 'date'
meta.value = value.getTime()
else
@ -48,6 +48,10 @@ valueToMeta = (sender, value, optimizeSimpleObject=false) ->
meta
# Convert object to meta by value.
plainObjectToMeta = (obj) ->
Object.getOwnPropertyNames(obj).map (name) -> {name, value: obj[name]}
# Convert Error into meta data.
exceptionToMeta = (error) ->
type: 'exception', message: error.message, stack: (error.stack || error)
@ -70,6 +74,13 @@ unwrapArgs = (sender, args) ->
returnValue = metaToValue meta.value
-> returnValue
when 'function'
# Cache the callbacks in renderer.
unless sender.callbacks
sender.callbacks = new IDWeakMap
sender.on 'render-view-deleted', ->
sender.callbacks.clear()
return sender.callbacks.get meta.id if sender.callbacks.has meta.id
rendererReleased = false
objectsRegistry.once "clear-#{sender.getId()}", ->
rendererReleased = true
@ -77,11 +88,13 @@ unwrapArgs = (sender, args) ->
ret = ->
if rendererReleased
throw new Error("Attempting to call a function in a renderer window
that has been closed or released. Function provided here: #{meta.id}.")
that has been closed or released. Function provided here: #{meta.location}.")
sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
v8Util.setDestructor ret, ->
return if rendererReleased
sender.callbacks.remove meta.id
sender.send 'ATOM_RENDERER_RELEASE_CALLBACK', meta.id
sender.callbacks.set meta.id, ret
ret
else throw new TypeError("Unknown type: #{meta.type}")

View file

@ -17,9 +17,9 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.34.1</string>
<string>0.34.2</string>
<key>CFBundleShortVersionString</key>
<string>0.34.1</string>
<string>0.34.2</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>

View file

@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 0,34,1,0
PRODUCTVERSION 0,34,1,0
FILEVERSION 0,34,2,0
PRODUCTVERSION 0,34,2,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -74,12 +74,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "GitHub, Inc."
VALUE "FileDescription", "Electron"
VALUE "FileVersion", "0.34.1"
VALUE "FileVersion", "0.34.2"
VALUE "InternalName", "electron.exe"
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
VALUE "OriginalFilename", "electron.exe"
VALUE "ProductName", "Electron"
VALUE "ProductVersion", "0.34.1"
VALUE "ProductVersion", "0.34.2"
VALUE "SquirrelAwareVersion", "1"
END
END

View file

@ -0,0 +1,79 @@
// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#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)

View 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_

View file

@ -1,3 +1,5 @@
v8Util = process.atomBinding 'v8_util'
module.exports =
class CallbacksRegistry
constructor: ->
@ -5,6 +7,10 @@ class CallbacksRegistry
@callbacks = {}
add: (callback) ->
# 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,
@ -17,10 +23,11 @@ class CallbacksRegistry
continue if location.indexOf('(native)') isnt -1
continue if location.indexOf('atom.asar') isnt -1
[x, filenameAndLine] = /([^/^\)]*)\)?$/gi.exec(location)
id = "#{filenameAndLine} (#{id})"
break
@callbacks[id] = callback
v8Util.setHiddenValue callback, 'callbackId', id
v8Util.setHiddenValue callback, 'location', filenameAndLine
id
get: (id) ->

View file

@ -7,7 +7,7 @@
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 34
#define ATOM_PATCH_VERSION 1
#define ATOM_PATCH_VERSION 2
#define ATOM_VERSION_IS_RELEASE 1

View file

@ -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;
}

View file

@ -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);

View file

@ -254,7 +254,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

View file

@ -4,30 +4,96 @@
#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"
#include "net/url_request/url_request.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<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);
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<const net::AuthChallengeInfo*>::ToV8(
v8::Isolate* isolate, const net::AuthChallengeInfo* val) {
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("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);
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);
}

View file

@ -5,25 +5,31 @@
#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 net {
class AuthChallengeInfo;
class URLRequest;
namespace content {
struct ContextMenuParams;
class WebContents;
}
using ContextMenuParamsWithWebContents =
std::pair<content::ContextMenuParams, content::WebContents*>;
namespace mate {
template<>
struct Converter<const net::URLRequest*> {
struct Converter<content::MenuItem::Type> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::URLRequest* val);
const content::MenuItem::Type& val);
};
template<>
struct Converter<const net::AuthChallengeInfo*> {
struct Converter<ContextMenuParamsWithWebContents> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const net::AuthChallengeInfo* val);
const ContextMenuParamsWithWebContents& val);
};
} // namespace mate

View file

@ -0,0 +1,34 @@
// 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 "native_mate/dictionary.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);
}
} // namespace mate

View file

@ -0,0 +1,31 @@
// 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 "native_mate/converter.h"
namespace net {
class AuthChallengeInfo;
class URLRequest;
}
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);
};
} // namespace mate
#endif // ATOM_COMMON_NATIVE_MATE_CONVERTERS_NET_CONVERTER_H_

View file

@ -48,6 +48,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);

View file

@ -33,7 +33,7 @@ wrapArgs = (args, visited=[]) ->
else if typeof value is 'function' and v8Util.getHiddenValue value, 'returnValue'
type: 'function-with-return-value', value: valueToMeta(value())
else if typeof value is 'function'
type: 'function', id: callbacksRegistry.add(value)
type: 'function', id: callbacksRegistry.add(value), location: v8Util.getHiddenValue value, 'location'
else
type: 'value', value: value
@ -46,7 +46,7 @@ metaToValue = (meta) ->
when 'array' then (metaToValue(el) for el in meta.members)
when 'buffer' then new Buffer(meta.value)
when 'promise' then Promise.resolve(then: metaToValue(meta.then))
when 'error' then new Error(meta.message)
when 'error' then metaToPlainObject meta
when 'date' then new Date(meta.value)
when 'exception'
throw new Error("#{meta.message}\n#{meta.stack}")
@ -110,6 +110,14 @@ metaToValue = (meta) ->
ret
# Construct a plain object from the meta.
metaToPlainObject = (meta) ->
obj = switch meta.type
when 'error' then new Error
else {}
obj[name] = value for {name, value} in meta.members
obj
# Browser calls a callback in renderer.
ipc.on 'ATOM_RENDERER_CALLBACK', (id, args) ->
callbacksRegistry.apply id, metaToValue(args)

View file

@ -63,9 +63,9 @@
* [Guía de Estilo](development/coding-style.md)
* [Estructura de los directorios del Código Fuente](development/source-code-directory-structure.md)
* [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](../../development/atom-shell-vs-node-webkit.md)
* [Repaso del Sistema de Compilación](../../development/build-system-overview.md)
* [Instrucciones de Compilación (Mac)](../../development/build-instructions-osx.md)
* [Diferencias Técnicas con NW.js (anteriormente conocido como node-webkit)](development/atom-shell-vs-node-webkit.md)
* [Repaso del Sistema de Compilación](development/build-system-overview.md)
* [Instrucciones de Compilación (Mac)](development/build-instructions-osx.md)
* [Instrucciones de Compilación (Windows)](../../development/build-instructions-windows.md)
* [Instrucciones de Compilación (Linux)](../../development/build-instructions-linux.md)
* [Instrucciones de Compilación (Linux)](development/build-instructions-linux.md)
* [Configurando un Servidor de Símbolos en el depurador](../../development/setting-up-symbol-server.md)

View file

@ -0,0 +1,34 @@
#Diferencias Técnicas entre Electron y NW.js (anteriormente conocido como node-webkit)
**Nota:Electron se llamaba antes Atom Shell.**
Como NW.js, Electron proporciona una plataforma para escribir aplicaciones de escritorio con JavaScript y HTML y tiene la integración de nodo para permitir el acceso al sistema de bajo nivel de las páginas web.
Pero también hay diferencias fundamentales entre los dos proyectos que hacen a Electron un producto totalmente independiente de NW.js:
**1. Ingreso a la aplicación**
En NW.js el principal punto de ingreso de una aplicación es una página web. Usted especifica una página principal de URL en el `package.json` y se abre en una ventana del navegador como ventana principal de la aplicación.
En Electron, el punto de ingreso es un script de JavaScript. En lugar de proporcionar una dirección URL directamente, usted crea manualmente una ventana del navegador y carga un archivo HTML utilizando la API. También es necesario escuchar a los eventos de la ventana para decidir cuándo salir de la aplicación.
Electron funciona más como el tiempo de ejecución(Runtime) de Node.js. Las Api's de Electron son de bajo nivel asi que puede usarlo para las pruebas del navegador en lugar de usar [PhantomJS.](http://phantomjs.org/)
**2.Construir un sistema**
Con el fin de evitar la complejidad de la construcción de todo Chromium, Electron utiliza `libchromiumcontent` para acceder a al contenido Chromium's API. `libchromiumcontent` es solo una liberia compartida que incluye el módulo de contenido de Chromium y todas sus dependencias. Los usuarios no necesitan una máquina potente para construir con Electron.
**3.Integración de Node**
In NW.js, the Node integration in web pages requires patching Chromium to work, while in Electron we chose a different way to integrate the libuv loop with each platform's message loop to avoid hacking Chromium. See the node_bindings code for how that was done.
En NW.js, la integración de Node en las páginas web requiere parchear Chromium para que funcione, mientras que en Electron elegimos una manera diferente para integrar el cilco libuv con cada ciclo de mensaje de las plataformas para evitar el hacking en Chromium. Ver el código `node_bindings` de cómo se hizo.
**4. Multi-contexto**
Si usted es un usuario experimentado NW.js, usted debe estar familiarizado con el concepto de contexto Node y el contexto web. Estos conceptos fueron inventados debido a la forma cómo se implementó NW.js.
Mediante el uso de la característica [multi-contexto](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/) de Node, Electron no introduce un nuevo contexto JavaScript en páginas web.Resultados de búsqueda

View file

@ -0,0 +1,96 @@
#Instrucciones de Compilación (Linux)
Siga las siguientes pautas para la construcción de Electron en Linux.
#Requisitos previos
* Python 2.7.x. Algunas distribuciones como CentOS siguen utilizando Python 2.6.x por lo que puede que tenga que comprobar su versión de Python con `Python -V`.
* Node.js v0.12.x. Hay varias formas de instalar Node. Puede descargar el código fuente de Node.js y compilar desde las fuentes. Si lo hace, permite la instalación de Node en el directorio personal como usuario estándar. O intentar de repositorios como NodeSource.
* Clang 3.4 o mayor.
* Cabeceras de desarrollo de GTK + y libnotify.
En Ubuntu, instalar las siguientes bibliotecas:
`$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
libnotify-dev libgnome-keyring-dev libgconf2-dev \
libasound2-dev libcap-dev libcups2-dev libxtst-dev \
libxss1 libnss3-dev gcc-multilib g++-multilib`
En Fedora, instale las siguientes bibliotecas:
`$ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring-devel \
xorg-x11-server-utils libcap-devel cups-devel libXtst-devel \
alsa-lib-devel libXrandr-devel GConf2-devel nss-devel`
Otras distribuciones pueden ofrecer paquetes similares para la instalación, a través de gestores de paquetes como el pacman. O puede compilarlo a partir del código fuente.
#Si utiliza máquinas virtuales para la construcción
Si usted planea construir Electron en una máquina virtual, necesitará un dispositivo de al menos 25 gigabytes de tamaño.
#Obteniendo el codigo
`$ git clone https://github.com/atom/electron.git`
#Bootstrapping (Arranque)
The bootstrap script will download all necessary build dependencies and create the build project files. You must have Python 2.7.x for the script to succeed. Downloading certain files can take a long time. Notice that we are using ninja to build Electron so there is no Makefile generated.
El script de bootstrap descargará todas las dependencias necesarias para construcción y creara los archivos del proyecto de construcción. Debe tener Python 2.7.x para que la secuencia de comandos tenga éxito. La descarga de determinados archivos puede llevar mucho tiempo. Nótese que estamos usando`ninja` para construir Electron por lo que no hay `Makefile` generado.
$ cd electron
$ ./script/bootstrap.py -v
#compilación cruzada
Si usted quiere construir para un `arm` objetivo también debe instalar las siguientes dependencias:
`$ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \ g++-arm-linux-gnueabihf`
And to cross compile for arm or ia32 targets, you should pass the --target_arch parameter to the bootstrap.py script:
cruzar y compilar para `arm` o `ia32` objetivos, debe pasar el parámetro `--target_arch` al script `bootstrap.py`:
`$ ./script/bootstrap.py -v --target_arch=arm`
#Construcción
Si a usted le gustaría construir dos objetivos de `Release` y `Debug`:
`$ ./script/build.py`
Este script causará que el ejecutable de Electron se muy grande para ser colocado en el directorio `out / R`. El tamaño del archivo es de más de 1,3 gigabytes. Esto sucede porque el binario de destino lanzamiento contiene los símbolos de depuración. Para reducir el tamaño de archivo, ejecute el script `create-dist.py`:
`$ ./script/create-dist.py`
This will put a working distribution with much smaller file sizes in the dist directory. After running the create-dist.py script, you may want to remove the 1.3+ gigabyte binary which is still in out/R.
Esto pondrá una distribución a trabajar con tamaños de archivo mucho más pequeños en el directorio `dist`. Después de ejecutar el script create-dist.py, es posible que desee quitar el binario 1.3+ gigabyte que todavía está en `out/R`.
También se puede construir sólo el objetivo `Debug`:
`$ ./script/build.py -c D`
Después de la construcción está hecho, usted puede encontrar el `Electron` de depuración binario bajo `out / D`.
#Limpieza
Para limpiar los archivos de creación:
`$ ./script/clean.py`
#Solución de problemas
Asegúrese de que ha instalado todas las dependencias de construcción.
#Error al cargar bibliotecas compartidas: libtinfo.so.5
Prebulit clang will try to link to libtinfo.so.5. Depending on the host architecture, symlink to appropriate libncurses:
preconstruir `clang` intentará enlazar a `libtinfo.so.5`. Dependiendo de la arquitectura anfitrión, enlace simbólico apropiado a `libncurses` :
`$ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5`
#Pruebas
Pon a prueba tus cambios que ajustan al estilo de codificación proyecto mediante:
`$ ./script/cpplint.py`
prueba de funcionalidad utilizando:
`$ ./script/test.py`

View file

@ -0,0 +1,48 @@
#Instrucciones de Compilación (Mac)
Siga las siguientes pautas para la construcción de Electron en OS X.
#Requisitos previos
`OS X >= 10.8`
`Xcode >= 5.1`
`node.js (external)`
Si está utilizando Python descargado de Homebrew, también es necesario instalar los siguientes módulos de python:
`pyobjc`
#Obtener el Código
`$ git clone https://github.com/atom/electron.git`
#Bootstrapping (arranque)
The bootstrap script will download all necessary build dependencies and create the build project files. Notice that we're using ninja to build Electron so there is no Xcode project generated.
El script de bootstrap descargará todas las dependencias de construcción necesarias y creara los archivos del proyecto de compilación. notemos que estamos usando `ninja` para construir Electron por lo que no hay un proyecto de Xcode generado.
`$ cd electron`
`$ ./script/bootstrap.py -v`
#Construcción
Construir ambos objetivos de `Release` y `Debug`:
`$ ./script/build.py`
También sólo se puede construir el objetivo de `Debug`:
`$ ./script/build.py -c D`
Después de la construcción está hecho, usted puede encontrar `Electron.app` bajo `out / D.`
#Soporte de 32bit
Electron sólo puede construirse para un objetivo de 64 bits en OS X y no hay un plan para apoyar a 32 bit OS X en el futuro.
#Pruebas
Pon a prueba tus cambios ajustandose al estilo de codificación del proyecto mediante:
`$ ./script/cpplint.py`
Prueba la funcionalidad usando:
`$ ./script/test.py`

View file

@ -0,0 +1,35 @@
#Repaso del Sistema de construcción
Electron utiliza `gyp` para la generación de proyectos y` ninja` para la contrucción. Las Configuraciones del proyecto se pueden encontrar en los archivos `.gypi` y `.gyp `.
#Archivos Gyp
los siguientes archivos `gyp` contienen las principales reglas para la contrucción en electron:
* `atom.gyp` define en si como se compila en Electron.
* `common.gypi` ajusta las configuraciones de generación de Node para construir junto con Chromium.
* `vendor/brightray/brightray.gyp` define cómo se construye `brightray` e incluye las configuraciones predeterminadas para linkear con Chromium.
* `vendor/brightray/brightray.gypi` incluye configuraciones de generación generales sobre la construcción.
#Construir un componente
Desde Chromium es un proyecto bastante largo, la etapa de enlace final puede tomar pocos minutos, lo que hace que sea difícil para el desarrollo. Con el fin de resolver esto, Chromium introdujo el "componente de construcción", que se basa en construir cada componente como una libreria compartida por separado, haciendo que se enlace muy rápido, pero sacrificando el tamaño del archivo y el rendimiento.
En Electron tomamos un enfoque muy similar: para versiones de `Debug` (depuración), el binario será linkeado a una versión de la libreria compartida de los componentes de Chromium para lograr un tiempo de enlace rápido; para versiones de `Release` (lanzamiento), el binario será linkeado a las versiones de las librerias estáticas, por lo que puede tener es posible tener un mejor tamaño binario y rendimiento.
#Bootstrapping minimo (minimo arranque)
Todos los binarios pre-compilados de Chromium (`libchromiumcontent`) son descargados al ejecutar el script de arranque. Por defecto ambas librerias estáticas y librerias compartidas se descargarán y el tamaño final debe estar entre 800 MB y 2 GB dependiendo de la plataforma.
Por defecto, `libchromiumcontent` se descarga de Amazon Web Services. Si se establece la variable de entorno `LIBCHROMIUMCONTENT_MIRROR`, el bootstrap script se descargará de ella. `libchromiumcontent-qiniu-mirror` es un espejo para el` libchromiumcontent`. Si tiene problemas para acceder a AWS, puede cambiar la dirección de descarga a la misma a través de `exportación LIBCHROMIUMCONTENT_MIRROR = http: // 7xk3d2.dl1.z0.glb.clouddn.com /`
Si sólo desea construir en Electron rápidamente para pruebas o desarrollo, puede descargar sólo las versiones de librerias compartidas pasando el parámetro `--dev`:
`$ ./script/bootstrap.py --dev`
`$ ./script/build.py -c D`
#generación de proyecto de dos frases
Los enlaces de Electron con diferentes conjuntos de librerias en versiones `Release` y `Debug`. `gyp`, sin embargo, no es compatible con la configuración de los diferentes ajustes de enlace para diferentes configuraciones.
Para evitar que Electron utilice una variable de `gyp` `libchromiumcontent_component` para controlar qué configuraciones de enlace usar y sólo generar un objetivo cuando se ejecute `gyp`.
#Nombres de destino
A diferencia de la mayoría de los proyectos que utilizan `Release` y `Debug` como nombres de destino, Electron utiliza `R` y `D` en su lugar. Esto se debe a `gyp` bloquea aleatoriamente si sólo hay una configuración de `Release` o `Debug` definidas, y Electron sólo tiene que generar un objetivo a la vez como se ha indicado anteriormente.
Esto sólo afecta a los desarrolladores, si usted está construyendo Electron para rebranding no se ven afectados.

View file

@ -31,7 +31,7 @@ app.on('window-all-closed', function() {
// Specify flash path.
// On Windows, it might be /path/to/pepflashplayer.dll
// On Mac, /path/to/PepperFlashPlayer.plugin
// On OS X, /path/to/PepperFlashPlayer.plugin
// On Linux, /path/to/libpepflashplayer.so
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');

View file

@ -39,7 +39,7 @@ app.on('window-all-closed', function() {
// Epecifica o caminho do flash.
// No Windows, deve ser /path/to/pepflashplayer.dll
// No Mac, /path/to/PepperFlashPlayer.plugin
// No OS X, /path/to/PepperFlashPlayer.plugin
// No Linux, /path/to/libpepflashplayer.so
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');

View file

@ -375,6 +375,12 @@ app.on('ready', function() {
});
```
### `app.setAppUserModelId(id)` _Windows_
* `id` String
Changes the [Application User Model ID][app-user-model-id] to `id`.
### `app.commandLine.appendSwitch(switch[, value])`
Append a switch (with optional `value`) to Chromium's command line.
@ -435,3 +441,4 @@ Sets the application's [dock menu][dock-menu].
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View file

@ -4,27 +4,34 @@ This module provides an interface for the `Squirrel` auto-updater framework.
## Platform notices
Though `autoUpdater` provides an uniform API for different platforms, there are
Though `autoUpdater` provides a uniform API for different platforms, there are
still some subtle differences on each platform.
### OS X
On OS X the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac], you
don't need any special setup to make it work. For server-side requirements, you
can read [Server Support][server-support].
On OS X, the `autoUpdater` module is built upon [Squirrel.Mac][squirrel-mac],
meaning you don't need any special setup to make it work. For server-side
requirements, you can read [Server Support][server-support].
### Windows
On Windows you have to install your app into user's machine before you can use
the auto-updater, it is recommended to use [grunt-electron-installer][installer]
module to generate a Windows installer.
On Windows, you have to install your app into a user's machine before you can
use the auto-updater, so it is recommended to use
[grunt-electron-installer][installer] module to generate a Windows installer.
The server-side setup is also different from OS X, you can read the documents of
The installer generated with Squirrel will create a shortcut icon with an
[Application User Model ID][app-user-model-id] in the format of
`com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, examples are
`com.squirrel.slack.Slack` and `com.squirrel.code.Code`. You have to use the
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
not be able to pin your app properly in task bar.
The server-side setup is also different from OS X. You can read the documents of
[Squirrel.Windows][squirrel-windows] to get more details.
### Linux
There is not built-in support for auto-updater on Linux, it is recommended to
There is not built-in support for auto-updater on Linux, so it is recommended to
use the distribution's package manager to update your app.
## Events
@ -82,12 +89,13 @@ once it is set.
Asks the server whether there is an update. You must call `setFeedUrl` before
using this API.
### `autoUpdater.quitAndUpdate()`
### `autoUpdater.quitAndInstall()`
Restarts the app and install the update after it has been downloaded. It should
only be called after `update-downloaded` has been emitted.
Restarts the app and installs the update after it has been downloaded. It
should only be called after `update-downloaded` has been emitted.
[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac
[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
[installer]: https://github.com/atom/grunt-electron-installer
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View file

@ -594,7 +594,7 @@ Returns the pathname of the file the window represents.
Specifies whether the windows document has been edited, and the icon in title
bar will become grey when set to `true`.
### `win.IsDocumentEdited()` _OS X_
### `win.isDocumentEdited()` _OS X_
Whether the window's document has been edited.

View file

@ -114,4 +114,6 @@ will be passed via `callback(response)`.
Displays a modal dialog that shows an error message.
This API can be called safely before the `ready` event the `app` module emits,
it is usually used to report errors in early stage of startup.
it is usually used to report errors in early stage of startup. If called
before the app `ready`event on Linux, the message will be emitted to stderr,
and no GUI dialog will appear.

View file

@ -33,6 +33,9 @@ npm install --save-dev electron-rebuild
# Every time you run "npm install", run this
./node_modules/.bin/electron-rebuild
# On Windows if you have trouble, try:
.\node_modules\.bin\electron-rebuild.cmd
```
### The npm Way

View file

@ -38,7 +38,7 @@ app.on('window-all-closed', function() {
// Specify flash path.
// On Windows, it might be /path/to/pepflashplayer.dll
// On Mac, /path/to/PepperFlashPlayer.plugin
// On OS X, /path/to/PepperFlashPlayer.plugin
// On Linux, /path/to/libpepflashplayer.so
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');

View file

@ -255,6 +255,8 @@
'atom/common/api/atom_api_asar.cc',
'atom/common/api/atom_api_clipboard.cc',
'atom/common/api/atom_api_crash_reporter.cc',
'atom/common/api/atom_api_id_weak_map.cc',
'atom/common/api/atom_api_id_weak_map.h',
'atom/common/api/atom_api_native_image.cc',
'atom/common/api/atom_api_native_image.h',
'atom/common/api/atom_api_native_image_mac.mm',
@ -314,6 +316,8 @@
'atom/common/native_mate_converters/gurl_converter.h',
'atom/common/native_mate_converters/image_converter.cc',
'atom/common/native_mate_converters/image_converter.h',
'atom/common/native_mate_converters/net_converter.cc',
'atom/common/native_mate_converters/net_converter.h',
'atom/common/native_mate_converters/string16_converter.h',
'atom/common/native_mate_converters/v8_value_converter.cc',
'atom/common/native_mate_converters/v8_value_converter.h',

View file

@ -88,3 +88,16 @@ describe 'ipc module', ->
w.destroy()
done()
w.loadUrl 'file://' + path.join(fixtures, 'api', 'send-sync-message.html')
describe 'remote listeners', ->
it 'can be added and removed correctly', ->
count = 0
w = new BrowserWindow(show: false)
listener = () ->
count += 1
w.removeListener 'blur', listener
w.on 'blur', listener
w.emit 'blur'
w.emit 'blur'
assert.equal count, 1
w.destroy()

2
vendor/native_mate vendored

@ -1 +1 @@
Subproject commit b7387da0854b20d376fdae0d93a01f83d080668d
Subproject commit 21cda4e7fcff592f33f989c1fea575658281711d