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',
|
'product_name%': 'Electron',
|
||||||
'company_name%': 'GitHub, Inc',
|
'company_name%': 'GitHub, Inc',
|
||||||
'company_abbr%': 'github',
|
'company_abbr%': 'github',
|
||||||
'version%': '0.33.7',
|
'version%': '0.34.0',
|
||||||
},
|
},
|
||||||
'includes': [
|
'includes': [
|
||||||
'filenames.gypi',
|
'filenames.gypi',
|
||||||
|
@ -64,9 +64,6 @@
|
||||||
'files': [
|
'files': [
|
||||||
'<(PRODUCT_DIR)/<(product_name) Helper.app',
|
'<(PRODUCT_DIR)/<(product_name) Helper.app',
|
||||||
'<(PRODUCT_DIR)/<(product_name) Framework.framework',
|
'<(PRODUCT_DIR)/<(product_name) Framework.framework',
|
||||||
'external_binaries/Squirrel.framework',
|
|
||||||
'external_binaries/ReactiveCocoa.framework',
|
|
||||||
'external_binaries/Mantle.framework',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -109,7 +106,21 @@
|
||||||
'<@(locale_dirs)',
|
'<@(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"
|
}, { # OS=="mac"
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'make_locale_paks',
|
'make_locale_paks',
|
||||||
|
@ -285,12 +296,28 @@
|
||||||
'vendor/breakpad/breakpad.gyp:breakpad_sender',
|
'vendor/breakpad/breakpad.gyp:breakpad_sender',
|
||||||
],
|
],
|
||||||
}], # OS=="win"
|
}], # OS=="win"
|
||||||
['OS=="mac"', {
|
['OS=="mac" and mas_build==0', {
|
||||||
'dependencies': [
|
'dependencies': [
|
||||||
'vendor/crashpad/client/client.gyp:crashpad_client',
|
'vendor/crashpad/client/client.gyp:crashpad_client',
|
||||||
'vendor/crashpad/handler/handler.gyp:crashpad_handler',
|
'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"', {
|
['OS=="linux"', {
|
||||||
'link_settings': {
|
'link_settings': {
|
||||||
'ldflags': [
|
'ldflags': [
|
||||||
|
@ -393,9 +420,6 @@
|
||||||
'libraries': [
|
'libraries': [
|
||||||
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
|
'$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
|
||||||
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
|
||||||
'external_binaries/Squirrel.framework',
|
|
||||||
'external_binaries/ReactiveCocoa.framework',
|
|
||||||
'external_binaries/Mantle.framework',
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'mac_bundle': 1,
|
'mac_bundle': 1,
|
||||||
|
@ -439,12 +463,6 @@
|
||||||
'<@(copied_libraries)',
|
'<@(copied_libraries)',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'destination': '<(PRODUCT_DIR)/<(product_name) Framework.framework/Versions/A/Resources',
|
|
||||||
'files': [
|
|
||||||
'<(PRODUCT_DIR)/crashpad_handler',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
'postbuilds': [
|
'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 framework
|
||||||
{
|
{
|
||||||
'target_name': '<(project_name)_helper',
|
'target_name': '<(project_name)_helper',
|
||||||
|
|
|
@ -21,6 +21,15 @@
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool IsBrowserProcess(base::CommandLine* cmd) {
|
||||||
|
std::string process_type = cmd->GetSwitchValueASCII(switches::kProcessType);
|
||||||
|
return process_type.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
AtomMainDelegate::AtomMainDelegate() {
|
AtomMainDelegate::AtomMainDelegate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,11 +37,14 @@ AtomMainDelegate::~AtomMainDelegate() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||||
|
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
|
||||||
logging::LoggingSettings settings;
|
logging::LoggingSettings settings;
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// On Windows the terminal returns immediately, so we add a new line to
|
// On Windows the terminal returns immediately, so we add a new line to
|
||||||
// prevent output in the same line as the prompt.
|
// prevent output in the same line as the prompt.
|
||||||
std::wcout << std::endl;
|
if (IsBrowserProcess(command_line))
|
||||||
|
std::wcout << std::endl;
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
// Print logging to debug.log on Windows
|
// Print logging to debug.log on Windows
|
||||||
settings.logging_dest = logging::LOG_TO_ALL;
|
settings.logging_dest = logging::LOG_TO_ALL;
|
||||||
|
@ -47,9 +59,10 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||||
#endif // !defined(OS_WIN)
|
#endif // !defined(OS_WIN)
|
||||||
|
|
||||||
// Only enable logging when --enable-logging is specified.
|
// 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;
|
settings.logging_dest = logging::LOG_NONE;
|
||||||
|
logging::SetMinLogLevel(logging::LOG_NUM_SEVERITIES);
|
||||||
|
}
|
||||||
|
|
||||||
logging::InitLogging(settings);
|
logging::InitLogging(settings);
|
||||||
|
|
||||||
|
@ -81,7 +94,7 @@ void AtomMainDelegate::PreSandboxStartup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only append arguments for browser process.
|
// Only append arguments for browser process.
|
||||||
if (!process_type.empty())
|
if (!IsBrowserProcess(command_line))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "atom/browser/api/atom_api_download_item.h"
|
#include "atom/browser/api/atom_api_download_item.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/api/atom_api_web_contents.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/callback.h"
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||||
|
@ -237,6 +238,8 @@ Session::~Session() {
|
||||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||||
content::DownloadItem* item) {
|
content::DownloadItem* item) {
|
||||||
auto web_contents = item->GetWebContents();
|
auto web_contents = item->GetWebContents();
|
||||||
|
if (SavePageHandler::IsSavePageTypes(item->GetMimeType()))
|
||||||
|
return;
|
||||||
bool prevent_default = Emit(
|
bool prevent_default = Emit(
|
||||||
"will-download",
|
"will-download",
|
||||||
DownloadItem::Create(isolate(), item),
|
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
|
} // namespace mate
|
||||||
|
|
||||||
|
|
||||||
|
@ -665,6 +685,13 @@ void WebContents::InsertCSS(const std::string& css) {
|
||||||
web_contents()->InsertCSS(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,
|
void WebContents::ExecuteJavaScript(const base::string16& code,
|
||||||
bool has_user_gesture) {
|
bool has_user_gesture) {
|
||||||
Send(new AtomViewMsg_ExecuteJavaScript(routing_id(), code, 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("setUserAgent", &WebContents::SetUserAgent)
|
||||||
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
|
||||||
.SetMethod("insertCSS", &WebContents::InsertCSS)
|
.SetMethod("insertCSS", &WebContents::InsertCSS)
|
||||||
|
.SetMethod("savePage", &WebContents::SavePage)
|
||||||
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
|
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
|
||||||
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
.SetMethod("openDevTools", &WebContents::OpenDevTools)
|
||||||
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/browser/api/frame_subscriber.h"
|
#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/api/trackable_object.h"
|
||||||
#include "atom/browser/common_web_contents_delegate.h"
|
#include "atom/browser/common_web_contents_delegate.h"
|
||||||
#include "content/public/browser/web_contents_observer.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);
|
void SetUserAgent(const std::string& user_agent);
|
||||||
std::string GetUserAgent();
|
std::string GetUserAgent();
|
||||||
void InsertCSS(const std::string& css);
|
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,
|
void ExecuteJavaScript(const base::string16& code,
|
||||||
bool has_user_gesture);
|
bool has_user_gesture);
|
||||||
void OpenDevTools(mate::Arguments* args);
|
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;
|
delegate_ = delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX) && defined(MAS_BUILD)
|
||||||
|
void AutoUpdater::SetFeedURL(const std::string& url) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoUpdater::CheckForUpdates() {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace auto_updater
|
} // namespace auto_updater
|
||||||
|
|
|
@ -69,7 +69,9 @@ unwrapArgs = (sender, args) ->
|
||||||
rendererReleased = true
|
rendererReleased = true
|
||||||
|
|
||||||
ret = ->
|
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)
|
sender.send 'ATOM_RENDERER_CALLBACK', meta.id, valueToMeta(sender, arguments)
|
||||||
v8Util.setDestructor ret, ->
|
v8Util.setDestructor ret, ->
|
||||||
return if rendererReleased
|
return if rendererReleased
|
||||||
|
|
|
@ -116,7 +116,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||||
} else if (options.Get(switches::kCenter, ¢er) && center) {
|
} else if (options.Get(switches::kCenter, ¢er) && 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;
|
int min_height = 0, min_width = 0;
|
||||||
if (options.Get(switches::kMinHeight, &min_height) |
|
if (options.Get(switches::kMinHeight, &min_height) |
|
||||||
options.Get(switches::kMinWidth, &min_width)) {
|
options.Get(switches::kMinWidth, &min_width)) {
|
||||||
|
|
|
@ -390,7 +390,10 @@ gfx::Size NativeWindowViews::GetContentSize() {
|
||||||
void NativeWindowViews::SetContentSizeConstraints(
|
void NativeWindowViews::SetContentSizeConstraints(
|
||||||
const extensions::SizeConstraints& size_constraints) {
|
const extensions::SizeConstraints& size_constraints) {
|
||||||
NativeWindow::SetContentSizeConstraints(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 defined(USE_X11)
|
||||||
if (resizable_)
|
if (resizable_)
|
||||||
old_size_constraints_ = size_constraints;
|
old_size_constraints_ = size_constraints;
|
||||||
|
|
|
@ -17,7 +17,11 @@
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>atom.icns</string>
|
<string>atom.icns</string>
|
||||||
<key>CFBundleVersion</key>
|
<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>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.8.0</string>
|
<string>10.8.0</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
|
|
|
@ -56,8 +56,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,33,7,0
|
FILEVERSION 0,34,0,0
|
||||||
PRODUCTVERSION 0,33,7,0
|
PRODUCTVERSION 0,34,0,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -74,12 +74,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "GitHub, Inc."
|
VALUE "CompanyName", "GitHub, Inc."
|
||||||
VALUE "FileDescription", "Electron"
|
VALUE "FileDescription", "Electron"
|
||||||
VALUE "FileVersion", "0.33.7"
|
VALUE "FileVersion", "0.34.0"
|
||||||
VALUE "InternalName", "electron.exe"
|
VALUE "InternalName", "electron.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||||
VALUE "OriginalFilename", "electron.exe"
|
VALUE "OriginalFilename", "electron.exe"
|
||||||
VALUE "ProductName", "Electron"
|
VALUE "ProductName", "Electron"
|
||||||
VALUE "ProductVersion", "0.33.7"
|
VALUE "ProductVersion", "0.34.0"
|
||||||
VALUE "SquirrelAwareVersion", "1"
|
VALUE "SquirrelAwareVersion", "1"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
|
@ -26,7 +26,6 @@ namespace {
|
||||||
const char* kWebRuntimeFeatures[] = {
|
const char* kWebRuntimeFeatures[] = {
|
||||||
switches::kExperimentalFeatures,
|
switches::kExperimentalFeatures,
|
||||||
switches::kExperimentalCanvasFeatures,
|
switches::kExperimentalCanvasFeatures,
|
||||||
switches::kSubpixelFontScaling,
|
|
||||||
switches::kOverlayScrollbars,
|
switches::kOverlayScrollbars,
|
||||||
switches::kOverlayFullscreenVideo,
|
switches::kOverlayFullscreenVideo,
|
||||||
switches::kSharedWorker,
|
switches::kSharedWorker,
|
||||||
|
|
|
@ -72,6 +72,10 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
||||||
// Do not warn about deprecated APIs.
|
// Do not warn about deprecated APIs.
|
||||||
dict.Set("noDeprecation", true);
|
dict.Set("noDeprecation", true);
|
||||||
|
|
||||||
|
#if defined(MAS_BUILD)
|
||||||
|
dict.Set("mas", true);
|
||||||
|
#endif
|
||||||
|
|
||||||
mate::Dictionary versions;
|
mate::Dictionary versions;
|
||||||
if (dict.Get("versions", &versions)) {
|
if (dict.Get("versions", &versions)) {
|
||||||
versions.Set(ATOM_PROJECT_NAME, ATOM_VERSION_STRING);
|
versions.Set(ATOM_PROJECT_NAME, ATOM_VERSION_STRING);
|
||||||
|
|
|
@ -1,16 +1,25 @@
|
||||||
savedGlobal = global # the "global.global" might be deleted later
|
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
class CallbacksRegistry
|
class CallbacksRegistry
|
||||||
constructor: ->
|
constructor: ->
|
||||||
@emptyFunc = -> throw new Error "Browser trying to call a non-exist callback
|
@nextId = 0
|
||||||
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."
|
|
||||||
@callbacks = {}
|
@callbacks = {}
|
||||||
|
|
||||||
add: (callback) ->
|
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
|
@callbacks[id] = callback
|
||||||
id
|
id
|
||||||
|
|
||||||
|
@ -18,10 +27,10 @@ class CallbacksRegistry
|
||||||
@callbacks[id] ? ->
|
@callbacks[id] ? ->
|
||||||
|
|
||||||
call: (id, args...) ->
|
call: (id, args...) ->
|
||||||
@get(id).call savedGlobal, args...
|
@get(id).call global, args...
|
||||||
|
|
||||||
apply: (id, args...) ->
|
apply: (id, args...) ->
|
||||||
@get(id).apply savedGlobal, args...
|
@get(id).apply global, args...
|
||||||
|
|
||||||
remove: (id) ->
|
remove: (id) ->
|
||||||
delete @callbacks[id]
|
delete @callbacks[id]
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
#define ATOM_VERSION_H
|
#define ATOM_VERSION_H
|
||||||
|
|
||||||
#define ATOM_MAJOR_VERSION 0
|
#define ATOM_MAJOR_VERSION 0
|
||||||
#define ATOM_MINOR_VERSION 33
|
#define ATOM_MINOR_VERSION 34
|
||||||
#define ATOM_PATCH_VERSION 7
|
#define ATOM_PATCH_VERSION 0
|
||||||
|
|
||||||
#define ATOM_VERSION_IS_RELEASE 1
|
#define ATOM_VERSION_IS_RELEASE 1
|
||||||
|
|
||||||
|
|
|
@ -64,4 +64,23 @@ CrashReporter::GetUploadedReports(const std::string& path) {
|
||||||
return result;
|
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
|
} // namespace crash_reporter
|
||||||
|
|
|
@ -40,8 +40,8 @@ class CrashReporter {
|
||||||
const std::string& company_name,
|
const std::string& company_name,
|
||||||
const std::string& submit_url,
|
const std::string& submit_url,
|
||||||
bool auto_submit,
|
bool auto_submit,
|
||||||
bool skip_system_crash_handler) = 0;
|
bool skip_system_crash_handler);
|
||||||
virtual void SetUploadParameters() = 0;
|
virtual void SetUploadParameters();
|
||||||
|
|
||||||
StringMap upload_parameters_;
|
StringMap upload_parameters_;
|
||||||
bool is_browser_;
|
bool is_browser_;
|
||||||
|
|
|
@ -11,6 +11,25 @@
|
||||||
#include "base/memory/singleton.h"
|
#include "base/memory/singleton.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/utf_string_conversions.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 {
|
namespace crash_reporter {
|
||||||
|
|
||||||
|
@ -24,6 +43,94 @@ const MINIDUMP_TYPE kSmallDumpType = static_cast<MINIDUMP_TYPE>(
|
||||||
const wchar_t kWaitEventFormat[] = L"$1CrashServiceWaitEvent";
|
const wchar_t kWaitEventFormat[] = L"$1CrashServiceWaitEvent";
|
||||||
const wchar_t kPipeNameFormat[] = L"\\\\.\\pipe\\$1 Crash Service";
|
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
|
} // namespace
|
||||||
|
|
||||||
CrashReporterWin::CrashReporterWin() {
|
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.
|
// to allow any previous handler to detach in the correct order.
|
||||||
breakpad_.reset();
|
breakpad_.reset();
|
||||||
|
|
||||||
int handler_types = google_breakpad::ExceptionHandler::HANDLER_EXCEPTION |
|
|
||||||
google_breakpad::ExceptionHandler::HANDLER_PURECALL;
|
|
||||||
breakpad_.reset(new google_breakpad::ExceptionHandler(
|
breakpad_.reset(new google_breakpad::ExceptionHandler(
|
||||||
temp_dir.value(),
|
temp_dir.value(),
|
||||||
FilterCallback,
|
FilterCallback,
|
||||||
MinidumpCallback,
|
MinidumpCallback,
|
||||||
this,
|
this,
|
||||||
handler_types,
|
google_breakpad::ExceptionHandler::HANDLER_ALL,
|
||||||
kSmallDumpType,
|
kSmallDumpType,
|
||||||
pipe_name.c_str(),
|
pipe_name.c_str(),
|
||||||
GetCustomInfo(product_name, version, company_name)));
|
GetCustomInfo(product_name, version, company_name)));
|
||||||
|
|
||||||
if (!breakpad_->IsOutOfProcess())
|
if (!breakpad_->IsOutOfProcess())
|
||||||
LOG(ERROR) << "Cannot initialize out-of-process crash handler";
|
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() {
|
void CrashReporterWin::SetUploadParameters() {
|
||||||
upload_parameters_["platform"] = "win32";
|
upload_parameters_["platform"] = "win32";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CrashReporterWin::CrashForException(EXCEPTION_POINTERS* info) {
|
||||||
|
if (breakpad_) {
|
||||||
|
breakpad_->WriteMinidumpForException(info);
|
||||||
|
TerminateProcessWithoutDump();
|
||||||
|
}
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool CrashReporterWin::FilterCallback(void* context,
|
bool CrashReporterWin::FilterCallback(void* context,
|
||||||
EXCEPTION_POINTERS* exinfo,
|
EXCEPTION_POINTERS* exinfo,
|
||||||
|
|
|
@ -29,6 +29,9 @@ class CrashReporterWin : public CrashReporter {
|
||||||
bool skip_system_crash_handler) override;
|
bool skip_system_crash_handler) override;
|
||||||
void SetUploadParameters() override;
|
void SetUploadParameters() override;
|
||||||
|
|
||||||
|
// Crashes the process after generating a dump for the provided exception.
|
||||||
|
int CrashForException(EXCEPTION_POINTERS* info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct DefaultSingletonTraits<CrashReporterWin>;
|
friend struct DefaultSingletonTraits<CrashReporterWin>;
|
||||||
|
|
||||||
|
|
|
@ -311,7 +311,7 @@ bool CrashService::Initialize(const base::string16& application_name,
|
||||||
// service is initialized.
|
// service is initialized.
|
||||||
base::string16 wait_name = ReplaceStringPlaceholders(
|
base::string16 wait_name = ReplaceStringPlaceholders(
|
||||||
kWaitEventFormat, application_name, NULL);
|
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);
|
::SetEvent(wait_event);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -152,6 +152,10 @@ v8::Local<v8::Value> V8ValueConverter::ToV8ValueImpl(
|
||||||
return ToV8Object(isolate,
|
return ToV8Object(isolate,
|
||||||
static_cast<const base::DictionaryValue*>(value));
|
static_cast<const base::DictionaryValue*>(value));
|
||||||
|
|
||||||
|
case base::Value::TYPE_BINARY:
|
||||||
|
return ToArrayBuffer(isolate,
|
||||||
|
static_cast<const base::BinaryValue*>(value));
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG(ERROR) << "Unexpected value type: " << value->GetType();
|
LOG(ERROR) << "Unexpected value type: " << value->GetType();
|
||||||
return v8::Null(isolate);
|
return v8::Null(isolate);
|
||||||
|
@ -200,6 +204,13 @@ v8::Local<v8::Value> V8ValueConverter::ToV8Object(
|
||||||
return result.GetHandle();
|
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(
|
base::Value* V8ValueConverter::FromV8ValueImpl(
|
||||||
FromV8ValueState* state,
|
FromV8ValueState* state,
|
||||||
v8::Local<v8::Value> val,
|
v8::Local<v8::Value> val,
|
||||||
|
|
|
@ -41,6 +41,9 @@ class V8ValueConverter {
|
||||||
v8::Local<v8::Value> ToV8Object(
|
v8::Local<v8::Value> ToV8Object(
|
||||||
v8::Isolate* isolate,
|
v8::Isolate* isolate,
|
||||||
const base::DictionaryValue* dictionary) const;
|
const base::DictionaryValue* dictionary) const;
|
||||||
|
v8::Local<v8::Value> ToArrayBuffer(
|
||||||
|
v8::Isolate* isolate,
|
||||||
|
const base::BinaryValue* value) const;
|
||||||
|
|
||||||
base::Value* FromV8ValueImpl(FromV8ValueState* state,
|
base::Value* FromV8ValueImpl(FromV8ValueState* state,
|
||||||
v8::Local<v8::Value> value,
|
v8::Local<v8::Value> value,
|
||||||
|
|
|
@ -99,7 +99,6 @@ const char kClientCertificate[] = "client-certificate";
|
||||||
// Web runtime features.
|
// Web runtime features.
|
||||||
const char kExperimentalFeatures[] = "experimental-features";
|
const char kExperimentalFeatures[] = "experimental-features";
|
||||||
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
||||||
const char kSubpixelFontScaling[] = "subpixel-font-scaling";
|
|
||||||
const char kOverlayScrollbars[] = "overlay-scrollbars";
|
const char kOverlayScrollbars[] = "overlay-scrollbars";
|
||||||
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
|
const char kOverlayFullscreenVideo[] = "overlay-fullscreen-video";
|
||||||
const char kSharedWorker[] = "shared-worker";
|
const char kSharedWorker[] = "shared-worker";
|
||||||
|
|
|
@ -51,7 +51,6 @@ extern const char kClientCertificate[];
|
||||||
|
|
||||||
extern const char kExperimentalFeatures[];
|
extern const char kExperimentalFeatures[];
|
||||||
extern const char kExperimentalCanvasFeatures[];
|
extern const char kExperimentalCanvasFeatures[];
|
||||||
extern const char kSubpixelFontScaling[];
|
|
||||||
extern const char kOverlayScrollbars[];
|
extern const char kOverlayScrollbars[];
|
||||||
extern const char kOverlayFullscreenVideo[];
|
extern const char kOverlayFullscreenVideo[];
|
||||||
extern const char kSharedWorker[];
|
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">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CFBundleExecutable</key>
|
|
||||||
<string>${PRODUCT_NAME} Framework</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>${ATOM_BUNDLE_ID}</string>
|
<string>${ATOM_BUNDLE_ID}</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>${PRODUCT_NAME} Framework</string>
|
<string>${PRODUCT_NAME}</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>${PRODUCT_NAME}</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>FMWK</string>
|
<string>FMWK</string>
|
||||||
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
<key>NSSupportsAutomaticGraphicsSwitching</key>
|
||||||
|
|
|
@ -234,8 +234,6 @@ void AtomRendererClient::EnableWebRuntimeFeatures() {
|
||||||
blink::WebRuntimeFeatures::enableExperimentalFeatures(b);
|
blink::WebRuntimeFeatures::enableExperimentalFeatures(b);
|
||||||
if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures, &b))
|
if (IsSwitchEnabled(command_line, switches::kExperimentalCanvasFeatures, &b))
|
||||||
blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(b);
|
blink::WebRuntimeFeatures::enableExperimentalCanvasFeatures(b);
|
||||||
if (IsSwitchEnabled(command_line, switches::kSubpixelFontScaling, &b))
|
|
||||||
blink::WebRuntimeFeatures::enableSubpixelFontScaling(b);
|
|
||||||
if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars, &b))
|
if (IsSwitchEnabled(command_line, switches::kOverlayScrollbars, &b))
|
||||||
blink::WebRuntimeFeatures::enableOverlayScrollbars(b);
|
blink::WebRuntimeFeatures::enableOverlayScrollbars(b);
|
||||||
if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo, &b))
|
if (IsSwitchEnabled(command_line, switches::kOverlayFullscreenVideo, &b))
|
||||||
|
|
|
@ -12,7 +12,9 @@ var globalShortcut = require('global-shortcut');
|
||||||
|
|
||||||
app.on('ready', function() {
|
app.on('ready', function() {
|
||||||
// 'ctrl+x' 단축키를 리스너에 등록합니다.
|
// '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) {
|
if (!ret) {
|
||||||
console.log('registration failed');
|
console.log('registration failed');
|
||||||
|
@ -56,4 +58,4 @@ app.on('will-quit', function() {
|
||||||
|
|
||||||
### `globalShortcut.unregisterAll()`
|
### `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
|
### Events
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,17 @@ $ cd /some-directory
|
||||||
$ git clone --recursive https://github.com/facebook/react-devtools.git
|
$ 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
|
```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
|
```javascript
|
||||||
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools');
|
require('remote').require('browser-window').removeDevToolsExtension('React Developer Tools');
|
||||||
|
@ -29,13 +33,13 @@ require('remote').require('browser-window').removeDevToolsExtension('React Devel
|
||||||
## 개발자 콘솔 확장 기능의 구성 형식
|
## 개발자 콘솔 확장 기능의 구성 형식
|
||||||
|
|
||||||
모든 개발자 콘솔 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다.
|
모든 개발자 콘솔 확장은 완벽히 Chrome 브라우저를 위해 작성되었기 때문에 Electron에서도 로드할 수 있습니다.
|
||||||
하지만 반드시 확장 기능은 소스코드 그대로의 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우
|
하지만 반드시 확장 기능은 소스 코드 디렉터리(폴더) 형태여야 합니다. 그래서 `crx` 등의 포맷으로 패키징된 확장 기능의 경우
|
||||||
사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상은 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다.
|
사용자가 직접 해당 패키지의 압축을 풀어서 로드하지 않는 이상 Electron에서 해당 확장 기능의 압축을 풀 방법이 없습니다.
|
||||||
|
|
||||||
## 백그라운드 페이지
|
## 백그라운드 페이지
|
||||||
|
|
||||||
현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 않습니다.
|
현재 Electron은 Chrome에서 지원하는 백그라운드 페이지(background pages)를 지원하지 않습니다.
|
||||||
몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데 이 경우 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다.
|
몇몇 확장 기능은 이 기능에 의존하는 경우가 있는데, 이 때 해당 확장 기능은 Electron에서 작동하지 않을 수 있습니다.
|
||||||
|
|
||||||
## `chrome.*` API
|
## `chrome.*` API
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
## Guias
|
## 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)
|
* [Empacotamento da aplicação](tutorial/application-packaging.md)
|
||||||
* [Usando módulos nativos](../../docs/tutorial/using-native-node-modules.md)
|
* [Usando módulos nativos](tutorial/using-native-node-modules.md)
|
||||||
* [Depuração do processo principal](../../docs/tutorial/debugging-main-process.md)
|
* [Depuração do processo principal](tutorial/debugging-main-process.md)
|
||||||
* [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md)
|
* [Usando Selenium e WebDriver](../../docs/tutorial/using-selenium-and-webdriver.md)
|
||||||
* [Extensão DevTools](../../docs/tutorial/devtools-extension.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
|
## Tutoriais
|
||||||
|
|
||||||
* [Introdução](../../docs/tutorial/quick-start.md)
|
* [Introdução](tutorial/quick-start.md)
|
||||||
* [A integração com o ambiente de desenvolvimento](../../docs/tutorial/desktop-environment-integration.md)
|
* [A integração com o ambiente de desenvolvimento](tutorial/desktop-environment-integration.md)
|
||||||
* [Evento de detecção on-line/off-line](../../docs/tutorial/online-offline-events.md)
|
* [Evento de detecção on-line/off-line](tutorial/online-offline-events.md)
|
||||||
|
|
||||||
## API - Referencias
|
## 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 (Mac)](../../docs/development/build-instructions-osx.md)
|
||||||
* [Instrução de build (Windows)](../../docs/development/build-instructions-windows.md)
|
* [Instrução de build (Windows)](../../docs/development/build-instructions-windows.md)
|
||||||
* [Instrução de build (Linux)](../../docs/development/build-instructions-linux.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-distribution.md)
|
||||||
* [应用打包](tutorial/application-packaging.md)
|
* [应用打包](tutorial/application-packaging.md)
|
||||||
* [使用原生模块](tutorial/using-native-node-modules.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)
|
* [Supported Platforms](tutorial/supported-platforms.md)
|
||||||
* [Application Distribution](tutorial/application-distribution.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)
|
* [Application Packaging](tutorial/application-packaging.md)
|
||||||
* [Using Native Node Modules](tutorial/using-native-node-modules.md)
|
* [Using Native Node Modules](tutorial/using-native-node-modules.md)
|
||||||
* [Debugging Main Process](tutorial/debugging-main-process.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.
|
* `plugins` Boolean - Whether plugins should be enabled.
|
||||||
* `experimental-features` Boolean
|
* `experimental-features` Boolean
|
||||||
* `experimental-canvas-features` Boolean
|
* `experimental-canvas-features` Boolean
|
||||||
* `subpixel-font-scaling` Boolean
|
|
||||||
* `overlay-scrollbars` Boolean
|
* `overlay-scrollbars` Boolean
|
||||||
* `overlay-fullscreen-video` Boolean
|
* `overlay-fullscreen-video` Boolean
|
||||||
* `shared-worker` Boolean
|
* `shared-worker` Boolean
|
||||||
|
|
|
@ -8,6 +8,8 @@ upstream node:
|
||||||
* `process.versions['electron']` String - Version of Electron.
|
* `process.versions['electron']` String - Version of Electron.
|
||||||
* `process.versions['chrome']` String - Version of Chromium.
|
* `process.versions['chrome']` String - Version of Chromium.
|
||||||
* `process.resourcesPath` String - Path to JavaScript source code.
|
* `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
|
## Events
|
||||||
|
|
||||||
|
@ -37,7 +39,7 @@ The `process` object has the following method:
|
||||||
|
|
||||||
Causes the main thread of the current process hang.
|
Causes the main thread of the current process hang.
|
||||||
|
|
||||||
### process.setFdLimit(maxDescriptors) _OS X_ _Linux_
|
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
|
||||||
|
|
||||||
* `maxDescriptors` Integer
|
* `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`
|
**Note:** Users should never store this object because it may become `null`
|
||||||
when the DevTools has been closed.
|
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
|
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
|
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:
|
On OS X:
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ window.setProgressBar(0.5);
|
||||||
## Represented File of Window (OS X)
|
## Represented File of Window (OS X)
|
||||||
|
|
||||||
On OS X a window can set its represented file, so the file's icon can show in
|
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.
|
popup will show.
|
||||||
|
|
||||||
You can also set the edited state of a window so that the file icon can indicate
|
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
|
$ 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,
|
Then you can load the extension in Electron by opening DevTools in any window,
|
||||||
and running the following code in the DevTools console:
|
and running the following code in the DevTools console:
|
||||||
|
|
||||||
```javascript
|
```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`
|
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/trackable_object.h',
|
||||||
'atom/browser/api/frame_subscriber.cc',
|
'atom/browser/api/frame_subscriber.cc',
|
||||||
'atom/browser/api/frame_subscriber.h',
|
'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.cc',
|
||||||
'atom/browser/auto_updater.h',
|
'atom/browser/auto_updater.h',
|
||||||
'atom/browser/auto_updater_delegate.h',
|
'atom/browser/auto_updater_delegate.h',
|
||||||
|
|
|
@ -106,10 +106,11 @@ def update_info_plist(version):
|
||||||
line = lines[i]
|
line = lines[i]
|
||||||
if 'CFBundleVersion' in line:
|
if 'CFBundleVersion' in line:
|
||||||
lines[i + 1] = ' <string>{0}</string>\n'.format(version)
|
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:
|
with open(info_plist, 'w') as f:
|
||||||
f.write(''.join(lines))
|
f.write(''.join(lines))
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
def tag_version(version):
|
def tag_version(version):
|
||||||
|
|
|
@ -8,7 +8,8 @@ import sys
|
||||||
import stat
|
import stat
|
||||||
|
|
||||||
from lib.config import LIBCHROMIUMCONTENT_COMMIT, BASE_URL, PLATFORM, \
|
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, \
|
from lib.util import scoped_cwd, rm_rf, get_atom_shell_version, make_zip, \
|
||||||
execute, atom_gyp
|
execute, atom_gyp
|
||||||
|
|
||||||
|
@ -170,7 +171,8 @@ def create_symbols():
|
||||||
|
|
||||||
def create_dist_zip():
|
def create_dist_zip():
|
||||||
dist_name = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION,
|
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)
|
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
|
||||||
|
|
||||||
with scoped_cwd(DIST_DIR):
|
with scoped_cwd(DIST_DIR):
|
||||||
|
@ -182,7 +184,7 @@ def create_dist_zip():
|
||||||
|
|
||||||
|
|
||||||
def create_chrome_binary_zip(binary, version):
|
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())
|
get_target_arch())
|
||||||
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
|
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():
|
def create_symbols_zip():
|
||||||
dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
|
dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
|
||||||
ATOM_SHELL_VERSION,
|
ATOM_SHELL_VERSION,
|
||||||
PLATFORM,
|
get_platform_key(),
|
||||||
get_target_arch())
|
get_target_arch())
|
||||||
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
|
zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,8 @@ import sys
|
||||||
|
|
||||||
|
|
||||||
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
|
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
|
||||||
'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent'
|
'http://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
|
||||||
LIBCHROMIUMCONTENT_COMMIT = '04523758cda2a96d2454f9056fb1fb9a1c1f95f1'
|
LIBCHROMIUMCONTENT_COMMIT = '78e54bc39a04b758ed5167cd980cc4d9951bd629'
|
||||||
|
|
||||||
PLATFORM = {
|
PLATFORM = {
|
||||||
'cygwin': 'win32',
|
'cygwin': 'win32',
|
||||||
|
@ -20,6 +20,13 @@ PLATFORM = {
|
||||||
verbose_mode = False
|
verbose_mode = False
|
||||||
|
|
||||||
|
|
||||||
|
def get_platform_key():
|
||||||
|
if os.environ.has_key('MAS_BUILD'):
|
||||||
|
return 'mas'
|
||||||
|
else:
|
||||||
|
return PLATFORM
|
||||||
|
|
||||||
|
|
||||||
def get_target_arch():
|
def get_target_arch():
|
||||||
try:
|
try:
|
||||||
target_arch_path = os.path.join(__file__, '..', '..', '..', 'vendor',
|
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.
|
# Avoid using the old gyp lib in system.
|
||||||
env['PYTHONPATH'] = os.path.pathsep.join([gyp_pylib,
|
env['PYTHONPATH'] = os.path.pathsep.join([gyp_pylib,
|
||||||
env.get('PYTHONPATH', '')])
|
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 = [
|
defines = [
|
||||||
'-Dlibchromiumcontent_component={0}'.format(component),
|
'-Dlibchromiumcontent_component={0}'.format(component),
|
||||||
'-Dtarget_arch={0}'.format(target_arch),
|
'-Dtarget_arch={0}'.format(target_arch),
|
||||||
'-Dhost_arch={0}'.format(get_host_arch()),
|
'-Dhost_arch={0}'.format(get_host_arch()),
|
||||||
'-Dlibrary=static_library',
|
'-Dlibrary=static_library',
|
||||||
|
'-Dmas_build={0}'.format(mas_build),
|
||||||
]
|
]
|
||||||
return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
|
return subprocess.call([python, gyp, '-f', 'ninja', '--depth', '.',
|
||||||
'atom.gyp', '-Icommon.gypi'] + defines, env=env)
|
'atom.gyp', '-Icommon.gypi'] + defines, env=env)
|
||||||
|
|
|
@ -7,7 +7,8 @@ import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
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, \
|
from lib.util import atom_gyp, execute, get_atom_shell_version, parse_version, \
|
||||||
scoped_cwd
|
scoped_cwd
|
||||||
from lib.github import GitHub
|
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_DIR = os.path.join(SOURCE_ROOT, 'dist')
|
||||||
DIST_NAME = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME,
|
DIST_NAME = '{0}-{1}-{2}-{3}.zip'.format(PROJECT_NAME,
|
||||||
ATOM_SHELL_VERSION,
|
ATOM_SHELL_VERSION,
|
||||||
PLATFORM,
|
get_platform_key(),
|
||||||
get_target_arch())
|
get_target_arch())
|
||||||
SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
|
SYMBOLS_NAME = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME,
|
||||||
ATOM_SHELL_VERSION,
|
ATOM_SHELL_VERSION,
|
||||||
PLATFORM,
|
get_platform_key(),
|
||||||
get_target_arch())
|
get_target_arch())
|
||||||
MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION,
|
MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION,
|
||||||
PLATFORM,
|
get_platform_key(),
|
||||||
get_target_arch())
|
get_target_arch())
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ def main():
|
||||||
# Upload chromedriver and mksnapshot for minor version update.
|
# Upload chromedriver and mksnapshot for minor version update.
|
||||||
if parse_version(args.version)[2] == '0':
|
if parse_version(args.version)[2] == '0':
|
||||||
chromedriver = 'chromedriver-{0}-{1}-{2}.zip'.format(
|
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, chromedriver))
|
||||||
upload_atom_shell(github, release, os.path.join(DIST_DIR, MKSNAPSHOT_NAME))
|
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
|
assert.notEqual data.length, 0
|
||||||
w.webContents.endFrameSubscription()
|
w.webContents.endFrameSubscription()
|
||||||
done()
|
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)
|
beforeEach -> w = new BrowserWindow(show: false)
|
||||||
afterEach -> w.destroy()
|
afterEach -> w.destroy()
|
||||||
|
|
||||||
# It is not working on 64bit Windows.
|
# It is not working for mas build.
|
||||||
return if process.platform is 'win32' and process.arch is 'x64'
|
return if process.mas
|
||||||
|
|
||||||
# The crash-reporter test is not reliable on CI machine.
|
# The crash-reporter test is not reliable on CI machine.
|
||||||
isCI = remote.process.argv[2] == '--ci'
|
isCI = remote.process.argv[2] == '--ci'
|
||||||
|
|
|
@ -450,10 +450,10 @@ describe 'asar package', ->
|
||||||
w = new BrowserWindow(show: false, width: 400, height: 400)
|
w = new BrowserWindow(show: false, width: 400, height: 400)
|
||||||
p = path.resolve fixtures, 'asar', 'web.asar', 'index.html'
|
p = path.resolve fixtures, 'asar', 'web.asar', 'index.html'
|
||||||
u = url.format protocol: 'file', slashed: true, pathname: p
|
u = url.format protocol: 'file', slashed: true, pathname: p
|
||||||
w.loadUrl u
|
|
||||||
ipc.once 'dirname', (event, dirname) ->
|
ipc.once 'dirname', (event, dirname) ->
|
||||||
assert.equal dirname, path.dirname(p)
|
assert.equal dirname, path.dirname(p)
|
||||||
done()
|
done()
|
||||||
|
w.loadUrl u
|
||||||
|
|
||||||
it 'loads script tag in html', (done) ->
|
it 'loads script tag in html', (done) ->
|
||||||
after ->
|
after ->
|
||||||
|
|
2
vendor/brightray
vendored
2
vendor/brightray
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 375436a777a793f4815f38c13a5226fcd82de567
|
Subproject commit fe2dd437c9ef7877bf9d454db8ae401965cd7cb0
|
Loading…
Reference in a new issue