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

This commit is contained in:
Eran Tiktin 2015-10-16 22:30:18 +03:00
commit f0c4c806b5
60 changed files with 1475 additions and 95 deletions

View file

@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '0.33.7',
'version%': '0.34.0',
},
'includes': [
'filenames.gypi',
@ -64,9 +64,6 @@
'files': [
'<(PRODUCT_DIR)/<(product_name) Helper.app',
'<(PRODUCT_DIR)/<(product_name) Framework.framework',
'external_binaries/Squirrel.framework',
'external_binaries/ReactiveCocoa.framework',
'external_binaries/Mantle.framework',
],
},
{
@ -109,7 +106,21 @@
'<@(locale_dirs)',
],
},
]
],
'conditions': [
['mas_build==0', {
'copies': [
{
'destination': '<(PRODUCT_DIR)/<(product_name).app/Contents/Frameworks',
'files': [
'external_binaries/Squirrel.framework',
'external_binaries/ReactiveCocoa.framework',
'external_binaries/Mantle.framework',
],
},
],
}],
],
}, { # OS=="mac"
'dependencies': [
'make_locale_paks',
@ -285,12 +296,28 @@
'vendor/breakpad/breakpad.gyp:breakpad_sender',
],
}], # OS=="win"
['OS=="mac"', {
['OS=="mac" and mas_build==0', {
'dependencies': [
'vendor/crashpad/client/client.gyp:crashpad_client',
'vendor/crashpad/handler/handler.gyp:crashpad_handler',
],
}], # OS=="mac"
'link_settings': {
# Do not link with QTKit for mas build.
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/QTKit.framework',
],
},
}], # OS=="mac" and mas_build==0
['OS=="mac" and mas_build==1', {
'defines': [
'MAS_BUILD',
],
'sources!': [
'atom/browser/auto_updater_mac.mm',
'atom/common/crash_reporter/crash_reporter_mac.h',
'atom/common/crash_reporter/crash_reporter_mac.mm',
],
}], # OS=="mac" and mas_build==1
['OS=="linux"', {
'link_settings': {
'ldflags': [
@ -393,9 +420,6 @@
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
'external_binaries/Squirrel.framework',
'external_binaries/ReactiveCocoa.framework',
'external_binaries/Mantle.framework',
],
},
'mac_bundle': 1,
@ -439,12 +463,6 @@
'<@(copied_libraries)',
],
},
{
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
'files': [
'<(PRODUCT_DIR)/crashpad_handler',
],
},
],
'postbuilds': [
{
@ -476,6 +494,25 @@
],
},
],
'conditions': [
['mas_build==0', {
'link_settings': {
'libraries': [
'external_binaries/Squirrel.framework',
'external_binaries/ReactiveCocoa.framework',
'external_binaries/Mantle.framework',
],
},
'copies': [
{
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
'files': [
'<(PRODUCT_DIR)/crashpad_handler',
],
},
],
}],
],
}, # target framework
{
'target_name': '<(project_name)_helper',

View file

@ -21,6 +21,15 @@
namespace atom {
namespace {
bool IsBrowserProcess(base::CommandLine* cmd) {
std::string process_type = cmd->GetSwitchValueASCII(switches::kProcessType);
return process_type.empty();
}
} // namespace
AtomMainDelegate::AtomMainDelegate() {
}
@ -28,11 +37,14 @@ AtomMainDelegate::~AtomMainDelegate() {
}
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
auto command_line = base::CommandLine::ForCurrentProcess();
logging::LoggingSettings settings;
#if defined(OS_WIN)
// On Windows the terminal returns immediately, so we add a new line to
// prevent output in the same line as the prompt.
std::wcout << std::endl;
if (IsBrowserProcess(command_line))
std::wcout << std::endl;
#if defined(DEBUG)
// Print logging to debug.log on Windows
settings.logging_dest = logging::LOG_TO_ALL;
@ -47,9 +59,10 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
#endif // !defined(OS_WIN)
// Only enable logging when --enable-logging is specified.
auto command_line = base::CommandLine::ForCurrentProcess();
if (!command_line->HasSwitch(switches::kEnableLogging))
if (!command_line->HasSwitch(switches::kEnableLogging)) {
settings.logging_dest = logging::LOG_NONE;
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
}
logging::InitLogging(settings);
@ -81,7 +94,7 @@ void AtomMainDelegate::PreSandboxStartup() {
}
// Only append arguments for browser process.
if (!process_type.empty())
if (!IsBrowserProcess(command_line))
return;
#if defined(OS_WIN)

View file

@ -11,6 +11,7 @@
#include "atom/browser/api/atom_api_download_item.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/api/save_page_handler.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/file_path_converter.h"
@ -237,6 +238,8 @@ Session::~Session() {
void Session::OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) {
auto web_contents = item->GetWebContents();
if (SavePageHandler::IsSavePageTypes(item->GetMimeType()))
return;
bool prevent_default = Emit(
"will-download",
DownloadItem::Create(isolate(), item),

View file

@ -162,6 +162,26 @@ struct Converter<net::HttpResponseHeaders*> {
}
};
template<>
struct Converter<content::SavePageType> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
content::SavePageType* out) {
std::string save_type;
if (!ConvertFromV8(isolate, val, &save_type))
return false;
if (save_type == "HTMLOnly") {
*out = content::SAVE_PAGE_TYPE_AS_ONLY_HTML;
} else if (save_type == "HTMLComplete") {
*out = content::SAVE_PAGE_TYPE_AS_COMPLETE_HTML;
} else if (save_type == "MHTML") {
*out = content::SAVE_PAGE_TYPE_AS_MHTML;
} else {
return false;
}
return true;
}
};
} // namespace mate
@ -665,6 +685,13 @@ void WebContents::InsertCSS(const std::string& css) {
web_contents()->InsertCSS(css);
}
bool WebContents::SavePage(const base::FilePath& full_file_path,
const content::SavePageType& save_type,
const SavePageHandler::SavePageCallback& callback) {
auto handler = new SavePageHandler(web_contents(), callback);
return handler->Handle(full_file_path, save_type);
}
void WebContents::ExecuteJavaScript(const base::string16& code,
bool has_user_gesture) {
Send(new AtomViewMsg_ExecuteJavaScript(routing_id(), code, has_user_gesture));
@ -976,6 +1003,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
.SetMethod("insertCSS", &WebContents::InsertCSS)
.SetMethod("savePage", &WebContents::SavePage)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)

View file

@ -9,6 +9,7 @@
#include <vector>
#include "atom/browser/api/frame_subscriber.h"
#include "atom/browser/api/save_page_handler.h"
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/common_web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
@ -73,6 +74,9 @@ class WebContents : public mate::TrackableObject<WebContents>,
void SetUserAgent(const std::string& user_agent);
std::string GetUserAgent();
void InsertCSS(const std::string& css);
bool SavePage(const base::FilePath& full_file_path,
const content::SavePageType& save_type,
const SavePageHandler::SavePageCallback& callback);
void ExecuteJavaScript(const base::string16& code,
bool has_user_gesture);
void OpenDevTools(mate::Arguments* args);

View file

