Merge remote-tracking branch 'refs/remotes/atom/master'
This commit is contained in:
commit
f0c4c806b5
60 changed files with 1475 additions and 95 deletions
69
atom.gyp
69
atom.gyp
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
78
atom/browser/api/save_page_handler.cc
Normal file
78
atom/browser/api/save_page_handler.cc
Normal 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
|
60
atom/browser/api/save_page_handler.h
Normal file
60
atom/browser/api/save_page_handler.h
Normal 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_
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -116,7 +116,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
|||
} else if (options.Get(switches::kCenter, ¢er) && 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)) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -26,7 +26,6 @@ namespace {
|
|||
const char* kWebRuntimeFeatures[] = {
|
||||
switches::kExperimentalFeatures,
|
||||
switches::kExperimentalCanvasFeatures,
|
||||
switches::kSubpixelFontScaling,
|
||||
switches::kOverlayScrollbars,
|
||||
switches::kOverlayFullscreenVideo,
|
||||
switches::kSharedWorker,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -64,4 +64,23 @@ CrashReporter::GetUploadedReports(const std::string& path) {
|
|||
return result;
|
||||
}
|
||||
|
||||
void CrashReporter::InitBreakpad(const std::string& product_name,
|
||||
const std::string& version,
|
||||
const std::string& company_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) {
|
||||
}
|
||||
|
||||
void CrashReporter::SetUploadParameters() {
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) && defined(MAS_BUILD)
|
||||
// static
|
||||
CrashReporter* CrashReporter::GetInstance() {
|
||||
static CrashReporter crash_reporter;
|
||||
return &crash_reporter;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace crash_reporter
|
||||
|
|
|
@ -40,8 +40,8 @@ class CrashReporter {
|
|||
const std::string& company_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) = 0;
|
||||
virtual void SetUploadParameters() = 0;
|
||||
bool skip_system_crash_handler);
|
||||
virtual void SetUploadParameters();
|
||||
|
||||
StringMap upload_parameters_;
|
||||
bool is_browser_;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -152,6 +152,10 @@ v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
|
|||
return ToV8Object(isolate,
|
||||
static_cast<const base::DictionaryValue*>(value));
|
||||
|
||||
case base::Value::TYPE_BINARY:
|
||||
return ToArrayBuffer(isolate,
|
||||
static_cast<const base::BinaryValue*>(value));
|
||||
|
||||
default:
|
||||
LOG(ERROR) << "Unexpected value type: " << value->GetType();
|
||||
return v8::Null(isolate);
|
||||
|
@ -200,6 +204,13 @@ v8::Local<v8::Value> V8ValueConverter::ToV8Object(
|
|||
return result.GetHandle();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> V8ValueConverter::ToArrayBuffer(
|
||||
v8::Isolate* isolate, const base::BinaryValue* value) const {
|
||||
return node::Buffer::Copy(isolate,
|
||||
value->GetBuffer(),
|
||||
value->GetSize()).ToLocalChecked();
|
||||
}
|
||||
|
||||
base::Value* V8ValueConverter::FromV8ValueImpl(
|
||||
FromV8ValueState* state,
|
||||
v8::Local<v8::Value> val,
|
||||
|
|
|
@ -41,6 +41,9 @@ class V8ValueConverter {
|
|||
v8::Local<v8::Value> ToV8Object(
|
||||
v8::Isolate* isolate,
|
||||
const base::DictionaryValue* dictionary) const;
|
||||
v8::Local<v8::Value> ToArrayBuffer(
|
||||
v8::Isolate* isolate,
|
||||
const base::BinaryValue* value) const;
|
||||
|
||||
base::Value* FromV8ValueImpl(FromV8ValueState* state,
|
||||
v8::Local<v8::Value> value,
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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[];
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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()`
|
||||
|
||||
모든 전역 단축키 등록을 해제합니다.
|
||||
모든 전역 단축키의 등록을 해제합니다.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
53
docs-translations/pt-BR/tutorial/debugging-main-process.md
Normal file
53
docs-translations/pt-BR/tutorial/debugging-main-process.md
Normal 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
|
|
@ -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
|
83
docs-translations/pt-BR/tutorial/online-offline-events.md
Normal file
83
docs-translations/pt-BR/tutorial/online-offline-events.md
Normal 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>
|
||||
```
|
|
@ -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.
|
|
@ -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>
|
||||
```
|
|
@ -1,5 +1,6 @@
|
|||
## 向导
|
||||
|
||||
* [支持平台](tutorial/supported-platforms.md)
|
||||
* [应用部署](tutorial/application-distribution.md)
|
||||
* [应用打包](tutorial/application-packaging.md)
|
||||
* [使用原生模块](tutorial/using-native-node-modules.md)
|
||||
|
|
68
docs-translations/zh-CN/api/ipc-main-process.md
Normal file
68
docs-translations/zh-CN/api/ipc-main-process.md
Normal 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` (选用)
|
||||
|
||||
这个可以发送一个可带参数的异步消息回渲染进程.
|
109
docs-translations/zh-CN/tutorial/application-distribution.md
Normal file
109
docs-translations/zh-CN/tutorial/application-distribution.md
Normal 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 模块以匹配这个新的可执行文件的名称。
|
48
docs-translations/zh-CN/tutorial/debugging-main-process.md
Normal file
48
docs-translations/zh-CN/tutorial/debugging-main-process.md
Normal 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
|
27
docs-translations/zh-CN/tutorial/supported-platforms.md
Normal file
27
docs-translations/zh-CN/tutorial/supported-platforms.md
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
});
|
||||
});
|
||||
```
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`
|
||||
|
|
115
docs/tutorial/mac-app-store-submission-guide.md
Normal file
115
docs/tutorial/mac-app-store-submission-guide.md
Normal 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/
|
|
@ -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',
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
2
vendor/brightray
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 375436a777a793f4815f38c13a5226fcd82de567
|
||||
Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0
|
Loading…
Reference in a new issue