@ -0,0 +1,78 @@
// 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/browser/api/save_page_handler.h"
#include <string>
#include "atom/browser/atom_browser_context.h"
#include "base/callback.h"
#include "base/files/file_path.h"
#include "content/public/browser/web_contents.h"
namespace atom {
namespace api {
SavePageHandler::SavePageHandler(content::WebContents* web_contents,
const SavePageCallback& callback)
: web_contents_(web_contents),
callback_(callback) {
}
SavePageHandler::~SavePageHandler() {
}
void SavePageHandler::OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) {
// OnDownloadCreated is invoked during WebContents::SavePage, so the |item|
// here is the one stated by WebContents::SavePage.
item->AddObserver(this);
}
bool SavePageHandler::Handle(const base::FilePath& full_path,
const content::SavePageType& save_type) {
auto download_manager = content::BrowserContext::GetDownloadManager(
web_contents_->GetBrowserContext());
download_manager->AddObserver(this);
bool result = web_contents_->SavePage(full_path,
full_path.DirName(),
save_type);
download_manager->RemoveObserver(this);
// If initialization fails which means fail to create |DownloadItem|, we need
// to delete the |SavePageHandler| instance to avoid memory-leak.
if (!result)
delete this;
return result;
}
void SavePageHandler::OnDownloadUpdated(content::DownloadItem* item) {
if (item->IsDone()) {
v8::Isolate* isolate = v8::Isolate::GetCurrent();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (item->GetState() == content::DownloadItem::COMPLETE) {
callback_.Run(v8::Null(isolate));
} else {
v8::Local<v8::String> error_message = v8::String::NewFromUtf8(
isolate, "Fail to save page");
callback_.Run(v8::Exception::Error(error_message));
}
Destroy(item);
}
}
void SavePageHandler::Destroy(content::DownloadItem* item) {
item->RemoveObserver(this);
delete this;
}
// static
bool SavePageHandler::IsSavePageTypes(const std::string& type) {
return type == "multipart/related" || type == "text/html";
}
} // namespace api
} // namespace atom

View file

@ -0,0 +1,60 @@
// 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_BROWSER_API_SAVE_PAGE_HANDLER_H_
#define ATOM_BROWSER_API_SAVE_PAGE_HANDLER_H_
#include <string>
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/save_page_type.h"
#include "v8/include/v8.h"
namespace base {
class FilePath;
}
namespace content {
class WebContents;
}
namespace atom {
namespace api {
// A self-destroyed class for handling save page request.
class SavePageHandler : public content::DownloadManager::Observer,
public content::DownloadItem::Observer {
public:
using SavePageCallback = base::Callback<void(v8::Local<v8::Value>)>;
SavePageHandler(content::WebContents* web_contents,
const SavePageCallback& callback);
~SavePageHandler();
bool Handle(const base::FilePath& full_path,
const content::SavePageType& save_type);
static bool IsSavePageTypes(const std::string& type);
private:
void Destroy(content::DownloadItem* item);
// content::DownloadManager::Observer:
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
// content::DownloadItem::Observer:
void OnDownloadUpdated(content::DownloadItem* item) override;
content::WebContents* web_contents_; // weak
SavePageCallback callback_;
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_SAVE_PAGE_HANDLER_H_

View file

@ -16,4 +16,12 @@ void AutoUpdater::SetDelegate(AutoUpdaterDelegate* delegate) {
delegate_ = delegate;
}
#if defined(OS_MACOSX) && defined(MAS_BUILD)
void AutoUpdater::SetFeedURL(const std::string& url) {
}
void AutoUpdater::CheckForUpdates() {
}
#endif
} // namespace auto_updater

View file

@ -69,7 +69,9 @@ unwrapArgs = (sender, args) ->
rendererReleased = true
ret = ->
throw new Error('Calling a callback of released renderer view') if rendererReleased
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}.")
sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
v8Util.setDestructor ret, ->
return if rendererReleased

View file

@ -116,7 +116,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
} else if (options.Get(switches::kCenter, &center) && center) {
Center();
}
extensions::SizeConstraints size_constraints;
// On Linux and Window we may already have maximum size defined.
extensions::SizeConstraints size_constraints(GetContentSizeConstraints());
int min_height = 0, min_width = 0;
if (options.Get(switches::kMinHeight, &min_height) |
options.Get(switches::kMinWidth, &min_width)) {

View file

@ -390,7 +390,10 @@ gfx::Size NativeWindowViews::GetContentSize() {
void NativeWindowViews::SetContentSizeConstraints(
const extensions::SizeConstraints& size_constraints) {
NativeWindow::SetContentSizeConstraints(size_constraints);
window_->OnSizeConstraintsChanged();
// widget_delegate() is only available after Init() is called, we make use of
// this to determine whether native widget has initialized.
if (window_ && window_->widget_delegate())
window_->OnSizeConstraintsChanged();
#if defined(USE_X11)
if (resizable_)
old_size_constraints_ = size_constraints;

View file

@ -17,7 +17,11 @@
<key>CFBundleIconFile</key>
<string>atom.icns</string>
<key>CFBundleVersion</key>
<string>0.33.7</string>
<string>0.34.0</string>
<key>CFBundleShortVersionString</key>
<string>0.34.0</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
<string>10.8.0</string>
<key>NSMainNibFile</key>

View file

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

View file

@ -26,7 +26,6 @@ namespace {
const char* kWebRuntimeFeatures[] = {
switches::kExperimentalFeatures,
switches::kExperimentalCanvasFeatures,
switches::kSubpixelFontScaling,
switches::kOverlayScrollbars,
switches::kOverlayFullscreenVideo,
switches::kSharedWorker,

View file

@ -72,6 +72,10 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
// 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)) {
versions.Set(ATOM_PROJECT_NAME, ATOM_VERSION_STRING);

View file

@ -1,16 +1,25 @@
savedGlobal = global # the "global.global" might be deleted later
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()
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)
id = "#{filenameAndLine} (#{id})"
break
@callbacks[id] = callback
id
@ -18,10 +27,10 @@ class CallbacksRegistry
@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]

View file

@ -6,8 +6,8 @@
#define ATOM_VERSION_H
#define ATOM_MAJOR_VERSION 0
#define ATOM_MINOR_VERSION 33
#define ATOM_PATCH_VERSION 7
#define ATOM_MINOR_VERSION 34
#define ATOM_PATCH_VERSION 0
#define ATOM_VERSION_IS_RELEASE 1

View file

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

View file

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

View file

@ -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];
};
void 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;
CHECK(VirtualProtect(
start, sizeof(ExceptionHandlerRecord), PAGE_EXECUTE_READ, &old_protect));
CHECK(RtlAddFunctionTable(
&record->runtime_function, 1, reinterpret_cast<DWORD64>(start)));
}
void UnregisterNonABICompliantCodeRange(void* start) {
ExceptionHandlerRecord* record =
reinterpret_cast<ExceptionHandlerRecord*>(start);
CHECK(RtlDeleteFunctionTable(&record->runtime_function));
}
#endif // _WIN64
} // namespace
CrashReporterWin::CrashReporterWin() {
@ -63,26 +170,46 @@ 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
// 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)
RegisterNonABICompliantCodeRange(code_range, size);
}
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,

View file

@ -29,6 +29,9 @@ 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>;

View file

@ -311,7 +311,7 @@ bool CrashService::Initialize(const base::string16& application_name,
// service is initialized.
base::string16 wait_name = 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;

View file

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

View file

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

View file

@ -99,7 +99,6 @@ 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";

View file

@ -51,7 +51,6 @@ extern const char kClientCertificate[];
extern const char kExperimentalFeatures[];
extern const char kExperimentalCanvasFeatures[];
extern const char kSubpixelFontScaling[];
extern const char kOverlayScrollbars[];
extern const char kOverlayFullscreenVideo[];
extern const char kSharedWorker[];

View file

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

View file

@ -234,8 +234,6 @@ void AtomRendererClient::EnableWebRuntimeFeatures() {
blink::WebRuntimeFeatures::enableExperimentalFeatures(b);
if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures, &b))
blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(b);
if (IsSwitchEnabled(command_line, switches::kSubpixelFontScaling, &b))
blink::WebRuntimeFeatures::enableSubpixelFontScaling(b);
if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars, &b))
blink::WebRuntimeFeatures::enableOverlayScrollbars(b);
if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo, &b))

View file

@ -12,7 +12,9 @@ var globalShortcut = require('global-shortcut');
app.on('ready', function() {
// 'ctrl+x' 단축키를 리스너에 등록합니다.
var ret = globalShortcut.register('ctrl+x', function() { console.log('ctrl+x is pressed'); })
var ret = globalShortcut.register('ctrl+x', function() {
console.log('ctrl+x is pressed');
});
if (!ret) {
console.log('registration failed');
@ -56,4 +58,4 @@ app.on('will-quit', function() {
### `globalShortcut.unregisterAll()`
모든 전역 단축키 등록을 해제합니다.
모든 전역 단축키 등록을 해제합니다.

View file

@ -56,9 +56,13 @@ Electron 문서 구조를 이해하는 데 참고할 수 있는 유용한 도움
메서드 이름은 인수가 무엇을 받는지에 따라 결정됩니다. 선택적 인수는 브라켓([, ])으로 묶어
이 인수가 다른 인수뒤에서 선택적으로 사용될 수 있다는 것을 표시합니다.
메서드의 밑에선 각 인수에 대해 자세한 설명을 합니다. 인수의 타입은 일반적인 타입 중 하나를 받거나:
[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), [`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object), [`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다.
메서드 이름 하단에선 각 인수에 대해 자세한 설명을 합니다.
인수의 타입은 일반적인 타입 중 하나를 받거나:
[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String),
[`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number),
[`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object),
[`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
와 같은 일반적으로 쓰이는 타입 중 하나를 받거나 Electron의 [`webContent`](api/web-content.md)같은 커스텀 타입을 받습니다.
### Events

View file

@ -14,13 +14,17 @@ $ cd /some-directory
$ git clone --recursive https://github.com/facebook/react-devtools.git
```
그리고 개발자 콘솔이 열린 창에서 다음의 코드를 콘솔에 입력하면 확장 기능을 로드할 수 있습니다:
[`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md)
가이드를 통해 확장 기능을 개발하는 방법을 알아볼 수 있습니다.
그리고 개발자 콘솔에서 다음 코드를 입력하면 확장 기능을 로드할 수 있습니다:
```javascript
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools');
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome');
```
확장 기능을 unload 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다:
확장 기능을 언로드 하고 콘솔을 다시 열 때 해당 확장 기능이 로드되지 않도록 하려면 `BrowserWindow.removeDevToolsExtension` API를 사용하면 됩니다:
```javascript
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools');
@ -29,13 +33,13 @@ require('remote').require('browser-window').removeDevToolsExtension('React Devel
## 개발자 콘솔 확장 기능의 구성 형식
모든 개발자 콘솔 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다.
하지만 반드시 확장 기능은 소스코드 그대로의 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우
사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다.
하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우
사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다.
## 백그라운드 페이지
현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 않습니다.
몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데 이 경우 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다.
몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데, 이 때 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다.
## `chrome.*` API

View file

@ -1,18 +1,18 @@
## Guias
* [Distribuir Aplicação](tutorial/application-distribution.md)
* [Distribuição de Aplicações](tutorial/application-distribution.md)
* [Empacotamento da aplicação](tutorial/application-packaging.md)
* [Usando módulos nativos](../../docs/tutorial/using-native-node-modules.md)
* [Depuração do processo principal](../../docs/tutorial/debugging-main-process.md)
* [Usando módulos nativos](tutorial/using-native-node-modules.md)
* [Depuração do processo principal](tutorial/debugging-main-process.md)
* [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md)
* [Extensão DevTools](../../docs/tutorial/devtools-extension.md)
* [Usando o plugin papper flash](../../docs/tutorial/using-pepper-flash-plugin.md)
* [Usando o plugin papper flash](tutorial/using-pepper-flash-plugin.md)
## Tutoriais
* [Introdução](../../docs/tutorial/quick-start.md)
* [A integração com o ambiente de desenvolvimento](../../docs/tutorial/desktop-environment-integration.md)
* [Evento de detecção on-line/off-line](../../docs/tutorial/online-offline-events.md)
* [Introdução](tutorial/quick-start.md)
* [A integração com o ambiente de desenvolvimento](tutorial/desktop-environment-integration.md)
* [Evento de detecção on-line/off-line](tutorial/online-offline-events.md)
## API - Referencias
@ -68,4 +68,4 @@ Módulos de ambos os processos:
* [Instrução de build (Mac)](../../docs/development/build-instructions-osx.md)
* [Instrução de build (Windows)](../../docs/development/build-instructions-windows.md)
* [Instrução de build (Linux)](../../docs/development/build-instructions-linux.md)
* [Configurando um symbol server no debugger](../../docs/development/setting-up-symbol-server.md)
* [Configurando um symbol server no debugger](../../docs/development/setting-up-symbol-server.md)

View file

@ -0,0 +1,53 @@
# Depurando o Processo Principal
A janela do navegador, DevTools, pode somente depurar o processo de renderização
de scripts (por exemplo, as páginas da web). Para providenciar um modo de
depurar os scripts através do processo principal, o Electron criou as opções
`--debug` e `--debug-brk`.
## Opções da Linha de Comando
Use a seguinte opção na linha de comando para depurar o processo principal do
Electron:
### `--debug=[porta]`
Quando este comando é usado, o Electron irá executar o protocolo de depuração
V8 mandando as mensagens na `porta`. A `porta` padrão é `5858`.
### `--debug-brk=[porta]`
Semelhante ao `--debug`, porém pausa o script na primeira linha.
## Usando node-inspector para depurar
__Nota:__ O Electron usa a versão v0.11.13 do Node, a qual, atualmenta não
funciona muito bem com node-inspector, e o processo principal irá quebrar se
você inspecionar o objeto `process` pelo console do node-inspector.
### 1. Inicie o servidor [node-inspector][node-inspector]
```bash
$ node-inspector
```
### 2. Habilite o modo de depuração para o Electron
Você pode também iniciar o Electron com um ponto de depuração, desta maneira:
```bash
$ electron --debug=5858 sua/aplicacao
```
ou para pausar o script na primeira linha:
```bash
$ electron --debug-brk=5858 sua/aplicacao
```
### 3. Carregue o debugger UI
Abra este endereço http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858
usando o Chrome.
[node-inspector]: https://github.com/node-inspector/node-inspector

View file

@ -0,0 +1,260 @@
# Integração com o ambiente desktop
Diferentes sistemas operacionais possuem diferentes formas de integrar
aplicacões desktop em seus ambientes. Por exemplo, no Windows, as aplicações podem
inserir atalhos no JumpList da barra de tarefas, no Mac, aplicações podem implementar um
menu customizado na dock.
Este guia explica como integrar suas aplicações no ambiente desktop com a API
do Electron.
## Documentos Recentes (Windows & OS X)
O Windows e o OS X disponibilizam um acesso fácil para a lista de arquivos
abertos recentemente pela aplicação através do JumpList ou Dock Menu respectivamente.
__JumpList:__
![JumpList Recent Files](http://i.msdn.microsoft.com/dynimg/IC420538.png)
__Dock menu da Aplicação:__
<img src="https://cloud.githubusercontent.com/assets/639601/5069610/2aa80758-6e97-11e4-8cfb-c1a414a10774.png" height="353" width="428" >
Para adicionar um arquivo para os documentos recentes, você pode usar a API
[app.addRecentDocument][addrecentdocument]:
```javascript
var app = require('app');
app.addRecentDocument('/Users/USERNAME/Desktop/work.type');
```
E você pode usar a API [app.clearRecentDocuments][clearrecentdocuments] para
limpar a lista de documentos recentes.
```javascript
app.clearRecentDocuments();
```
### Notas para Windows
A fim de ser possível usar estas funcionalidades no Windows, sua aplicação deve
estar registrada como um handler daquele tipo de documento, caso contrário, o
arquivo não será exibido no JumpList mesmo depois de você ter adicionado isto.
Você pode encontrar qualquer coisa sobre o registro da aplicacão em
[Application Registration][app-registration].
Quando um usuário clica em um arquivo na JumpList, uma nova instância da sua aplicacão
deve ser iniciada com o caminho do arquivo adicionado como um argumento de
linha de comando.
### Notas para OS X
Quando um arquivo for requisitado pelo menu de documentos recentes, o evento `open-file`
do módulo `app` irá ser emitido.
## Dock Menu customizado (OS X)
OS X permite que desenvolvedores especifiquem um menu customizado para a dock,
que normalmente contém alguns atalhos para as funcionalidades mais utilizadas
da sua aplicação.
__Dock menu do Terminal.app:__
<img src="https://cloud.githubusercontent.com/assets/639601/5069962/6032658a-6e9c-11e4-9953-aa84006bdfff.png" height="354" width="341" >
Para criar seu Dock Menu customizado, você pode usar a API `app.dock.setMenu`,
ela está disponível apenas no OS X:
```javascript
var app = require('app');
var Menu = require('menu');
var dockMenu = Menu.buildFromTemplate([
{ label: 'New Window', click: function() { console.log('New Window'); } },
{ label: 'New Window with Settings', submenu: [
{ label: 'Basic' },
{ label: 'Pro'}
]},
{ label: 'New Command...'}
]);
app.dock.setMenu(dockMenu);
```
## Tarefas do Usuário (Windows)
No Windows você pode especificar ações customizadas na categoria `Tarefas` do JumpList,
esse texto foi copiado do MSDN:
> Applications define tasks based on both the program's features and the key
> things a user is expected to do with them. Tasks should be context-free, in
> that the application does not need to be running for them to work. They
> should also be the statistically most common actions that a normal user would
> perform in an application, such as compose an email message or open the
> calendar in a mail program, create a new document in a word processor, launch
> an application in a certain mode, or launch one of its subcommands. An
> application should not clutter the menu with advanced features that standard
> users won't need or one-time actions such as registration. Do not use tasks
> for promotional items such as upgrades or special offers.
>
> It is strongly recommended that the task list be static. It should remain the
> same regardless of the state or status of the application. While it is
> possible to vary the list dynamically, you should consider that this could
> confuse the user who does not expect that portion of the destination list to
> change.
__Tarefas do Internet Explorer:__
![IE](http://i.msdn.microsoft.com/dynimg/IC420539.png)
Ao contrário do Menu Dock no OS X que é um verdadeiro menu, tarefas do usuário no Windows
funcionam como atalhos, de uma forma que quando o usuário clica em uma tarefa, um programa
deve ser executado com os argumentos especificados.
Para setar tarefas do usuário para sua aplicação, você pode usar a API
[app.setUserTasks][setusertaskstasks]:
```javascript
var app = require('app');
app.setUserTasks([
{
program: process.execPath,
arguments: '--new-window',
iconPath: process.execPath,
iconIndex: 0,
title: 'New Window',
description: 'Create a new window'
}
]);
```
Para limpar sua lista de tarefas, apenas chame `app.setUserTasks` com um
array vazio.
```javascript
app.setUserTasks([]);
```
As tarefas do usuário são exibidas mesmo depois da aplicação ser fechada,
então o ícone e o caminho do programa especificado pela tarefa deve existir
até sua aplicação ser desinstalada.
## Miniaturas na Barra de Ferramentas
No Windows você pode adicionar uma miniatura na barra de ferramentas com botões
específicos para a janela e barra de tarefas para aplicação. Isso provê ao usuário
uma forma de acessar um comando específico para janela sem ser necessário restaurar
ou ativar a janela.
Isto é ilustrado no MSDN:
> This toolbar is simply the familiar standard toolbar common control. It has a
> maximum of seven buttons. Each button's ID, image, tooltip, and state are defined
> in a structure, which is then passed to the taskbar. The application can show,
> enable, disable, or hide buttons from the thumbnail toolbar as required by its
> current state.
>
> For example, Windows Media Player might offer standard media transport controls
> such as play, pause, mute, and stop.
__Miniaturas da barra de tarefas do Windows Media Player:__
![player](https://i-msdn.sec.s-msft.com/dynimg/IC420540.png)
Você pode usar [BrowserWindow.setThumbarButtons][setthumbarbuttons] para criar
miniaturas na barra de ferramentas para sua aplicação.
```
var BrowserWindow = require('browser-window');
var path = require('path');
var win = new BrowserWindow({
width: 800,
height: 600
});
win.setThumbarButtons([
{
tooltip: "button1",
icon: path.join(__dirname, 'button1.png'),
click: function() { console.log("button2 clicked"); }
},
{
tooltip: "button2",
icon: path.join(__dirname, 'button2.png'),
flags:['enabled', 'dismissonclick'],
click: function() { console.log("button2 clicked."); }
}
]);
```
Para limpar os botões na miniatura da barra de ferramentas, apenas chame
`BrowserWindow.setThumbarButtons` com um array vazio.
```javascript
win.setThumbarButtons([]);
```
## Unity Launcher Shortcuts (Linux)
No Unity, você pode adicionar entradas customizadas para estes lançadores modificando
o arquivo `.desktop`, veja [Adding Shortcuts to a Launcher][unity-launcher].
__Launcher shortcuts do Audacious:__
![audacious](https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles?action=AttachFile&do=get&target=shortcuts.png)
## Barra de Progresso na Barra de Tarefas (Windows & Unity)
No Windows o botão na barra de tarefas pode ser usado para exibir uma barra de progresso.
Isto permite que a janela exiba informação sobre o progresso de algum processo sem
a necessidade do usuário mudar de janela.
A Unity DE também tem uma funcionalidade parecida que permite especificar uma barra
de progresso no ícone do lançador.
__Barra de Progresso no botão da barra de tarefas:__
![Barra de Progresso na Barra de Tarefas](https://cloud.githubusercontent.com/assets/639601/5081682/16691fda-6f0e-11e4-9676-49b6418f1264.png)
__Barra de progresso no Unity launcher:__
![Unity Launcher](https://cloud.githubusercontent.com/assets/639601/5081747/4a0a589e-6f0f-11e4-803f-91594716a546.png)
Para adicionar uma barra de progresso para uma janela, você pode ver a API:
[BrowserWindow.setProgressBar][setprogressbar]:
```javascript
var window = new BrowserWindow({...});
window.setProgressBar(0.5);
```
## Representação do arquivo na janela (OS X)
No OS X, uma janela pode possuir a representação de um arquivo na barra de título,
permitindo que ao usuário acionar um Command-Click ou Control-Click sobre o título da janela,
uma pop-up de navegação entre arquivos é exibida.
Você também pode inserir um estado de edição na janela para que o ícone do arquivo
possa indicar se o documento nesta janela foi modificado.
__Menu popup da representação de arquivo:__
<img src="https://cloud.githubusercontent.com/assets/639601/5082061/670a949a-6f14-11e4-987a-9aaa04b23c1d.png" height="232" width="663" >
Para inserir o arquivo de representacão da janela, você pode usar as API
[BrowserWindow.setRepresentedFilename][setrepresentedfilename] e
[BrowserWindow.setDocumentEdited][setdocumentedited]:
```javascript
var window = new BrowserWindow({...});
window.setRepresentedFilename('/etc/passwd');
window.setDocumentEdited(true);
```
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks
[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress
[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename
[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited
[app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons

View file

@ -0,0 +1,83 @@
# Online/Offline Event Detection
Os eventos de detecão Online e Offile podem ser implementados no processo
de renderização utilizando a API padrão do HTML, como é mostrado no exemplo
a seguir.
_main.js_
```javascript
var app = require('app');
var BrowserWindow = require('browser-window');
var onlineStatusWindow;
app.on('ready', function() {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
});
```
_online-status.html_
```html
<!DOCTYPE html>
<html>
<body>
<script>
var alertOnlineStatus = function() {
window.alert(navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', alertOnlineStatus);
window.addEventListener('offline', alertOnlineStatus);
alertOnlineStatus();
</script>
</body>
</html>
```
Pode haver casos onde você também deseja responder a estes eventos no processo principal.
Mas o processo principal não consegue detectar esses eventos diretamente, pois não possui
um objeto `navigator`. Utilizando a ferramentas para comunicação entre processos, os eventos
podem ser direcionados para o processo principal e manipulados quando necessário. Você
pode ver isto no exemplo abaixo.
_main.js_
```javascript
var app = require('app');
var ipc = require('ipc');
var BrowserWindow = require('browser-window');
var onlineStatusWindow;
app.on('ready', function() {
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
});
ipc.on('online-status-changed', function(event, status) {
console.log(status);
});
```
_online-status.html_
```html
<!DOCTYPE html>
<html>
<body>
<script>
var ipc = require('ipc');
var updateOnlineStatus = function() {
ipc.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
};
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOnlineStatus);
updateOnlineStatus();
</script>
</body>
</html>
```

View file

@ -0,0 +1,68 @@
# Usando Módulos Nativos do Node
Os módulos nativos do Node são suportados pelo Electron, desde que o Electron
esteja usando uma versão diferente da oficial V8 do Node, você tem de
especificar manualmente a localização das headers do Electron quando compilar os
módulos nativos.
## Compatibilidade de Módulos Nativos do Node
Módulos nativos podem quebrar quando utilizar a nova versão do Node, V8.
Para ter certeza que o módulo que você está interessado em trabalhar com o
Electron, você deve checar se a versão do Node utilizada é compatível com a
usada pelo Electron.
Você pode verificar qual versão do Node foi utilizada no Electron olhando na
página [releases](https://github.com/atom/electron/releases) ou usando
`process.version` (veja [Quick Start](https://github.com/atom/electron/blob/master/docs/tutorial/quick-start.md)
por exemplo).
Considere usar [NAN](https://github.com/nodejs/nan/) para seus próprios
módulos, caso isso facilite o suporte da múltiplas versões do Node. Isso é
também de grande ajuda para fazer a portabilidade dos módulos antigos para as
versões mais novas do Node, assim podendo trabalhar com o Electron.
## Como Instalar os Módulos Nativos
Existem três maneiras de instalar os módulos nativos:
### O Modo Fácil
O modo mais direto para recompilar os módulos é pelo pacote
[`electron-rebuild`](https://github.com/paulcbetts/electron-rebuild),
o que lida com passos manuais para baixar as headers e construir os módulos
nativos:
```sh
npm install --save-dev electron-rebuild
# Sempre que rodar npm install, execute também:
node ./node_modules/.bin/electron-rebuild
```
### Via npm
Você pode usar também `npm` para instalar os módulos. Os passos são exatamente
os mesmos com os módulos Node, exceto que você precisa configurar algumas
variáveis da ambiente:
```bash
export npm_config_disturl=https://atom.io/download/atom-shell
export npm_config_target=0.33.1
export npm_config_arch=x64
export npm_config_runtime=electron
HOME=~/.electron-gyp npm install module-name
```
### O modo node-gyp
Para compilar os módulos do Node com as headers do Electron, você precisa dizer
ao `node-gyp` onde baixar as headers e qual versão usar:
```bash
$ cd /path-to-module/
$ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=https://atom.io/download/atom-shell
```
A tag `HOME=~/.electron-gyp` altera onde encontrar as headers de desenvolvimento.
A tag `--target=0.29.1` é a versão do Electron. A tag `--dist-url=...` especifica
onde baixar as headers. A tag `--arch=x64` diz ao módulo que é feito em 64bit.

View file

@ -0,0 +1,68 @@
# Usando o Plugin Pepper Flash
Electron atualmente suporta o plugin Pepper Flash. Para usá-lo no Electron,
você deve especificar manualmente a localização do plugin e então ele será
habilitado em sua aplicação.
## Prepare uma cópia do plugin Flash
Tanto no OS X como no Linux, os detalhes do plugin Pepper Flash podem ser
encontrados navegando por `chrome://plugins` no navegador Chrome. Essa
localização e versão são úteis para o suporte do plugin Electron's Pepper Flash.
Você pode também copiar para outra localização.
## Adicionando a opçao Electron
Você pode adicionar diretamente `--ppapi-flash-path` e `ppapi-flash-version`
para a linha de comando do Electron ou usando o método
`app.commandLine.appendSwitch` após o evento pronto. Também, adicione a opção
`plugins` em `browser-window`.
Por exemplo:
```javascript
var app = require('app');
var BrowserWindow = require('browser-window');
// Informa os erros ao ao servidor.
require('crash-reporter').start();
// Mantém uma referência global da janela, se não manter, a janela irá fechar
// automaticamente quando o objeto javascript for GCed.
var mainWindow = null;
// Sai assim que todas as janelas forem fechadas.
app.on('window-all-closed', function() {
if (process.platform != 'darwin') {
app.quit();
}
});
// Epecifica o caminho do flash.
// No Windows, deve ser /path/to/pepflashplayer.dll
// No Mac, /path/to/PepperFlashPlayer.plugin
// No Linux, /path/to/libpepflashplayer.so
app.commandLine.appendSwitch('ppapi-flash-path', '/path/to/libpepflashplayer.so');
// Especifica a versão do flash, por exemplo, v17.0.0.169
app.commandLine.appendSwitch('ppapi-flash-version', '17.0.0.169');
app.on('ready', function() {
mainWindow = new BrowserWindow({
'width': 800,
'height': 600,
'web-preferences': {
'plugins': true
}
});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
// Algo mais
});
```
## Ative o plugin Flash na tag `<webview>`
Adicione o atributo `plugins` na tag `<webview>`.
```html
<webview src="http://www.adobe.com/software/flash/about/" plugins></webview>
```

View file

@ -1,5 +1,6 @@
## 向导
* [支持平台](tutorial/supported-platforms.md)
* [应用部署](tutorial/application-distribution.md)
* [应用打包](tutorial/application-packaging.md)
* [使用原生模块](tutorial/using-native-node-modules.md)

View file

@ -0,0 +1,68 @@
# ipc (主进程)
在主进程使用`ipc`模块时,`ipc`负责捕获从渲染进程(网页)发送的同步或者是异步消息.
## 发送消息
主进程也可以向渲染进程发送信息,具体可以看[WebContents.send](web-contents.md#webcontentssendchannel-args).
- 当发送消息的时候,事件名字为`channel`.
- 回复一个同步消息的时候,你需要使用`event.returnValue`
- 回复一个异步消息的时候,使用`event.sender.send(...)`
下面是一个主进程和渲染进程的通信例子.
```javascript
// 在主进程中.
var ipc = require('ipc');
ipc.on('asynchronous-message', function(event, arg) {
console.log(arg); // 打印 "ping"
event.sender.send('asynchronous-reply', 'pong');
});
ipc.on('synchronous-message', function(event, arg) {
console.log(arg); // 打印 "ping"
event.returnValue = 'pong';
});
```
```javascript
// 在渲染进程(网页).
var ipc = require('ipc');
console.log(ipc.sendSync('synchronous-message', 'ping')); // 打印 "pong"
ipc.on('asynchronous-reply', function(arg) {
console.log(arg); // 打印 "pong"
});
ipc.send('asynchronous-message', 'ping');
```
## 监听消息
`ipc`模块有下列几种方法来监听事件.
### `ipc.on(channel, callback)`
* `channel` - 事件名称.
* `callback` - 回调函数.
当事件发生的时候,会传入`callback` `event`和`arg`参数.
## IPC 事件
传入`callback`的`event`对象含有下列方法.
### `Event.returnValue`
在同步消息中,设置这个值将会被返回.
### `Event.sender`
返回一个可以发送消息的`WebContents`.
### `Event.sender.send(channel[.arg1][,arg2][,...])`
* `channel` - 事件名称.
* `arg` (选用)
这个可以发送一个可带参数的异步消息回渲染进程.

View file

@ -0,0 +1,109 @@
# 应用部署
为了使用Electron部署你的应用程序你存放应用程序的文件夹需要叫做 `app` 并且需要放在 Electron 的资源文件夹下(在 OS X 中是指 `Electron.app/Contents/Resources/`,在 Linux 和 Windows 中是指 `resources/`
就像这样:
在 OS X 中:
```text
electron/Electron.app/Contents/Resources/app/
├── package.json
├── main.js
└── index.html
```
在 Windows 和 Linux 中:
```text
electron/resources/app
├── package.json
├── main.js
└── index.html
```
然后运行 `Electron.app` (或者 Linux 中的 `electron`Windows 中的 `electron.exe`,
接着 Electron 就会以你的应用程序的方式启动。`electron` 文件夹将被部署并可以分发给最终的使用者。
## 将你的应用程序打包成一个文件
除了通过拷贝所有的资源文件来分发你的应用程序之外,你可以可以通过打包你的应用程序为一个 [asar](https://github.com/atom/asar) 库文件以避免暴露你的源代码。
为了使用一个 `asar` 库文件代替 `app` 文件夹,你需要修改这个库文件的名字为 `app.asar`
然后将其放到 Electron 的资源文件夹下,然后 Electron 就会试图读取这个库文件并从中启动。
如下所示:
在 OS X 中:
```text
electron/Electron.app/Contents/Resources/
└── app.asar
```
在 Windows 和 Linux 中:
```text
electron/resources/
└── app.asar
```
更多的细节请见 [Application packaging](application-packaging.md).
## 更换名称与下载二进制文件
在使用 Electron 打包你的应用程序之后,你可能需要在分发给用户之前修改打包的名字。
### Windows
你可以将 `electron.exe` 改成任意你喜欢的名字,然后可以使用像
[rcedit](https://github.com/atom/rcedit) 或者[ResEdit](http://www.resedit.net)
编辑它的icon和其他信息。
### OS X
你可以将 `Electron.app` 改成任意你喜欢的名字,然后你也需要修改这些文件中的
`CFBundleDisplayName` `CFBundleIdentifier` 以及 `CFBundleName` 字段。
这些文件如下:
* `Electron.app/Contents/Info.plist`
* `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`
你也可以重命名帮助应用程序以避免在应用程序监视器中显示 `Electron Helper`
但是请确保你已经修改了帮助应用的可执行文件的名字。
一个改过名字的应用程序的构造可能是这样的:
```
MyApp.app/Contents
├── Info.plist
├── MacOS/
│   └── MyApp
└── Frameworks/
├── MyApp Helper EH.app
| ├── Info.plist
| └── MacOS/
|    └── MyApp Helper EH
├── MyApp Helper NP.app
| ├── Info.plist
| └── MacOS/
|    └── MyApp Helper NP
└── MyApp Helper.app
├── Info.plist
└── MacOS/
   └── MyApp Helper
```
### Linux
你可以将 `electron` 改成任意你喜欢的名字。
## 通过重编译源代码来更换名称
通过修改产品名称并重编译源代码来更换 Electron 的名称也是可行的。
你需要修改 `atom.gyp` 文件并彻底重编译一次。
### grunt打包脚本
手动的检查 Electron 代码并重编译是很复杂晦涩的,因此有一个 Grunt任务可以自动自动的处理
这些内容 [grunt-build-atom-shell](https://github.com/paulcbetts/grunt-build-atom-shell).
这个任务会自动的处理编辑 `.gyp` 文件,从源代码进行编译,然后重编译你的应用程序的本地 Node 模块以匹配这个新的可执行文件的名称。

View file

@ -0,0 +1,48 @@
# 主进程调试
浏览器窗口的开发工具仅能调试渲染器的进程脚本比如web 页面)。为了提供一个可以调试主进程
的方法Electron 提供了 `--debug``--debug-brk` 开关。
## 命令行开关
使用如下的命令行开关来调试 Electron 的主进程:
### `--debug=[port]`
当这个开关用于 Electron 时,它将会监听 V8 引擎中有关 `port` 的调试器协议信息。
默认的 `port``5858`
### `--debug-brk=[port]`
就像 `--debug` 一样,但是会在第一行暂停脚本运行。
## 使用 node-inspector 来调试
__备注__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好
如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。
### 1. 开始 [node-inspector][node-inspector] 服务
```bash
$ node-inspector
```
### 2. 打开 Electron 的调试模式
你也可以用调试参数来运行 Electron
```bash
$ electron --debug=5858 your/app
```
或者,在第一行暂停你的脚本:
```bash
$ electron --debug-brk=5858 your/app
```
### 3. 加载调试器界面
在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858
[node-inspector]: https://github.com/node-inspector/node-inspector

View file

@ -0,0 +1,27 @@
# 支持的平台
以下的平台是 Electron 目前支持的:
### OS X
对于 OS X 系统仅有64位的二进制文档支持的最低版本是 OS X 10.8。
### Windows
仅支持 Windows 7 及其以后的版本,之前的版本中是不能工作的。
对于 Windows 提供 `x86``amd64` (x64) 版本的二进制文件。需要注意的是
`ARM` 版本的 Windows 目前尚不支持.
### Linux
预编译的 `ia32`(`i686`) 和 `x64`(`amd64`) 版本 Electron 二进制文件都是在
Ubuntu 12.04 下编译的,`arm` 版的二进制文件是在 ARM v7硬浮点 ABI 与
Debian Wheezy 版本的 NEON下完成的。
预编译二进制文件是否能够运行,取决于其中是否包括了编译平台链接的库,所以只有 Ubuntu 12.04
可以保证正常工作,但是以下的平台也被正事可以运行 Electron的预编译版本
* Ubuntu 12.04 及更新
* Fedora 21
* Debian 8

View file

@ -2,6 +2,7 @@
* [Supported Platforms](tutorial/supported-platforms.md)
* [Application Distribution](tutorial/application-distribution.md)
* [Mac App Store Submission Guide](tutorial/mac-app-store-submission-guide.md)
* [Application Packaging](tutorial/application-packaging.md)
* [Using Native Node Modules](tutorial/using-native-node-modules.md)
* [Debugging Main Process](tutorial/debugging-main-process.md)

View file

@ -111,7 +111,6 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
* `plugins` Boolean - Whether plugins should be enabled.
* `experimental-features` Boolean
* `experimental-canvas-features` Boolean
* `subpixel-font-scaling` Boolean
* `overlay-scrollbars` Boolean
* `overlay-fullscreen-video` Boolean
* `shared-worker` Boolean

View file

@ -8,6 +8,8 @@ upstream node:
* `process.versions['electron']` String - Version of Electron.
* `process.versions['chrome']` String - Version of Chromium.
* `process.resourcesPath` String - Path to JavaScript source code.
* `process.mas` Boolean - For Mac App Store build, this value is `true`, for
other builds it is `undefined`.
## Events
@ -37,7 +39,7 @@ The `process` object has the following method:
Causes the main thread of the current process hang.
### process.setFdLimit(maxDescriptors) _OS X_ _Linux_
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
* `maxDescriptors` Integer

View file

@ -631,3 +631,26 @@ Get the `WebContents` of DevTools for this `WebContents`.
**Note:** Users should never store this object because it may become `null`
when the DevTools has been closed.
### `webContents.savePage(fullPath, saveType, callback)`
* `fullPath` String - The full file path.
* `saveType` String - Specify the save type.
* `HTMLOnly` - Save only the HTML of the page.
* `HTMLComplete` - Save complete-html page.
* `MHTML` - Save complete-html page as MHTML.
* `callback` Function - `function(error) {}`.
* `error` Error
Returns true if the process of saving page has been initiated successfully.
```javascript
win.loadUrl('https://github.com');
win.webContents.on('did-finish-load', function() {
win.webContents.savePage('/tmp/test.html', 'HTMLComplete', function(error) {
if (!error)
console.log("Save page successfully");
});
});
```

View file

@ -35,7 +35,7 @@ exposing your app's source code to users.
To use an `asar` archive to replace the `app` folder, you need to rename the
archive to `app.asar`, and put it under Electron's resources directory like
below, and Electron will then try read the archive and start from it.
below, and Electron will then try to read the archive and start from it.
On OS X:

View file

@ -223,7 +223,7 @@ window.setProgressBar(0.5);
## Represented File of Window (OS X)
On OS X a window can set its represented file, so the file's icon can show in
the title bar and when users Command-Click or Control-Click on the tile a path
the title bar and when users Command-Click or Control-Click on the title a path
popup will show.
You can also set the edited state of a window so that the file icon can indicate

View file

@ -16,11 +16,13 @@ $ cd /some-directory
$ git clone --recursive https://github.com/facebook/react-devtools.git
```
Follow the instructions in [`react-devtools/shells/chrome/Readme.md`](https://github.com/facebook/react-devtools/blob/master/shells/chrome/Readme.md) to build the extension.
Then you can load the extension in Electron by opening DevTools in any window,
and running the following code in the DevTools console:
```javascript
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools');
require('remote').require('browser-window').addDevToolsExtension('/some-directory/react-devtools/shells/chrome');
```
To unload the extension, you can call the `BrowserWindow.removeDevToolsExtension`

View file

@ -0,0 +1,115 @@
# Mac App Store Submission Guide
Since v0.34.0, Electron allows submitting packaged apps to Mac App Store (MAS),
this guide provides information on how to submit your app, and the limitations
of the MAS build.
## How to submit your app
Following steps introduces a simple way to submit your app to Mac App Store, but
it doesn't make sure your app gets approved by Apple, you still have to read
apple's [Submitting Your App][submitting-your-app] guide on how to meet Mac
App Store's requirements.
### Get certificate
To submit your app to Mac App Store, you have to get a certificate from Apple
first, you can follow [existing guides][nwjs-guide] on web.
### Sign your app
After getting the certificate, you can package your app by following
[Application Distribution](application-distribution.md), and then sign your app.
The step is basically the same with other programs, the key is to sign every
dependency of Electron one by one.
First you need to prepare two entitlements files.
`child.plist`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
```
`parent.plist`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
```
And then sign your app with following script:
```bash
#!/bin/bash
# Name of your app.
APP="YourApp"
# The path of you app to sign.
APP_PATH="/path/to/YouApp.app"
# The path to the location you want to put the signed package.
RESULT_PATH="~/Desktop/$APP.pkg"
# The name of certificates you requested.
APP_KEY="3rd Party Mac Developer Application: Company Name (APPIDENTITY)"
INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)"
FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Libraries/libnode.dylib"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Electron Framework"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/"
codesign --deep -fs "$APP_KEY" --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/"
codesign -fs "$APP_KEY" --entitlements parent.plist "$APP_PATH"
productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$APP_PATH"
```
If you are new to app sandboxing of OS X, you should also go through Apple's
[Enabling App Sandbox][enable-app-sandbox] to have a basic idea, and add keys
for the permissions needed by your app to the entitlements files.
### Upload your app and submit for review
After signing your app you can use Application Loader to upload it to iTunes
Connect for processing, make sure you have [created a record][create-record]
before uploading. Then you can [submit your app for review][submit-for-review].
## Limitations of MAS build
In order to satisfy requirements for app sandboxing, following modules have been
disabled in MAS build:
* `crash-reporter`
* `auto-updater`
and following behaviors have been changed:
* Video capture may not work for some machines.
* Certain accessibility features may not work.
* Apps will not be aware of DNS changes.
Also due to the usage of app sandboxing, the resources can be accessed by the
app is strictly limited, you can read [App Sandboxing][app-sandboxing] for more.
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html
[nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps
[enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html
[create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html
[submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html
[app-sandboxing]: https://developer.apple.com/app-sandboxing/

View file

@ -108,6 +108,8 @@
'atom/browser/api/trackable_object.h',
'atom/browser/api/frame_subscriber.cc',
'atom/browser/api/frame_subscriber.h',
'atom/browser/api/save_page_handler.cc',
'atom/browser/api/save_page_handler.h',
'atom/browser/auto_updater.cc',
'atom/browser/auto_updater.h',
'atom/browser/auto_updater_delegate.h',

View file

@ -106,10 +106,11 @@ def update_info_plist(version):
line = lines[i]
if 'CFBundleVersion' in line:
lines[i + 1] = ' <string>{0}</string>\n'.format(version)
if 'CFBundleShortVersionString' in line:
lines[i + 1] = ' <string>{0}</string>\n'.format(version)
with open(info_plist, 'w') as f:
f.write(''.join(lines))
return
with open(info_plist, 'w') as f:
f.write(''.join(lines))
def tag_version(version):

View file

@ -8,7 +8,8 @@ import sys
import stat
from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL, PLATFORM, \
get_target_arch, get_chromedriver_version
get_target_arch, get_chromedriver_version, \
get_platform_key
from lib.util import scoped_cwd, rm_rf, get_atom_shell_version, make_zip, \
execute, atom_gyp
@ -170,7 +171,8 @@ def create_symbols():
def create_dist_zip():
dist_name = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION,
PLATFORM, get_target_arch())
get_platform_key(),
get_target_arch())
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
with scoped_cwd(DIST_DIR):
@ -182,7 +184,7 @@ def create_dist_zip():
def create_chrome_binary_zip(binary, version):
dist_name = '{0}-{1}-{2}-{3}.zip'.format(binary, version, PLATFORM,
dist_name = '{0}-{1}-{2}-{3}.zip'.format(binary, version, get_platform_key(),
get_target_arch())
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
@ -198,7 +200,7 @@ def create_chrome_binary_zip(binary, version):
def create_symbols_zip():
dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
ATOM_SHELL_VERSION,
PLATFORM,
get_platform_key(),
get_target_arch())
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)

View file

@ -7,8 +7,8 @@ import sys
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = '04523758cda2a96d2454f9056fb1fb9a1c1f95f1'
'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
LIBCHROMIUMCONTENT_COMMIT = '78e54bc39a04b758ed5167cd980cc4d9951bd629'
PLATFORM = {
'cygwin': 'win32',
@ -20,6 +20,13 @@ PLATFORM = {
verbose_mode = False
def get_platform_key():
if os.environ.has_key('MAS_BUILD'):
return 'mas'
else:
return PLATFORM
def get_target_arch():
try:
target_arch_path = os.path.join(__file__, '..', '..', '..', 'vendor',

View file

@ -55,11 +55,17 @@ def run_gyp(target_arch, component):
# Avoid using the old gyp lib in system.
env['PYTHONPATH'] = os.path.pathsep.join([gyp_pylib,
env.get('PYTHONPATH', '')])
# Whether to build for Mac App Store.
if os.environ.has_key('MAS_BUILD'):
mas_build = 1
else:
mas_build = 0
defines = [
'-Dlibchromiumcontent_component={0}'.format(component),
'-Dtarget_arch={0}'.format(target_arch),
'-Dhost_arch={0}'.format(get_host_arch()),
'-Dlibrary=static_library',
'-Dmas_build={0}'.format(mas_build),
]
return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
'atom.gyp', '-Icommon.gypi'] + defines, env=env)

View file

@ -7,7 +7,8 @@ import subprocess
import sys
import tempfile
from lib.config import PLATFORM, get_target_arch, get_chromedriver_version
from lib.config import PLATFORM, get_target_arch, get_chromedriver_version, \
get_platform_key
from lib.util import atom_gyp, execute, get_atom_shell_version, parse_version, \
scoped_cwd
from lib.github import GitHub
@ -24,14 +25,14 @@ OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'R')
DIST_DIR = os.path.join(SOURCE_ROOT, 'dist')
DIST_NAME = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME,
ATOM_SHELL_VERSION,
PLATFORM,
get_platform_key(),
get_target_arch())
SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
ATOM_SHELL_VERSION,
PLATFORM,
get_platform_key(),
get_target_arch())
MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION,
PLATFORM,
get_platform_key(),
get_target_arch())
@ -85,7 +86,7 @@ def main():
# Upload chromedriver and mksnapshot for minor version update.
if parse_version(args.version)[2] == '0':
chromedriver = 'chromedriver-{0}-{1}-{2}.zip'.format(
get_chromedriver_version(), PLATFORM, get_target_arch())
get_chromedriver_version(), get_platform_key(), get_target_arch())
upload_atom_shell(github, release, os.path.join(DIST_DIR, chromedriver))
upload_atom_shell(github, release, os.path.join(DIST_DIR, MKSNAPSHOT_NAME))

View file

@ -301,3 +301,15 @@ describe 'browser-window module', ->
assert.notEqual data.length, 0
w.webContents.endFrameSubscription()
done()
describe 'save page', ->
savePagePath = path.join fixtures, 'save_page.html'
it 'should save page', (done) ->
w.webContents.on 'did-finish-load', ->
w.webContents.savePage savePagePath, 'HTMLComplete', (error) ->
assert.equal error, null
assert fs.existsSync savePagePath
fs.unlinkSync savePagePath
done()
w.loadUrl "file://#{fixtures}/api/blank.html"

View file

@ -15,8 +15,8 @@ describe 'crash-reporter module', ->
beforeEach -> w = new BrowserWindow(show: false)
afterEach -> w.destroy()
# It is not working on 64bit Windows.
return if process.platform is 'win32' and process.arch is 'x64'
# It is not working for mas build.
return if process.mas
# The crash-reporter test is not reliable on CI machine.
isCI = remote.process.argv[2] == '--ci'

View file

@ -450,10 +450,10 @@ describe 'asar package', ->
w = new BrowserWindow(show: false, width: 400, height: 400)
p = path.resolve fixtures, 'asar', 'web.asar', 'index.html'
u = url.format protocol: 'file', slashed: true, pathname: p
w.loadUrl u
ipc.once 'dirname', (event, dirname) ->
assert.equal dirname, path.dirname(p)
done()
w.loadUrl u
it 'loads script tag in html', (done) ->
after ->

2
vendor/brightray vendored

@ -1 +1 @@
Subproject commit 375436a777a793f4815f38c13a5226fcd82de567
Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0