commit
090c817ac9
179 changed files with 5024 additions and 2968 deletions
|
@ -6,7 +6,7 @@
|
|||
|
||||
### [Electron](https://github.com/atom/electron/) 한국어 참조문서
|
||||
|
||||
:zap: *이전까지 Atom Shell로 알려져 있었습니다* :zap:
|
||||
:zap: *프레임워크 이름이 Atom Shell에서 Electron으로 바뀌었습니다* :zap:
|
||||
|
||||
Electron 프레임워크는 JavaScript, HTML 그리고 CSS를 사용하여 Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주는 프레임워크입니다. 이 프레임워크는 [io.js](http://iojs.org) 와
|
||||
[Chromium](http://www.chromium.org)을 기반으로 만들어 졌으며 [Atom Editor](https://github.com/atom/atom)에 사용되고 있습니다.
|
||||
|
|
|
@ -48,6 +48,8 @@ contains documents describing how to build and contribute to Electron.
|
|||
- [Korean](https://github.com/atom/electron/tree/master/docs-translations/ko)
|
||||
- [Japanese](https://github.com/atom/electron/tree/master/docs-translations/jp)
|
||||
- [Spanish](https://github.com/atom/electron/tree/master/docs-translations/es)
|
||||
- [Simplified Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-CN)
|
||||
- [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW)
|
||||
|
||||
## Community
|
||||
|
||||
|
|
2
atom.gyp
2
atom.gyp
|
@ -4,7 +4,7 @@
|
|||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.31.0',
|
||||
'version%': '0.31.2',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "atom/app/node_main.h"
|
||||
#include "atom/common/atom_command_line.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
@ -134,6 +135,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
|
|||
if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
|
||||
node_indicator == "1") {
|
||||
// Now that argv conversion is done, we can finally start.
|
||||
base::AtExitManager atexit_manager;
|
||||
base::i18n::InitializeICU();
|
||||
return atom::NodeMain(argc, argv);
|
||||
} else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
|
||||
|
@ -165,6 +167,7 @@ int main(int argc, const char* argv[]) {
|
|||
char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
|
||||
if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
|
||||
base::i18n::InitializeICU();
|
||||
base::AtExitManager atexit_manager;
|
||||
return atom::NodeMain(argc, const_cast<char**>(argv));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
|
||||
#include "atom/app/node_main.h"
|
||||
|
||||
#include "atom/app/uv_task_runner.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/node_includes.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "gin/array_buffer.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "gin/v8_initializer.h"
|
||||
|
@ -24,14 +26,20 @@ int NodeMain(int argc, char *argv[]) {
|
|||
|
||||
int exit_code = 1;
|
||||
{
|
||||
// Feed gin::PerIsolateData with a task runner.
|
||||
uv_loop_t* loop = uv_default_loop();
|
||||
scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
|
||||
base::ThreadTaskRunnerHandle handle(uv_task_runner);
|
||||
|
||||
gin::V8Initializer::LoadV8Snapshot();
|
||||
gin::V8Initializer::LoadV8Natives();
|
||||
gin::IsolateHolder::Initialize(
|
||||
gin::IsolateHolder::kNonStrictMode,
|
||||
gin::ArrayBufferAllocator::SharedInstance());
|
||||
|
||||
JavascriptEnvironment gin_env;
|
||||
node::Environment* env = node::CreateEnvironment(
|
||||
gin_env.isolate(), uv_default_loop(), gin_env.context(), argc, argv,
|
||||
gin_env.isolate(), loop, gin_env.context(), argc, argv,
|
||||
exec_argc, exec_argv);
|
||||
|
||||
// Start our custom debugger implementation.
|
||||
|
|
55
atom/app/uv_task_runner.cc
Normal file
55
atom/app/uv_task_runner.cc
Normal file
|
@ -0,0 +1,55 @@
|
|||
// 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/app/uv_task_runner.h"
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
|
||||
}
|
||||
|
||||
UvTaskRunner::~UvTaskRunner() {
|
||||
for (auto& iter : tasks_) {
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(iter.first));
|
||||
delete iter.first;
|
||||
}
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
uv_timer_t* timer = new uv_timer_t;
|
||||
timer->data = this;
|
||||
uv_timer_init(loop_, timer);
|
||||
uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
|
||||
tasks_[timer] = task;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::RunsTasksOnCurrentThread() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UvTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
return PostDelayedTask(from_here, task, delay);;
|
||||
}
|
||||
|
||||
// static
|
||||
void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
|
||||
UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
|
||||
if (!ContainsKey(self->tasks_, timer))
|
||||
return;
|
||||
|
||||
self->tasks_[timer].Run();
|
||||
self->tasks_.erase(timer);
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(timer));
|
||||
delete timer;
|
||||
}
|
||||
|
||||
} // namespace atom
|
44
atom/app/uv_task_runner.h
Normal file
44
atom/app/uv_task_runner.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_APP_UV_TASK_RUNNER_H_
|
||||
#define ATOM_APP_UV_TASK_RUNNER_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/single_thread_task_runner.h"
|
||||
#include "vendor/node/deps/uv/include/uv.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// TaskRunner implementation that posts tasks into libuv's default loop.
|
||||
class UvTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
explicit UvTaskRunner(uv_loop_t* loop);
|
||||
~UvTaskRunner() override;
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
bool RunsTasksOnCurrentThread() const override;
|
||||
bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
static void OnTimeout(uv_timer_t* timer);
|
||||
|
||||
uv_loop_t* loop_;
|
||||
|
||||
std::map<uv_timer_t*, base::Closure> tasks_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_APP_UV_TASK_RUNNER_H_
|
|
@ -19,27 +19,19 @@ using content::TracingController;
|
|||
namespace mate {
|
||||
|
||||
template<>
|
||||
struct Converter<base::trace_event::CategoryFilter> {
|
||||
struct Converter<base::trace_event::TraceConfig> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::CategoryFilter* out) {
|
||||
std::string filter;
|
||||
if (!ConvertFromV8(isolate, val, &filter))
|
||||
return false;
|
||||
*out = base::trace_event::CategoryFilter(filter);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<base::trace_event::TraceOptions> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
base::trace_event::TraceOptions* out) {
|
||||
std::string options;
|
||||
base::trace_event::TraceConfig* out) {
|
||||
Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
return out->SetFromString(options);
|
||||
std::string category_filter, trace_options;
|
||||
if (!options.Get("categoryFilter", &category_filter) ||
|
||||
!options.Get("traceOptions", &trace_options))
|
||||
return false;
|
||||
*out = base::trace_event::TraceConfig(category_filter, trace_options);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -107,6 +107,10 @@ void Menu::SetSublabel(int index, const base::string16& sublabel) {
|
|||
model_->SetSublabel(index, sublabel);
|
||||
}
|
||||
|
||||
void Menu::SetRole(int index, const base::string16& role) {
|
||||
model_->SetRole(index, role);
|
||||
}
|
||||
|
||||
void Menu::Clear() {
|
||||
model_->Clear();
|
||||
}
|
||||
|
@ -154,6 +158,7 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("insertSubMenu", &Menu::InsertSubMenuAt)
|
||||
.SetMethod("setIcon", &Menu::SetIcon)
|
||||
.SetMethod("setSublabel", &Menu::SetSublabel)
|
||||
.SetMethod("setRole", &Menu::SetRole)
|
||||
.SetMethod("clear", &Menu::Clear)
|
||||
.SetMethod("getIndexOfCommandId", &Menu::GetIndexOfCommandId)
|
||||
.SetMethod("getItemCount", &Menu::GetItemCount)
|
||||
|
|
|
@ -73,6 +73,7 @@ class Menu : public mate::Wrappable,
|
|||
Menu* menu);
|
||||
void SetIcon(int index, const gfx::Image& image);
|
||||
void SetSublabel(int index, const base::string16& sublabel);
|
||||
void SetRole(int index, const base::string16& role);
|
||||
void Clear();
|
||||
int GetIndexOfCommandId(int command_id);
|
||||
int GetItemCount() const;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "atom/browser/api/atom_api_cookies.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/common/native_mate_converters/callback.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
|
@ -101,6 +102,19 @@ struct Converter<ClearStorageDataOptions> {
|
|||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Converter<content::DownloadItem*> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
content::DownloadItem* val) {
|
||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
dict.Set("url", val->GetURL());
|
||||
dict.Set("filename", val->GetSuggestedFilename());
|
||||
dict.Set("mimeType", val->GetMimeType());
|
||||
dict.Set("hasUserGesture", val->HasUserGesture());
|
||||
return dict.GetHandle();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mate
|
||||
|
||||
namespace atom {
|
||||
|
@ -109,6 +123,10 @@ namespace api {
|
|||
|
||||
namespace {
|
||||
|
||||
// The wrapSession funtion which is implemented in JavaScript
|
||||
using WrapSessionCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||
WrapSessionCallback g_wrap_session;
|
||||
|
||||
class ResolveProxyHelper {
|
||||
public:
|
||||
ResolveProxyHelper(AtomBrowserContext* browser_context,
|
||||
|
@ -215,9 +233,28 @@ void SetProxyInIO(net::URLRequestContextGetter* getter,
|
|||
Session::Session(AtomBrowserContext* browser_context)
|
||||
: browser_context_(browser_context) {
|
||||
AttachAsUserData(browser_context);
|
||||
// Observe DownloadManger to get download notifications.
|
||||
auto download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context);
|
||||
download_manager->AddObserver(this);
|
||||
}
|
||||
|
||||
Session::~Session() {
|
||||
auto download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context_);
|
||||
download_manager->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) {
|
||||
auto web_contents = item->GetWebContents();
|
||||
bool prevent_default = Emit("will-download", item,
|
||||
api::WebContents::CreateFrom(isolate(),
|
||||
web_contents));
|
||||
if (prevent_default) {
|
||||
item->Cancel(true);
|
||||
item->Remove();
|
||||
}
|
||||
}
|
||||
|
||||
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
|
||||
|
@ -288,9 +325,33 @@ mate::Handle<Session> Session::CreateFrom(
|
|||
if (existing)
|
||||
return mate::CreateHandle(isolate, static_cast<Session*>(existing));
|
||||
|
||||
return mate::CreateHandle(isolate, new Session(browser_context));
|
||||
auto handle = mate::CreateHandle(isolate, new Session(browser_context));
|
||||
g_wrap_session.Run(handle.ToV8());
|
||||
return handle;
|
||||
}
|
||||
|
||||
void SetWrapSession(const WrapSessionCallback& callback) {
|
||||
g_wrap_session = callback;
|
||||
}
|
||||
|
||||
void ClearWrapSession() {
|
||||
g_wrap_session.Reset();
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
||||
} // namespace atom
|
||||
|
||||
namespace {
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
dict.SetMethod("_setWrapSession", &atom::api::SetWrapSession);
|
||||
dict.SetMethod("_clearWrapSession", &atom::api::ClearWrapSession);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_session, Initialize)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
|
||||
|
@ -27,7 +28,8 @@ class AtomBrowserContext;
|
|||
|
||||
namespace api {
|
||||
|
||||
class Session: public mate::TrackableObject<Session> {
|
||||
class Session: public mate::TrackableObject<Session>,
|
||||
public content::DownloadManager::Observer {
|
||||
public:
|
||||
using ResolveProxyCallback = base::Callback<void(std::string)>;
|
||||
|
||||
|
@ -41,6 +43,10 @@ class Session: public mate::TrackableObject<Session> {
|
|||
explicit Session(AtomBrowserContext* browser_context);
|
||||
~Session();
|
||||
|
||||
// content::DownloadManager::Observer:
|
||||
void OnDownloadCreated(content::DownloadManager* manager,
|
||||
content::DownloadItem* item) override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
|
|
@ -159,11 +159,19 @@ WebContents::WebContents(const mate::Dictionary& options) {
|
|||
|
||||
type_ = is_guest ? WEB_VIEW : BROWSER_WINDOW;
|
||||
|
||||
auto browser_context = AtomBrowserMainParts::Get()->browser_context();
|
||||
content::BrowserContext* browser_context =
|
||||
AtomBrowserMainParts::Get()->browser_context();
|
||||
content::WebContents* web_contents;
|
||||
if (is_guest) {
|
||||
content::SiteInstance* site_instance = content::SiteInstance::CreateForURL(
|
||||
browser_context, GURL("chrome-guest://fake-host"));
|
||||
GURL guest_site;
|
||||
options.Get("partition", &guest_site);
|
||||
// use hosts' browser_context when no partition is specified.
|
||||
if (!guest_site.query().empty()) {
|
||||
browser_context = AtomBrowserMainParts::Get()
|
||||
->GetBrowserContextForPartition(guest_site);
|
||||
}
|
||||
auto site_instance =
|
||||
content::SiteInstance::CreateForURL(browser_context, guest_site);
|
||||
content::WebContents::CreateParams params(browser_context, site_instance);
|
||||
guest_delegate_.reset(new WebViewGuestDelegate);
|
||||
params.guest_delegate = guest_delegate_.get();
|
||||
|
@ -217,7 +225,7 @@ bool WebContents::ShouldCreateWebContents(
|
|||
int route_id,
|
||||
int main_frame_route_id,
|
||||
WindowContainerType window_container_type,
|
||||
const base::string16& frame_name,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const std::string& partition_id,
|
||||
content::SessionStorageNamespace* session_storage_namespace) {
|
||||
|
@ -362,14 +370,16 @@ void WebContents::DidFailProvisionalLoad(
|
|||
content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) {
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) {
|
||||
Emit("did-fail-load", error_code, error_description);
|
||||
}
|
||||
|
||||
void WebContents::DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) {
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) {
|
||||
Emit("did-fail-load", error_code, error_description);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
|
||||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/common_web_contents_delegate.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/common/favicon_url.h"
|
||||
#include "native_mate/handle.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
|
@ -135,7 +135,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
int route_id,
|
||||
int main_frame_route_id,
|
||||
WindowContainerType window_container_type,
|
||||
const base::string16& frame_name,
|
||||
const std::string& frame_name,
|
||||
const GURL& target_url,
|
||||
const std::string& partition_id,
|
||||
content::SessionStorageNamespace* session_storage_namespace) override;
|
||||
|
@ -170,11 +170,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
void DidFailLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) override;
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidFailProvisionalLoad(content::RenderFrameHost* render_frame_host,
|
||||
const GURL& validated_url,
|
||||
int error_code,
|
||||
const base::string16& error_description) override;
|
||||
const base::string16& error_description,
|
||||
bool was_ignored_by_handler) override;
|
||||
void DidStartLoading() override;
|
||||
void DidStopLoading() override;
|
||||
void DidGetResourceResponseStart(
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
@ -34,16 +35,19 @@ struct Converter<atom::WebViewManager::WebViewInfo> {
|
|||
return false;
|
||||
|
||||
GURL preload_url;
|
||||
if (!options.Get("preloadUrl", &preload_url))
|
||||
if (!options.Get(atom::web_view::kPreloadUrl, &preload_url))
|
||||
return false;
|
||||
|
||||
if (!preload_url.is_empty() &&
|
||||
!net::FileURLToFilePath(preload_url, &(out->preload_script)))
|
||||
return false;
|
||||
|
||||
return options.Get("nodeIntegration", &(out->node_integration)) &&
|
||||
options.Get("plugins", &(out->plugins)) &&
|
||||
options.Get("disableWebSecurity", &(out->disable_web_security));
|
||||
return options.Get(atom::web_view::kNodeIntegration,
|
||||
&(out->node_integration)) &&
|
||||
options.Get(atom::web_view::kPlugins, &(out->plugins)) &&
|
||||
options.Get(atom::web_view::kPartitionId, &(out->partition_id)) &&
|
||||
options.Get(atom::web_view::kDisableWebSecurity,
|
||||
&(out->disable_web_security));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -67,12 +71,15 @@ void AddGuest(int guest_instance_id,
|
|||
content::WebContents* guest_web_contents,
|
||||
atom::WebViewManager::WebViewInfo info) {
|
||||
auto manager = GetWebViewManager(embedder);
|
||||
if (manager) {
|
||||
if (manager)
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents);
|
||||
|
||||
info.guest_instance_id = guest_instance_id;
|
||||
info.embedder = embedder;
|
||||
manager->AddGuest(guest_instance_id, element_instance_id, embedder,
|
||||
guest_web_contents, info);
|
||||
}
|
||||
auto data = new atom::WebViewManager::WebViewInfoUserData(info);
|
||||
guest_web_contents->SetUserData(
|
||||
atom::web_view::kWebViewInfoKeyName, data);
|
||||
}
|
||||
|
||||
void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
EventEmitter = require('events').EventEmitter
|
||||
|
||||
bindings = process.atomBinding 'app'
|
||||
sessionBindings = process.atomBinding 'session'
|
||||
|
||||
app = bindings.app
|
||||
app.__proto__ = EventEmitter.prototype
|
||||
|
||||
wrapSession = (session) ->
|
||||
# session is an Event Emitter.
|
||||
session.__proto__ = EventEmitter.prototype
|
||||
|
||||
app.setApplicationMenu = (menu) ->
|
||||
require('menu').setApplicationMenu menu
|
||||
|
||||
|
@ -41,5 +46,9 @@ app.getDataPath = -> @getPath 'userData'
|
|||
app.setDataPath = (path) -> @setPath 'userData', path
|
||||
app.resolveProxy = -> @defaultSession.resolveProxy.apply @defaultSession, arguments
|
||||
|
||||
# Session wrapper.
|
||||
sessionBindings._setWrapSession wrapSession
|
||||
process.once 'exit', sessionBindings._clearWrapSession
|
||||
|
||||
# Only one App object pemitted.
|
||||
module.exports = app
|
||||
|
|
|
@ -62,6 +62,12 @@ BrowserWindow::loadUrl = -> @webContents.loadUrl.apply @webContents, arguments
|
|||
BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||
|
||||
# Be compatible with old API.
|
||||
BrowserWindow::undo = -> @webContents.undo()
|
||||
BrowserWindow::redo = -> @webContents.redo()
|
||||
BrowserWindow::cut = -> @webContents.cut()
|
||||
BrowserWindow::copy = -> @webContents.copy()
|
||||
BrowserWindow::paste = -> @webContents.paste()
|
||||
BrowserWindow::selectAll = -> @webContents.selectAll()
|
||||
BrowserWindow::restart = -> @webContents.reload()
|
||||
BrowserWindow::getUrl = -> @webContents.getUrl()
|
||||
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
|
||||
|
|
|
@ -3,18 +3,30 @@ v8Util = process.atomBinding 'v8_util'
|
|||
|
||||
nextCommandId = 0
|
||||
|
||||
# Maps role to methods of webContents
|
||||
rolesMap =
|
||||
undo: 'undo'
|
||||
redo: 'redo'
|
||||
cut: 'cut'
|
||||
copy: 'copy'
|
||||
paste: 'paste'
|
||||
selectall: 'selectAll'
|
||||
minimize: 'minimize'
|
||||
close: 'close'
|
||||
|
||||
class MenuItem
|
||||
@types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
||||
|
||||
constructor: (options) ->
|
||||
Menu = require 'menu'
|
||||
|
||||
{click, @selector, @type, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||
{click, @selector, @type, @role, @label, @sublabel, @accelerator, @icon, @enabled, @visible, @checked, @submenu} = options
|
||||
|
||||
@type = 'submenu' if not @type? and @submenu?
|
||||
throw new Error('Invalid submenu') if @type is 'submenu' and @submenu?.constructor isnt Menu
|
||||
|
||||
@overrideReadOnlyProperty 'type', 'normal'
|
||||
@overrideReadOnlyProperty 'role'
|
||||
@overrideReadOnlyProperty 'accelerator'
|
||||
@overrideReadOnlyProperty 'icon'
|
||||
@overrideReadOnlyProperty 'submenu'
|
||||
|
@ -27,12 +39,14 @@ class MenuItem
|
|||
throw new Error("Unknown menu type #{@type}") if MenuItem.types.indexOf(@type) is -1
|
||||
|
||||
@commandId = ++nextCommandId
|
||||
@click = =>
|
||||
@click = (focusedWindow) =>
|
||||
# Manually flip the checked flags when clicked.
|
||||
@checked = !@checked if @type in ['checkbox', 'radio']
|
||||
|
||||
if typeof click is 'function'
|
||||
click this, BrowserWindow.getFocusedWindow()
|
||||
if @role and rolesMap[@role] and process.platform isnt 'darwin'
|
||||
focusedWindow?[rolesMap[@role]]()
|
||||
else if typeof click is 'function'
|
||||
click this, focusedWindow
|
||||
else if typeof @selector is 'string'
|
||||
Menu.sendActionToFirstResponder @selector
|
||||
|
||||
|
|
|
@ -67,7 +67,8 @@ Menu::_init = ->
|
|||
isCommandIdVisible: (commandId) => @commandsMap[commandId]?.visible
|
||||
getAcceleratorForCommandId: (commandId) => @commandsMap[commandId]?.accelerator
|
||||
getIconForCommandId: (commandId) => @commandsMap[commandId]?.icon
|
||||
executeCommand: (commandId) => @commandsMap[commandId]?.click()
|
||||
executeCommand: (commandId) =>
|
||||
@commandsMap[commandId]?.click BrowserWindow.getFocusedWindow()
|
||||
menuWillShow: =>
|
||||
# Make sure radio groups have at least one menu item seleted.
|
||||
for id, group of @groupsMap
|
||||
|
@ -115,6 +116,7 @@ Menu::insert = (pos, item) ->
|
|||
|
||||
@setSublabel pos, item.sublabel if item.sublabel?
|
||||
@setIcon pos, item.icon if item.icon?
|
||||
@setRole pos, item.role if item.role?
|
||||
|
||||
# Make menu accessable to items.
|
||||
item.overrideReadOnlyProperty 'menu', this
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/web_view_manager.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#include "atom/common/options_switches.h"
|
||||
#include "base/command_line.h"
|
||||
|
@ -74,8 +75,12 @@ ProcessOwner GetProcessOwner(int process_id,
|
|||
return OWNER_NATIVE_WINDOW;
|
||||
|
||||
// Then search for guest WebContents.
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, info))
|
||||
auto data = static_cast<WebViewManager::WebViewInfoUserData*>(
|
||||
web_contents->GetUserData(web_view::kWebViewInfoKeyName));
|
||||
if (data) {
|
||||
*info = data->web_view_info();
|
||||
return OWNER_GUEST_WEB_CONTENTS;
|
||||
}
|
||||
|
||||
return OWNER_NONE;
|
||||
}
|
||||
|
@ -155,9 +160,10 @@ void AtomBrowserClient::OverrideWebkitPrefs(
|
|||
|
||||
// Custom preferences of guest page.
|
||||
auto web_contents = content::WebContents::FromRenderViewHost(host);
|
||||
WebViewManager::WebViewInfo info;
|
||||
if (WebViewManager::GetInfoForWebContents(web_contents, &info)) {
|
||||
prefs->web_security_enabled = !info.disable_web_security;
|
||||
auto info = static_cast<WebViewManager::WebViewInfoUserData*>(
|
||||
web_contents->GetUserData(web_view::kWebViewInfoKeyName));
|
||||
if (info) {
|
||||
prefs->web_security_enabled = !info->web_view_info().disable_web_security;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
#include "atom/browser/api/trackable_object.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/bridge_task_runner.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/javascript_environment.h"
|
||||
#include "atom/browser/node_debugger.h"
|
||||
#include "atom/common/api/atom_bindings.h"
|
||||
#include "atom/common/node_bindings.h"
|
||||
#include "base/command_line.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "v8/include/v8-debug.h"
|
||||
|
||||
|
@ -24,6 +26,23 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const base::FilePath::CharType kStoragePartitionDirname[] = "Partitions";
|
||||
|
||||
void GetStoragePartitionConfig(const GURL& partition,
|
||||
base::FilePath* partition_path,
|
||||
bool* in_memory,
|
||||
std::string* id) {
|
||||
*in_memory = (partition.path() != "/persist");
|
||||
net::UnescapeRule::Type flags =
|
||||
net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS;
|
||||
*id = net::UnescapeURLComponent(partition.query(), flags);
|
||||
*partition_path = base::FilePath(kStoragePartitionDirname).AppendASCII(*id);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
|
||||
|
||||
|
@ -48,6 +67,21 @@ AtomBrowserMainParts* AtomBrowserMainParts::Get() {
|
|||
return self_;
|
||||
}
|
||||
|
||||
content::BrowserContext* AtomBrowserMainParts::GetBrowserContextForPartition(
|
||||
const GURL& partition) {
|
||||
std::string id;
|
||||
bool in_memory;
|
||||
base::FilePath partition_path;
|
||||
GetStoragePartitionConfig(partition, &partition_path, &in_memory, &id);
|
||||
if (browser_context_map_.contains(id))
|
||||
return browser_context_map_.get(id);
|
||||
|
||||
scoped_ptr<brightray::BrowserContext> browser_context(CreateBrowserContext());
|
||||
browser_context->Initialize(partition_path.value(), in_memory);
|
||||
browser_context_map_.set(id, browser_context.Pass());
|
||||
return browser_context_map_.get(id);
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::RegisterDestructionCallback(
|
||||
const base::Closure& callback) {
|
||||
destruction_callbacks_.push_back(callback);
|
||||
|
@ -64,9 +98,17 @@ void AtomBrowserMainParts::PostEarlyInitialization() {
|
|||
SetDPIFromGSettings();
|
||||
#endif
|
||||
|
||||
// The ProxyResolverV8 has setup a complete V8 environment, in order to avoid
|
||||
// conflicts we only initialize our V8 environment after that.
|
||||
{
|
||||
// Temporary set the bridge_task_runner_ as current thread's task runner,
|
||||
// so we can fool gin::PerIsolateData to use it as its task runner, instead
|
||||
// of getting current message loop's task runner, which is null for now.
|
||||
bridge_task_runner_ = new BridgeTaskRunner;
|
||||
base::ThreadTaskRunnerHandle handle(bridge_task_runner_);
|
||||
|
||||
// The ProxyResolverV8 has setup a complete V8 environment, in order to
|
||||
// avoid conflicts we only initialize our V8 environment after that.
|
||||
js_env_.reset(new JavascriptEnvironment);
|
||||
}
|
||||
|
||||
node_bindings_->Initialize();
|
||||
|
||||
|
|
|
@ -6,10 +6,14 @@
|
|||
#define ATOM_BROWSER_ATOM_BROWSER_MAIN_PARTS_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/containers/scoped_ptr_hash_map.h"
|
||||
#include "base/timer/timer.h"
|
||||
#include "brightray/browser/browser_main_parts.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
|
||||
class BrowserProcess;
|
||||
|
||||
|
@ -20,6 +24,7 @@ class Browser;
|
|||
class JavascriptEnvironment;
|
||||
class NodeBindings;
|
||||
class NodeDebugger;
|
||||
class BridgeTaskRunner;
|
||||
|
||||
class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
||||
public:
|
||||
|
@ -28,6 +33,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
|
||||
static AtomBrowserMainParts* Get();
|
||||
|
||||
// Returns the BrowserContext associated with the partition.
|
||||
content::BrowserContext* GetBrowserContextForPartition(
|
||||
const GURL& partition);
|
||||
|
||||
// Register a callback that should be destroyed before JavaScript environment
|
||||
// gets destroyed.
|
||||
void RegisterDestructionCallback(const base::Closure& callback);
|
||||
|
@ -54,6 +63,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
// A fake BrowserProcess object that used to feed the source code from chrome.
|
||||
scoped_ptr<BrowserProcess> fake_browser_process_;
|
||||
|
||||
// The gin::PerIsolateData requires a task runner to create, so we feed it
|
||||
// with a task runner that will post all work to main loop.
|
||||
scoped_refptr<BridgeTaskRunner> bridge_task_runner_;
|
||||
|
||||
scoped_ptr<Browser> browser_;
|
||||
scoped_ptr<JavascriptEnvironment> js_env_;
|
||||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
|
@ -65,6 +78,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
// List of callbacks should be executed before destroying JS env.
|
||||
std::list<base::Closure> destruction_callbacks_;
|
||||
|
||||
// partition_id => browser_context
|
||||
base::ScopedPtrHashMap<std::string, scoped_ptr<brightray::BrowserContext>>
|
||||
browser_context_map_;
|
||||
|
||||
static AtomBrowserMainParts* self_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserMainParts);
|
||||
|
|
42
atom/browser/bridge_task_runner.cc
Normal file
42
atom/browser/bridge_task_runner.cc
Normal file
|
@ -0,0 +1,42 @@
|
|||
// 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/bridge_task_runner.h"
|
||||
|
||||
#include "base/message_loop/message_loop.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
bool BridgeTaskRunner::PostDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->PostDelayedTask(from_here, task, delay);
|
||||
}
|
||||
|
||||
bool BridgeTaskRunner::RunsTasksOnCurrentThread() const {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->RunsTasksOnCurrentThread();
|
||||
}
|
||||
|
||||
bool BridgeTaskRunner::PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) {
|
||||
auto message_loop = base::MessageLoop::current();
|
||||
if (!message_loop)
|
||||
return false;
|
||||
|
||||
return message_loop->task_runner()->PostNonNestableDelayedTask(
|
||||
from_here, task, delay);
|
||||
}
|
||||
|
||||
} // namespace atom
|
35
atom/browser/bridge_task_runner.h
Normal file
35
atom/browser/bridge_task_runner.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// 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_BRIDGE_TASK_RUNNER_H_
|
||||
#define ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
||||
|
||||
#include "base/single_thread_task_runner.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
// Post all tasks to the current message loop's task runner if available,
|
||||
// otherwise fail silently.
|
||||
class BridgeTaskRunner : public base::SingleThreadTaskRunner {
|
||||
public:
|
||||
BridgeTaskRunner() {}
|
||||
~BridgeTaskRunner() override {}
|
||||
|
||||
// base::SingleThreadTaskRunner:
|
||||
bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
bool RunsTasksOnCurrentThread() const override;
|
||||
bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
const base::Closure& task,
|
||||
base::TimeDelta delay) override;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(BridgeTaskRunner);
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_BRIDGE_TASK_RUNNER_H_
|
|
@ -153,7 +153,7 @@ class Browser : public WindowListObserver {
|
|||
void OnWindowAllClosed() override;
|
||||
|
||||
// Observers of the browser.
|
||||
ObserverList<BrowserObserver> observers_;
|
||||
base::ObserverList<BrowserObserver> observers_;
|
||||
|
||||
// Whether "ready" event has been emitted.
|
||||
bool is_ready_;
|
||||
|
|
|
@ -36,21 +36,138 @@ app.once('ready', function() {
|
|||
if (Menu.getApplicationMenu())
|
||||
return;
|
||||
|
||||
var template;
|
||||
if (process.platform == 'darwin') {
|
||||
template = [
|
||||
var template = [
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'CmdOrCtrl+Z',
|
||||
role: 'undo'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+CmdOrCtrl+Z',
|
||||
role: 'redo'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
role: 'cut'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
role: 'copy'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
role: 'paste'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'CmdOrCtrl+A',
|
||||
role: 'selectall'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Ctrl+Command+F';
|
||||
else
|
||||
return 'F11';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Alt+Command+I';
|
||||
else
|
||||
return 'Ctrl+Shift+I';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'CmdOrCtrl+M',
|
||||
role: 'minimize'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'CmdOrCtrl+W',
|
||||
role: 'close'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
template.unshift({
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
selector: 'orderFrontStandardAboutPanel:'
|
||||
role: 'about'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
role: 'services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
|
@ -59,16 +176,16 @@ app.once('ready', function() {
|
|||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'Command+H',
|
||||
selector: 'hide:'
|
||||
role: 'hide'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
role: 'hideothers:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
selector: 'unhideAllApplications:'
|
||||
role: 'unhide:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
|
@ -79,195 +196,16 @@ app.once('ready', function() {
|
|||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'Command+Z',
|
||||
selector: 'undo:'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+Command+Z',
|
||||
selector: 'redo:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'Command+X',
|
||||
selector: 'cut:'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'Command+C',
|
||||
selector: 'copy:'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'Command+V',
|
||||
selector: 'paste:'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'View',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'Command+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: 'Ctrl+Command+F',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'Command+M',
|
||||
selector: 'performMiniaturize:'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'Command+W',
|
||||
selector: 'performClose:'
|
||||
},
|
||||
});
|
||||
template[3].submenu.push(
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
role: 'front'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
} else {
|
||||
template = [
|
||||
{
|
||||
label: '&File',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Open',
|
||||
accelerator: 'Ctrl+O',
|
||||
},
|
||||
{
|
||||
label: '&Close',
|
||||
accelerator: 'Ctrl+W',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.close();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '&View',
|
||||
submenu: [
|
||||
{
|
||||
label: '&Reload',
|
||||
accelerator: 'Ctrl+R',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Full Screen',
|
||||
accelerator: 'F11',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle &Developer Tools',
|
||||
accelerator: 'Shift+Ctrl+I',
|
||||
click: function() {
|
||||
var focusedWindow = BrowserWindow.getFocusedWindow();
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
{
|
||||
label: 'Documentation',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
|
||||
},
|
||||
{
|
||||
label: 'Community Discussions',
|
||||
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
|
||||
},
|
||||
{
|
||||
label: 'Search Issues',
|
||||
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
);
|
||||
}
|
||||
|
||||
var menu = Menu.buildFromTemplate(template);
|
||||
|
|
|
@ -38,12 +38,29 @@ moveLastToFirst = (list) ->
|
|||
getNextInstanceId = (webContents) ->
|
||||
++nextInstanceId
|
||||
|
||||
# Generate URL encoded partition id.
|
||||
getPartitionId = (partition) ->
|
||||
# Guest site url will be chrome-guest://fake-host/{persist}?{partitionId}
|
||||
partitionId = "chrome-guest://fake-host/"
|
||||
if partition
|
||||
persist = partition.startsWith('persist:')
|
||||
if persist
|
||||
partition = partition.substring('persist:'.length)
|
||||
partitionId += 'persist?'
|
||||
else
|
||||
# Just to differentiate from same persistant ID
|
||||
partition += "_temp"
|
||||
partitionId += '?'
|
||||
partitionId += encodeURIComponent(partition)
|
||||
return partitionId
|
||||
|
||||
# Create a new guest instance.
|
||||
createGuest = (embedder, params) ->
|
||||
webViewManager ?= process.atomBinding 'web_view_manager'
|
||||
|
||||
id = getNextInstanceId embedder
|
||||
guest = webContents.create {isGuest: true, embedder}
|
||||
partitionId = getPartitionId params.partition
|
||||
guest = webContents.create {isGuest: true, partition: partitionId, embedder}
|
||||
guestInstances[id] = {guest, embedder}
|
||||
|
||||
# Destroy guest when the embedder is gone or navigated.
|
||||
|
@ -120,6 +137,7 @@ attachGuest = (embedder, elementInstanceId, guestInstanceId, params) ->
|
|||
plugins: params.plugins
|
||||
disableWebSecurity: params.disablewebsecurity
|
||||
preloadUrl: params.preload ? ''
|
||||
partitionId: getPartitionId(params.partition)
|
||||
|
||||
guest.attachParams = params
|
||||
embedderElementsMap[key] = guestInstanceId
|
||||
|
|
|
@ -57,13 +57,19 @@ ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_POSTMESSAGE', (event, guestId, me
|
|||
if guestContents?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
||||
guestContents.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, message, targetOrigin) ->
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', (event, guestId, message, targetOrigin, sourceOrigin) ->
|
||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
||||
if embedder?.getUrl().indexOf(targetOrigin) is 0 or targetOrigin is '*'
|
||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', message, targetOrigin
|
||||
embedder.send 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', guestId, message, sourceOrigin
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WEB_CONTENTS_METHOD', (event, guestId, method, args...) ->
|
||||
BrowserWindow.fromId(guestId)?.webContents?[method] args...
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_IS_GUEST_WINDOW', (event) ->
|
||||
event.returnValue = v8Util.getHiddenValue(event.sender, 'embedder') isnt undefined
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID', (event) ->
|
||||
embedder = v8Util.getHiddenValue event.sender, 'embedder'
|
||||
if embedder?
|
||||
guest = BrowserWindow.fromWebContents event.sender
|
||||
if guest?
|
||||
event.returnValue = guest.id
|
||||
return
|
||||
event.returnValue = null
|
||||
|
|
|
@ -310,7 +310,7 @@ class NativeWindow : public content::WebContentsObserver,
|
|||
brightray::InspectableWebContents* inspectable_web_contents_;
|
||||
|
||||
// Observers of this window.
|
||||
ObserverList<NativeWindowObserver> observers_;
|
||||
base::ObserverList<NativeWindowObserver> observers_;
|
||||
|
||||
base::WeakPtrFactory<NativeWindow> weak_factory_;
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ bool URLRequestAsarJob::IsRedirectResponse(GURL* location,
|
|||
#if defined(OS_WIN)
|
||||
// Follow a Windows shortcut.
|
||||
// We just resolve .lnk file, ignore others.
|
||||
if (!LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
|
||||
if (!base::LowerCaseEqualsASCII(file_path_.Extension(), ".lnk"))
|
||||
return false;
|
||||
|
||||
base::FilePath new_path = file_path_;
|
||||
|
@ -193,7 +193,7 @@ bool URLRequestAsarJob::IsRedirectResponse(GURL* location,
|
|||
|
||||
net::Filter* URLRequestAsarJob::SetupFilter() const {
|
||||
// Bug 9936 - .svgz files needs to be decompressed.
|
||||
return LowerCaseEqualsASCII(file_path_.Extension(), ".svgz")
|
||||
return base::LowerCaseEqualsASCII(file_path_.Extension(), ".svgz")
|
||||
? net::Filter::GZipFactory() : NULL;
|
||||
}
|
||||
|
||||
|
@ -265,8 +265,7 @@ void URLRequestAsarJob::DidOpen(int result) {
|
|||
}
|
||||
|
||||
if (type_ == TYPE_ASAR) {
|
||||
int rv = stream_->Seek(base::File::FROM_BEGIN,
|
||||
file_info_.offset,
|
||||
int rv = stream_->Seek(file_info_.offset,
|
||||
base::Bind(&URLRequestAsarJob::DidSeek,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
if (rv != net::ERR_IO_PENDING) {
|
||||
|
@ -285,8 +284,7 @@ void URLRequestAsarJob::DidOpen(int result) {
|
|||
byte_range_.first_byte_position() + 1;
|
||||
|
||||
if (remaining_bytes_ > 0 && byte_range_.first_byte_position() != 0) {
|
||||
int rv = stream_->Seek(base::File::FROM_BEGIN,
|
||||
byte_range_.first_byte_position(),
|
||||
int rv = stream_->Seek(byte_range_.first_byte_position(),
|
||||
base::Bind(&URLRequestAsarJob::DidSeek,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
if (rv != net::ERR_IO_PENDING) {
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace {
|
|||
|
||||
// Convert string to RequestType.
|
||||
net::URLFetcher::RequestType GetRequestType(const std::string& raw) {
|
||||
std::string method = StringToUpperASCII(raw);
|
||||
std::string method = base::StringToUpperASCII(raw);
|
||||
if (method.empty() || method == "GET")
|
||||
return net::URLFetcher::GET;
|
||||
else if (method == "POST")
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.31.0</string>
|
||||
<string>0.31.2</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
|
|
@ -56,8 +56,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,31,0,0
|
||||
PRODUCTVERSION 0,31,0,0
|
||||
FILEVERSION 0,31,2,0
|
||||
PRODUCTVERSION 0,31,2,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -74,12 +74,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.31.0"
|
||||
VALUE "FileVersion", "0.31.2"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.31.0"
|
||||
VALUE "ProductVersion", "0.31.2"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
|
||||
#include "base/stl_util.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomMenuModel::AtomMenuModel(Delegate* delegate)
|
||||
|
@ -14,6 +16,17 @@ AtomMenuModel::AtomMenuModel(Delegate* delegate)
|
|||
AtomMenuModel::~AtomMenuModel() {
|
||||
}
|
||||
|
||||
void AtomMenuModel::SetRole(int index, const base::string16& role) {
|
||||
roles_[index] = role;
|
||||
}
|
||||
|
||||
base::string16 AtomMenuModel::GetRoleAt(int index) {
|
||||
if (ContainsKey(roles_, index))
|
||||
return roles_[index];
|
||||
else
|
||||
return base::string16();
|
||||
}
|
||||
|
||||
void AtomMenuModel::MenuClosed() {
|
||||
ui::SimpleMenuModel::MenuClosed();
|
||||
FOR_EACH_OBSERVER(Observer, observers_, MenuClosed());
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#ifndef ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
|
||||
#define ATOM_BROWSER_UI_ATOM_MENU_MODEL_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "base/observer_list.h"
|
||||
#include "ui/base/models/simple_menu_model.h"
|
||||
|
||||
|
@ -31,13 +33,17 @@ class AtomMenuModel : public ui::SimpleMenuModel {
|
|||
void AddObserver(Observer* obs) { observers_.AddObserver(obs); }
|
||||
void RemoveObserver(Observer* obs) { observers_.RemoveObserver(obs); }
|
||||
|
||||
void SetRole(int index, const base::string16& role);
|
||||
base::string16 GetRoleAt(int index);
|
||||
|
||||
// ui::SimpleMenuModel:
|
||||
void MenuClosed() override;
|
||||
|
||||
private:
|
||||
Delegate* delegate_; // weak ref.
|
||||
|
||||
ObserverList<Observer> observers_;
|
||||
std::map<int, base::string16> roles_;
|
||||
base::ObserverList<Observer> observers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomMenuModel);
|
||||
};
|
||||
|
|
|
@ -59,17 +59,4 @@ class MenuModel;
|
|||
|
||||
@end
|
||||
|
||||
// Exposed only for unit testing, do not call directly.
|
||||
@interface AtomMenuController (PrivateExposedForTesting)
|
||||
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item;
|
||||
@end
|
||||
|
||||
// Protected methods that subclassers can override.
|
||||
@interface AtomMenuController (Protected)
|
||||
- (void)addItemToMenu:(NSMenu*)menu
|
||||
atIndex:(NSInteger)index
|
||||
fromModel:(ui::MenuModel*)model;
|
||||
- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
|
||||
@end
|
||||
|
||||
#endif // ATOM_BROWSER_UI_COCOA_ATOM_MENU_CONTROLLER_H_
|
||||
|
|
|
@ -8,16 +8,36 @@
|
|||
#include "atom/browser/ui/atom_menu_model.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "ui/base/accelerators/accelerator.h"
|
||||
#include "ui/base/accelerators/platform_accelerator_cocoa.h"
|
||||
#include "ui/base/l10n/l10n_util_mac.h"
|
||||
#include "ui/events/cocoa/cocoa_event_utils.h"
|
||||
#include "ui/gfx/image/image.h"
|
||||
|
||||
@interface AtomMenuController (Private)
|
||||
- (void)addSeparatorToMenu:(NSMenu*)menu
|
||||
atIndex:(int)index;
|
||||
@end
|
||||
namespace {
|
||||
|
||||
struct Role {
|
||||
SEL selector;
|
||||
const char* role;
|
||||
};
|
||||
Role kRolesMap[] = {
|
||||
{ @selector(orderFrontStandardAboutPanel:), "about" },
|
||||
{ @selector(hide:), "hide" },
|
||||
{ @selector(hideOtherApplications:), "hideothers" },
|
||||
{ @selector(unhideAllApplications:), "unhide" },
|
||||
{ @selector(arrangeInFront:), "front" },
|
||||
{ @selector(undo:), "undo" },
|
||||
{ @selector(redo:), "redo" },
|
||||
{ @selector(cut:), "cut" },
|
||||
{ @selector(copy:), "copy" },
|
||||
{ @selector(paste:), "paste" },
|
||||
{ @selector(selectAll:), "selectall" },
|
||||
{ @selector(performMiniaturize:), "minimize" },
|
||||
{ @selector(performClose:), "close" },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation AtomMenuController
|
||||
|
||||
|
@ -101,7 +121,9 @@
|
|||
// associated with the entry in the model identified by |modelIndex|.
|
||||
- (void)addItemToMenu:(NSMenu*)menu
|
||||
atIndex:(NSInteger)index
|
||||
fromModel:(ui::MenuModel*)model {
|
||||
fromModel:(ui::MenuModel*)ui_model {
|
||||
atom::AtomMenuModel* model = static_cast<atom::AtomMenuModel*>(ui_model);
|
||||
|
||||
base::string16 label16 = model->GetLabelAt(index);
|
||||
NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
|
||||
base::scoped_nsobject<NSMenuItem> item(
|
||||
|
@ -124,13 +146,13 @@
|
|||
[submenu setTitle:[item title]];
|
||||
[item setSubmenu:submenu];
|
||||
|
||||
// Hack to set window and help menu.
|
||||
if ([[item title] isEqualToString:@"Window"] && [submenu numberOfItems] > 0)
|
||||
// Set submenu's role.
|
||||
base::string16 role = model->GetRoleAt(index);
|
||||
if (role == base::ASCIIToUTF16("window"))
|
||||
[NSApp setWindowsMenu:submenu];
|
||||
else if ([[item title] isEqualToString:@"Help"])
|
||||
else if (role == base::ASCIIToUTF16("help"))
|
||||
[NSApp setHelpMenu:submenu];
|
||||
if ([[item title] isEqualToString:@"Services"] &&
|
||||
[submenu numberOfItems] == 0)
|
||||
if (role == base::ASCIIToUTF16("services"))
|
||||
[NSApp setServicesMenu:submenu];
|
||||
} else {
|
||||
// The MenuModel works on indexes so we can't just set the command id as the
|
||||
|
@ -139,7 +161,6 @@
|
|||
// model. Setting the target to |self| allows this class to participate
|
||||
// in validation of the menu items.
|
||||
[item setTag:index];
|
||||
[item setTarget:self];
|
||||
NSValue* modelObject = [NSValue valueWithPointer:model];
|
||||
[item setRepresentedObject:modelObject]; // Retains |modelObject|.
|
||||
ui::Accelerator accelerator;
|
||||
|
@ -153,6 +174,19 @@
|
|||
platformAccelerator->modifier_mask()];
|
||||
}
|
||||
}
|
||||
|
||||
// Set menu item's role.
|
||||
base::string16 role = model->GetRoleAt(index);
|
||||
if (role.empty()) {
|
||||
[item setTarget:self];
|
||||
} else {
|
||||
for (const Role& pair : kRolesMap) {
|
||||
if (role == base::ASCIIToUTF16(pair.role)) {
|
||||
[item setAction:pair.selector];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[menu insertItem:item atIndex:index];
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ gboolean FileFilterCaseInsensitive(const GtkFileFilterInfo* file_info,
|
|||
// Makes .* file extension matches all file types.
|
||||
if (*file_extension == ".*")
|
||||
return true;
|
||||
return EndsWith(file_info->filename, *file_extension, false);
|
||||
return base::EndsWith(file_info->filename, *file_extension, false);
|
||||
}
|
||||
|
||||
// Deletes |data| when gtk_file_filter_add_custom() is done with it.
|
||||
|
|
|
@ -252,7 +252,7 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window,
|
|||
|
||||
bool matched = false;
|
||||
for (size_t i = 0; i < filter.second.size(); ++i) {
|
||||
if (EndsWith(file_name, filter.second[i], false)) {
|
||||
if (base::EndsWith(file_name, filter.second[i], false)) {
|
||||
matched = true;
|
||||
break;;
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ class TrayIcon {
|
|||
TrayIcon();
|
||||
|
||||
private:
|
||||
ObserverList<TrayIconObserver> observers_;
|
||||
base::ObserverList<TrayIconObserver> observers_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(TrayIcon);
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ void SetWindowType(::Window xwindow, const std::string& type) {
|
|||
XDisplay* xdisplay = gfx::GetXDisplay();
|
||||
std::string type_prefix = "_NET_WM_WINDOW_TYPE_";
|
||||
::Atom window_type = XInternAtom(
|
||||
xdisplay, (type_prefix + StringToUpperASCII(type)).c_str(), False);
|
||||
xdisplay, (type_prefix + base::StringToUpperASCII(type)).c_str(), False);
|
||||
XChangeProperty(xdisplay, xwindow,
|
||||
XInternAtom(xdisplay, "_NET_WM_WINDOW_TYPE", False),
|
||||
XA_ATOM,
|
||||
|
|
24
atom/browser/web_view_constants.cc
Normal file
24
atom/browser/web_view_constants.cc
Normal file
|
@ -0,0 +1,24 @@
|
|||
// 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/web_view_constants.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace web_view {
|
||||
|
||||
const char kPreloadUrl[] = "preloadUrl";
|
||||
const char kNodeIntegration[] = "nodeIntegration";
|
||||
const char kPlugins[] = "plugins";
|
||||
const char kDisableWebSecurity[] = "disableWebSecurity";
|
||||
const char kPartitionId[] = "partitionId";
|
||||
|
||||
const int kDefaultWidth = 300;
|
||||
const int kDefaultHeight = 300;
|
||||
|
||||
const char kWebViewInfoKeyName[] = "web_view_info";
|
||||
|
||||
} // namespace web_view
|
||||
|
||||
} // namespace atom
|
27
atom/browser/web_view_constants.h
Normal file
27
atom/browser/web_view_constants.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
// 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_WEB_VIEW_CONSTANTS_H_
|
||||
#define ATOM_BROWSER_WEB_VIEW_CONSTANTS_H_
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace web_view {
|
||||
|
||||
extern const char kPreloadUrl[];
|
||||
extern const char kNodeIntegration[];
|
||||
extern const char kPlugins[];
|
||||
extern const char kDisableWebSecurity[];
|
||||
extern const char kPartitionId[];
|
||||
|
||||
extern const int kDefaultWidth;
|
||||
extern const int kDefaultHeight;
|
||||
|
||||
extern const char kWebViewInfoKeyName[];
|
||||
|
||||
} // namespace web_view
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_WEB_VIEW_CONSTANTS_H_
|
|
@ -5,6 +5,7 @@
|
|||
#include "atom/browser/web_view_guest_delegate.h"
|
||||
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/web_view_constants.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "content/public/browser/guest_host.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
|
@ -13,13 +14,6 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const int kDefaultWidth = 300;
|
||||
const int kDefaultHeight = 300;
|
||||
|
||||
} // namespace
|
||||
|
||||
WebViewGuestDelegate::WebViewGuestDelegate()
|
||||
: guest_opaque_(true),
|
||||
guest_host_(nullptr),
|
||||
|
@ -178,7 +172,7 @@ gfx::Size WebViewGuestDelegate::GetDefaultSize() const {
|
|||
return embedder_web_contents_->GetRenderWidgetHostView()
|
||||
->GetVisibleViewportSize();
|
||||
} else {
|
||||
return gfx::Size(kDefaultWidth, kDefaultHeight);
|
||||
return gfx::Size(web_view::kDefaultWidth, web_view::kDefaultHeight);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,37 +5,12 @@
|
|||
#include "atom/browser/web_view_manager.h"
|
||||
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
WebViewManager* GetManagerFromWebContents(
|
||||
const content::WebContents* web_contents) {
|
||||
auto context = web_contents->GetBrowserContext();
|
||||
if (!context)
|
||||
return nullptr;
|
||||
return static_cast<WebViewManager*>(context->GetGuestManager());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
bool WebViewManager::GetInfoForWebContents(
|
||||
const content::WebContents* web_contents, WebViewInfo* info) {
|
||||
auto manager = GetManagerFromWebContents(web_contents);
|
||||
if (!manager)
|
||||
return false;
|
||||
base::AutoLock auto_lock(manager->lock_);
|
||||
auto iter = manager->webview_info_map_.find(web_contents);
|
||||
if (iter == manager->webview_info_map_.end())
|
||||
return false;
|
||||
*info = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
WebViewManager::WebViewManager(content::BrowserContext* context) {
|
||||
}
|
||||
|
||||
|
@ -45,11 +20,9 @@ WebViewManager::~WebViewManager() {
|
|||
void WebViewManager::AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
const WebViewInfo& info) {
|
||||
content::WebContents* web_contents) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
web_contents_embdder_map_[guest_instance_id] = { web_contents, embedder };
|
||||
webview_info_map_[web_contents] = info;
|
||||
web_contents_embedder_map_[guest_instance_id] = { web_contents, embedder };
|
||||
|
||||
// Map the element in embedder to guest.
|
||||
int owner_process_id = embedder->GetRenderProcessHost()->GetID();
|
||||
|
@ -59,12 +32,10 @@ void WebViewManager::AddGuest(int guest_instance_id,
|
|||
|
||||
void WebViewManager::RemoveGuest(int guest_instance_id) {
|
||||
base::AutoLock auto_lock(lock_);
|
||||
if (!ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||
if (!ContainsKey(web_contents_embedder_map_, guest_instance_id))
|
||||
return;
|
||||
|
||||
auto web_contents = web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||
web_contents_embdder_map_.erase(guest_instance_id);
|
||||
webview_info_map_.erase(web_contents);
|
||||
web_contents_embedder_map_.erase(guest_instance_id);
|
||||
|
||||
// Remove the record of element in embedder too.
|
||||
for (const auto& element : element_instance_id_to_guest_map_)
|
||||
|
@ -82,15 +53,15 @@ content::WebContents* WebViewManager::GetGuestByInstanceID(
|
|||
return nullptr;
|
||||
|
||||
int guest_instance_id = element_instance_id_to_guest_map_[key];
|
||||
if (ContainsKey(web_contents_embdder_map_, guest_instance_id))
|
||||
return web_contents_embdder_map_[guest_instance_id].web_contents;
|
||||
if (ContainsKey(web_contents_embedder_map_, guest_instance_id))
|
||||
return web_contents_embedder_map_[guest_instance_id].web_contents;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool WebViewManager::ForEachGuest(content::WebContents* embedder_web_contents,
|
||||
const GuestCallback& callback) {
|
||||
for (auto& item : web_contents_embdder_map_)
|
||||
for (auto& item : web_contents_embedder_map_)
|
||||
if (item.second.embedder == embedder_web_contents &&
|
||||
callback.Run(item.second.web_contents))
|
||||
return true;
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
#include <map>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "content/public/browser/browser_plugin_guest_manager.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
|
@ -27,12 +29,20 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
bool plugins;
|
||||
bool disable_web_security;
|
||||
base::FilePath preload_script;
|
||||
GURL partition_id;
|
||||
};
|
||||
|
||||
// Finds the WebViewManager attached with |web_contents| and returns the
|
||||
// WebViewInfo of it.
|
||||
static bool GetInfoForWebContents(const content::WebContents* web_contents,
|
||||
WebViewInfo* info);
|
||||
class WebViewInfoUserData : public base::SupportsUserData::Data {
|
||||
public:
|
||||
explicit WebViewInfoUserData(WebViewInfo info)
|
||||
: web_view_info_(info) {}
|
||||
~WebViewInfoUserData() override {}
|
||||
|
||||
WebViewInfo& web_view_info() { return web_view_info_; }
|
||||
|
||||
private:
|
||||
WebViewInfo web_view_info_;
|
||||
};
|
||||
|
||||
explicit WebViewManager(content::BrowserContext* context);
|
||||
virtual ~WebViewManager();
|
||||
|
@ -40,8 +50,7 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
void AddGuest(int guest_instance_id,
|
||||
int element_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
const WebViewInfo& info);
|
||||
content::WebContents* web_contents);
|
||||
void RemoveGuest(int guest_instance_id);
|
||||
|
||||
protected:
|
||||
|
@ -57,7 +66,7 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
content::WebContents* embedder;
|
||||
};
|
||||
// guest_instance_id => (web_contents, embedder)
|
||||
std::map<int, WebContentsWithEmbedder> web_contents_embdder_map_;
|
||||
std::map<int, WebContentsWithEmbedder> web_contents_embedder_map_;
|
||||
|
||||
struct ElementInstanceKey {
|
||||
int embedder_process_id;
|
||||
|
@ -81,10 +90,6 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
|||
// (embedder_process_id, element_instance_id) => guest_instance_id
|
||||
std::map<ElementInstanceKey, int> element_instance_id_to_guest_map_;
|
||||
|
||||
typedef std::map<const content::WebContents*, WebViewInfo> WebViewInfoMap;
|
||||
// web_contents => (guest_instance_id, embedder, ...)
|
||||
WebViewInfoMap webview_info_map_;
|
||||
|
||||
base::Lock lock_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(WebViewManager);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
namespace atom {
|
||||
|
||||
// static
|
||||
base::LazyInstance<ObserverList<WindowListObserver>>::Leaky
|
||||
base::LazyInstance<base::ObserverList<WindowListObserver>>::Leaky
|
||||
WindowList::observers_ = LAZY_INSTANCE_INITIALIZER;
|
||||
|
||||
// static
|
||||
|
|
|
@ -60,7 +60,8 @@ class WindowList {
|
|||
|
||||
// A list of observers which will be notified of every window addition and
|
||||
// removal across all WindowLists.
|
||||
static base::LazyInstance<ObserverList<WindowListObserver>>::Leaky observers_;
|
||||
static base::LazyInstance<base::ObserverList<WindowListObserver>>::Leaky
|
||||
observers_;
|
||||
|
||||
static WindowList* instance_;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "atom/common/node_includes.h"
|
||||
#include "base/base64.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/pattern.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/base/data_url.h"
|
||||
|
@ -62,7 +63,7 @@ float GetScaleFactorFromPath(const base::FilePath& path) {
|
|||
// We don't try to convert string to float here because it is very very
|
||||
// expensive.
|
||||
for (unsigned i = 0; i < arraysize(kScaleFactorPairs); ++i) {
|
||||
if (EndsWith(filename, kScaleFactorPairs[i].name, true))
|
||||
if (base::EndsWith(filename, kScaleFactorPairs[i].name, true))
|
||||
return kScaleFactorPairs[i].scale;
|
||||
}
|
||||
|
||||
|
@ -104,7 +105,7 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
|
|||
const base::FilePath& path) {
|
||||
bool succeed = false;
|
||||
std::string filename(path.BaseName().RemoveExtension().AsUTF8Unsafe());
|
||||
if (MatchPattern(filename, "*@*x"))
|
||||
if (base::MatchPattern(filename, "*@*x"))
|
||||
// Don't search for other representations if the DPI has been specified.
|
||||
return AddImageSkiaRep(image, path, GetScaleFactorFromPath(path));
|
||||
else
|
||||
|
@ -119,8 +120,8 @@ bool PopulateImageSkiaRepsFromPath(gfx::ImageSkia* image,
|
|||
|
||||
#if defined(OS_MACOSX)
|
||||
bool IsTemplateFilename(const base::FilePath& path) {
|
||||
return (MatchPattern(path.value(), "*Template.*") ||
|
||||
MatchPattern(path.value(), "*Template@*x.*"));
|
||||
return (base::MatchPattern(path.value(), "*Template.*") ||
|
||||
base::MatchPattern(path.value(), "*Template@*x.*"));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "atom/common/chrome_version.h"
|
||||
#include "atom/common/native_mate_converters/string16_converter.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/process/process_metrics.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
@ -61,6 +62,9 @@ void AtomBindings::BindTo(v8::Isolate* isolate,
|
|||
dict.SetMethod("crash", &Crash);
|
||||
dict.SetMethod("hang", &Hang);
|
||||
dict.SetMethod("log", &Log);
|
||||
#if defined(OS_POSIX)
|
||||
dict.SetMethod("setFdLimit", &base::SetFdLimit);
|
||||
#endif
|
||||
dict.SetMethod("activateUvLoop",
|
||||
base::Bind(&AtomBindings::ActivateUVLoop, base::Unretained(this)));
|
||||
|
||||
|
|
|
@ -136,7 +136,8 @@ bool Archive::Init() {
|
|||
}
|
||||
|
||||
uint32 size;
|
||||
if (!PickleIterator(Pickle(buf.data(), buf.size())).ReadUInt32(&size)) {
|
||||
if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadUInt32(
|
||||
&size)) {
|
||||
LOG(ERROR) << "Failed to parse header size from " << path_.value();
|
||||
return false;
|
||||
}
|
||||
|
@ -149,7 +150,8 @@ bool Archive::Init() {
|
|||
}
|
||||
|
||||
std::string header;
|
||||
if (!PickleIterator(Pickle(buf.data(), buf.size())).ReadString(&header)) {
|
||||
if (!base::PickleIterator(base::Pickle(buf.data(), buf.size())).ReadString(
|
||||
&header)) {
|
||||
LOG(ERROR) << "Failed to parse header from " << path_.value();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 31
|
||||
#define ATOM_PATCH_VERSION 0
|
||||
#define ATOM_PATCH_VERSION 2
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#ifndef ATOM_COMMON_CHROME_VERSION_H_
|
||||
#define ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
||||
#define CHROME_VERSION_STRING "44.0.2403.125"
|
||||
#define CHROME_VERSION_STRING "45.0.2454.85"
|
||||
#define CHROME_VERSION "v" CHROME_VERSION_STRING
|
||||
|
||||
#endif // ATOM_COMMON_CHROME_VERSION_H_
|
||||
|
|
|
@ -40,6 +40,7 @@ REFERENCE_MODULE(atom_browser_power_monitor);
|
|||
REFERENCE_MODULE(atom_browser_power_save_blocker);
|
||||
REFERENCE_MODULE(atom_browser_protocol);
|
||||
REFERENCE_MODULE(atom_browser_global_shortcut);
|
||||
REFERENCE_MODULE(atom_browser_session);
|
||||
REFERENCE_MODULE(atom_browser_tray);
|
||||
REFERENCE_MODULE(atom_browser_web_contents);
|
||||
REFERENCE_MODULE(atom_browser_web_view_manager);
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "third_party/WebKit/public/web/WebPluginParams.h"
|
||||
#include "third_party/WebKit/public/web/WebKit.h"
|
||||
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
|
||||
#include "third_party/WebKit/Source/wtf/ArrayBufferContents.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
|
@ -52,10 +51,6 @@ bool IsSwitchEnabled(base::CommandLine* command_line,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsGuestFrame(blink::WebFrame* frame) {
|
||||
return frame->uniqueName().utf8() == "ATOM_SHELL_GUEST_WEB_VIEW";
|
||||
}
|
||||
|
||||
// global.Uint8Array;
|
||||
v8::Local<v8::Function> GetUint8ArrayConstructor(
|
||||
v8::Isolate* isolate, v8::Local<v8::Context> context) {
|
||||
|
@ -113,8 +108,7 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
|
|||
|
||||
AtomRendererClient::AtomRendererClient()
|
||||
: node_bindings_(NodeBindings::Create(false)),
|
||||
atom_bindings_(new AtomBindings),
|
||||
main_frame_(nullptr) {
|
||||
atom_bindings_(new AtomBindings) {
|
||||
}
|
||||
|
||||
AtomRendererClient::~AtomRendererClient() {
|
||||
|
@ -189,15 +183,10 @@ bool AtomRendererClient::OverrideCreatePlugin(
|
|||
void AtomRendererClient::DidCreateScriptContext(
|
||||
blink::WebFrame* frame,
|
||||
v8::Handle<v8::Context> context) {
|
||||
// Only attach node bindings in main frame or guest frame.
|
||||
if (!IsGuestFrame(frame)) {
|
||||
if (main_frame_)
|
||||
// Only insert node integration for the main frame.
|
||||
if (frame->parent())
|
||||
return;
|
||||
|
||||
// The first web frame is the main frame.
|
||||
main_frame_ = frame;
|
||||
}
|
||||
|
||||
// Give the node loop a run to make sure everything is ready.
|
||||
node_bindings_->RunMessageLoop();
|
||||
|
||||
|
@ -215,20 +204,17 @@ void AtomRendererClient::DidCreateScriptContext(
|
|||
node_bindings_->LoadEnvironment(env);
|
||||
}
|
||||
|
||||
bool AtomRendererClient::ShouldFork(blink::WebFrame* frame,
|
||||
bool AtomRendererClient::ShouldFork(blink::WebLocalFrame* frame,
|
||||
const GURL& url,
|
||||
const std::string& http_method,
|
||||
bool is_initial_navigation,
|
||||
bool is_server_redirect,
|
||||
bool* send_referrer) {
|
||||
// Never fork renderer process for guests.
|
||||
if (IsGuestFrame(frame))
|
||||
return false;
|
||||
|
||||
// Handle all the navigations and reloads in browser.
|
||||
// FIXME We only support GET here because http method will be ignored when
|
||||
// the OpenURLFromTab is triggered, which means form posting would not work,
|
||||
// we should solve this by patching Chromium in future.
|
||||
*send_referrer = true;
|
||||
return http_method == "GET";
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ class AtomRendererClient : public content::ContentRendererClient,
|
|||
blink::WebLocalFrame* frame,
|
||||
const blink::WebPluginParams& params,
|
||||
blink::WebPlugin** plugin) override;
|
||||
bool ShouldFork(blink::WebFrame* frame,
|
||||
bool ShouldFork(blink::WebLocalFrame* frame,
|
||||
const GURL& url,
|
||||
const std::string& http_method,
|
||||
bool is_initial_navigation,
|
||||
|
@ -64,9 +64,6 @@ class AtomRendererClient : public content::ContentRendererClient,
|
|||
scoped_ptr<NodeBindings> node_bindings_;
|
||||
scoped_ptr<AtomBindings> atom_bindings_;
|
||||
|
||||
// The main frame.
|
||||
blink::WebFrame* main_frame_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomRendererClient);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,7 +6,9 @@
|
|||
|
||||
#include <map>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
namespace atom {
|
||||
|
@ -20,7 +22,8 @@ static base::LazyInstance<GuestViewContainerMap> g_guest_view_container_map =
|
|||
} // namespace
|
||||
|
||||
GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame)
|
||||
: render_frame_(render_frame) {
|
||||
: render_frame_(render_frame),
|
||||
weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
GuestViewContainer::~GuestViewContainer() {
|
||||
|
@ -55,4 +58,8 @@ void GuestViewContainer::DidResizeElement(const gfx::Size& new_size) {
|
|||
FROM_HERE, base::Bind(element_resize_callback_, new_size));
|
||||
}
|
||||
|
||||
base::WeakPtr<content::BrowserPluginDelegate> GuestViewContainer::GetWeakPtr() {
|
||||
return weak_ptr_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -28,6 +28,7 @@ class GuestViewContainer : public content::BrowserPluginDelegate {
|
|||
// content::BrowserPluginDelegate:
|
||||
void SetElementInstanceID(int element_instance_id) final;
|
||||
void DidResizeElement(const gfx::Size& new_size) final;
|
||||
base::WeakPtr<BrowserPluginDelegate> GetWeakPtr() final;
|
||||
|
||||
private:
|
||||
int element_instance_id_;
|
||||
|
@ -35,6 +36,8 @@ class GuestViewContainer : public content::BrowserPluginDelegate {
|
|||
|
||||
ResizeCallback element_resize_callback_;
|
||||
|
||||
base::WeakPtrFactory<GuestViewContainer> weak_ptr_factory_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GuestViewContainer);
|
||||
};
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ for arg in process.argv
|
|||
if arg.indexOf('--guest-instance-id=') == 0
|
||||
# This is a guest web view.
|
||||
process.guestInstanceId = parseInt arg.substr(arg.indexOf('=') + 1)
|
||||
# Set the frame name to make AtomRendererClient recognize this guest.
|
||||
require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW'
|
||||
else if arg.indexOf('--node-integration=') == 0
|
||||
nodeIntegration = arg.substr arg.indexOf('=') + 1
|
||||
else if arg.indexOf('--preload=') == 0
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
window.onload = ->
|
||||
inspectorFrame = document.getElementById('inspector-app-iframe').contentWindow
|
||||
|
||||
# Use menu API to show context menu.
|
||||
inspectorFrame.eval 'InspectorFrontendHost.showContextMenuAtPoint = parent.createMenu'
|
||||
InspectorFrontendHost.showContextMenuAtPoint = createMenu
|
||||
|
||||
# Use dialog API to override file chooser dialog.
|
||||
inspectorFrame.eval 'WebInspector.createFileSelectorElement = parent.createFileSelectorElement'
|
||||
WebInspector.createFileSelectorElement = createFileSelectorElement
|
||||
|
||||
convertToMenuTemplate = (items) ->
|
||||
template = []
|
||||
|
@ -60,7 +58,3 @@ createFileSelectorElement = (callback) ->
|
|||
fileSelectorElement.style.display = 'none'
|
||||
fileSelectorElement.click = showFileChooserDialog.bind this, callback
|
||||
return fileSelectorElement
|
||||
|
||||
# Exposed for iframe.
|
||||
window.createMenu = createMenu
|
||||
window.createFileSelectorElement = createFileSelectorElement
|
||||
|
|
|
@ -94,14 +94,22 @@ window.confirm = (message, title='') ->
|
|||
window.prompt = ->
|
||||
throw new Error('prompt() is and will not be supported.')
|
||||
|
||||
# Simple implementation of postMessage.
|
||||
if ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_IS_GUEST_WINDOW'
|
||||
# Implement window.postMessage if current window is a guest window.
|
||||
guestId = ipc.sendSync 'ATOM_SHELL_GUEST_WINDOW_MANAGER_GET_GUEST_ID'
|
||||
if guestId?
|
||||
window.opener =
|
||||
postMessage: (message, targetOrigin='*') ->
|
||||
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', message, targetOrigin
|
||||
ipc.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_OPENER_POSTMESSAGE', guestId, message, targetOrigin, location.origin
|
||||
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (message, targetOrigin) ->
|
||||
window.postMessage message, targetOrigin
|
||||
ipc.on 'ATOM_SHELL_GUEST_WINDOW_POSTMESSAGE', (guestId, message, sourceOrigin) ->
|
||||
# Manually dispatch event instead of using postMessage because we also need to
|
||||
# set event.source.
|
||||
event = document.createEvent 'Event'
|
||||
event.initEvent 'message', false, false
|
||||
event.data = message
|
||||
event.origin = sourceOrigin
|
||||
event.source = new BrowserWindowProxy(guestId)
|
||||
window.dispatchEvent event
|
||||
|
||||
# Forward history operations to browser.
|
||||
sendHistoryOperation = (args...) ->
|
||||
|
|
|
@ -296,8 +296,7 @@ void PdfToEmfUtilityProcessHostClient::Start(
|
|||
// generate when sent to a metafile DC.
|
||||
utility_process_host_ =
|
||||
content::UtilityProcessHost::Create(
|
||||
this, base::MessageLoop::current()->message_loop_proxy())
|
||||
->AsWeakPtr();
|
||||
this, base::MessageLoop::current()->task_runner())->AsWeakPtr();
|
||||
if (!utility_process_host_)
|
||||
return OnFailed();
|
||||
// Should reply with OnProcessStarted().
|
||||
|
|
|
@ -220,64 +220,6 @@ PrintedDocument* PrintJob::document() const {
|
|||
return document_.get();
|
||||
}
|
||||
|
||||
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
|
||||
if (document_.get() == new_document)
|
||||
return;
|
||||
|
||||
document_ = new_document;
|
||||
|
||||
if (document_.get()) {
|
||||
settings_ = document_->settings();
|
||||
}
|
||||
|
||||
if (worker_) {
|
||||
DCHECK(!is_job_pending_);
|
||||
// Sync the document with the worker.
|
||||
worker_->PostTask(FROM_HERE,
|
||||
base::Bind(&HoldRefCallback,
|
||||
make_scoped_refptr(this),
|
||||
base::Bind(&PrintJobWorker::OnDocumentChanged,
|
||||
base::Unretained(worker_.get()),
|
||||
document_)));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::FAILED: {
|
||||
settings_.Clear();
|
||||
// No need to cancel since the worker already canceled itself.
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED: {
|
||||
DCHECK_EQ(event_details.document(), document_.get());
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::NEW_DOC:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::JOB_DONE:
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
// Don't care.
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::DOC_DONE: {
|
||||
// This will call Stop() and broadcast a JOB_DONE message.
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
break;
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
class PrintJob::PdfToEmfState {
|
||||
|
@ -375,6 +317,68 @@ void PrintJob::OnPdfToEmfPageConverted(int page_number,
|
|||
|
||||
#endif // OS_WIN
|
||||
|
||||
void PrintJob::UpdatePrintedDocument(PrintedDocument* new_document) {
|
||||
if (document_.get() == new_document)
|
||||
return;
|
||||
|
||||
document_ = new_document;
|
||||
|
||||
if (document_.get()) {
|
||||
settings_ = document_->settings();
|
||||
}
|
||||
|
||||
if (worker_) {
|
||||
DCHECK(!is_job_pending_);
|
||||
// Sync the document with the worker.
|
||||
worker_->PostTask(FROM_HERE,
|
||||
base::Bind(&HoldRefCallback,
|
||||
make_scoped_refptr(this),
|
||||
base::Bind(&PrintJobWorker::OnDocumentChanged,
|
||||
base::Unretained(worker_.get()),
|
||||
document_)));
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::OnNotifyPrintJobEvent(const JobEventDetails& event_details) {
|
||||
switch (event_details.type()) {
|
||||
case JobEventDetails::FAILED: {
|
||||
settings_.Clear();
|
||||
// No need to cancel since the worker already canceled itself.
|
||||
Stop();
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::USER_INIT_DONE:
|
||||
case JobEventDetails::DEFAULT_INIT_DONE:
|
||||
case JobEventDetails::USER_INIT_CANCELED: {
|
||||
DCHECK_EQ(event_details.document(), document_.get());
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::NEW_DOC:
|
||||
case JobEventDetails::NEW_PAGE:
|
||||
case JobEventDetails::JOB_DONE:
|
||||
case JobEventDetails::ALL_PAGES_REQUESTED: {
|
||||
// Don't care.
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::DOC_DONE: {
|
||||
// This will call Stop() and broadcast a JOB_DONE message.
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::Bind(&PrintJob::OnDocumentDone, this));
|
||||
break;
|
||||
}
|
||||
case JobEventDetails::PAGE_DONE:
|
||||
#if defined(OS_WIN)
|
||||
ptd_to_emf_state_->OnPageProcessed(
|
||||
base::Bind(&PrintJob::OnPdfToEmfPageConverted, this));
|
||||
#endif // OS_WIN
|
||||
break;
|
||||
default: {
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrintJob::OnDocumentDone() {
|
||||
// Be sure to live long enough. The instance could be destroyed by the
|
||||
// JOB_DONE broadcast.
|
||||
|
|
|
@ -46,7 +46,8 @@ ui::ClipboardType ConvertClipboardType(uint32_t type) {
|
|||
// assume all data that is placed on the clipboard is UTF16 and pepper allows
|
||||
// arbitrary data so this change would require some reworking of the chrome
|
||||
// clipboard interface for custom data.
|
||||
bool JumpToFormatInPickle(const base::string16& format, PickleIterator* iter) {
|
||||
bool JumpToFormatInPickle(const base::string16& format,
|
||||
base::PickleIterator* iter) {
|
||||
size_t size = 0;
|
||||
if (!iter->ReadSizeT(&size))
|
||||
return false;
|
||||
|
@ -66,22 +67,22 @@ bool JumpToFormatInPickle(const base::string16& format, PickleIterator* iter) {
|
|||
}
|
||||
|
||||
bool IsFormatAvailableInPickle(const base::string16& format,
|
||||
const Pickle& pickle) {
|
||||
PickleIterator iter(pickle);
|
||||
const base::Pickle& pickle) {
|
||||
base::PickleIterator iter(pickle);
|
||||
return JumpToFormatInPickle(format, &iter);
|
||||
}
|
||||
|
||||
std::string ReadDataFromPickle(const base::string16& format,
|
||||
const Pickle& pickle) {
|
||||
const base::Pickle& pickle) {
|
||||
std::string result;
|
||||
PickleIterator iter(pickle);
|
||||
base::PickleIterator iter(pickle);
|
||||
if (!JumpToFormatInPickle(format, &iter) || !iter.ReadString(&result))
|
||||
return std::string();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool WriteDataToPickle(const std::map<base::string16, std::string>& data,
|
||||
Pickle* pickle) {
|
||||
base::Pickle* pickle) {
|
||||
pickle->WriteSizeT(data.size());
|
||||
for (std::map<base::string16, std::string>::const_iterator it = data.begin();
|
||||
it != data.end();
|
||||
|
@ -187,7 +188,7 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgIsFormatAvailable(
|
|||
std::string clipboard_data;
|
||||
clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(),
|
||||
&clipboard_data);
|
||||
Pickle pickle(clipboard_data.data(), clipboard_data.size());
|
||||
base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
|
||||
available =
|
||||
IsFormatAvailableInPickle(base::UTF8ToUTF16(format_name), pickle);
|
||||
}
|
||||
|
@ -265,7 +266,7 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgReadData(
|
|||
std::string clipboard_data;
|
||||
clipboard->ReadData(ui::Clipboard::GetPepperCustomDataFormatType(),
|
||||
&clipboard_data);
|
||||
Pickle pickle(clipboard_data.data(), clipboard_data.size());
|
||||
base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
|
||||
if (IsFormatAvailableInPickle(format_name, pickle)) {
|
||||
result = PP_OK;
|
||||
clipboard_string = ReadDataFromPickle(format_name, pickle);
|
||||
|
@ -340,7 +341,7 @@ int32_t PepperFlashClipboardMessageFilter::OnMsgWriteData(
|
|||
}
|
||||
|
||||
if (custom_data_map.size() > 0) {
|
||||
Pickle pickle;
|
||||
base::Pickle pickle;
|
||||
if (WriteDataToPickle(custom_data_map, &pickle)) {
|
||||
scw.WritePickledData(pickle,
|
||||
ui::Clipboard::GetPepperCustomDataFormatType());
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#if defined(OS_WIN)
|
||||
// A vector of filters, each being a Tuple containing a display string (i.e.
|
||||
// "Text Files") and a filter pattern (i.e. "*.txt").
|
||||
typedef std::vector<Tuple<base::string16, base::string16>>
|
||||
typedef std::vector<base::Tuple<base::string16, base::string16>>
|
||||
GetOpenFileNameFilter;
|
||||
#endif // OS_WIN
|
||||
|
||||
|
|
|
@ -56,17 +56,9 @@ void PepperSharedMemoryMessageFilter::OnHostMsgCreateSharedMemory(
|
|||
->GetVarTracker()
|
||||
->TrackSharedMemoryHandle(instance, host_shm_handle, size);
|
||||
|
||||
base::PlatformFile host_handle =
|
||||
#if defined(OS_WIN)
|
||||
host_shm_handle;
|
||||
#elif defined(OS_POSIX)
|
||||
host_shm_handle.fd;
|
||||
#else
|
||||
#error Not implemented.
|
||||
#endif
|
||||
// We set auto_close to false since we need our file descriptor to
|
||||
// actually be duplicated on linux. The shared memory destructor will
|
||||
// close the original handle for us.
|
||||
plugin_handle->set_shmem(host_->ShareHandleWithRemote(host_handle, false),
|
||||
size);
|
||||
plugin_handle->set_shmem(
|
||||
host_->ShareSharedMemoryHandleWithRemote(host_shm_handle), size);
|
||||
}
|
||||
|
|
|
@ -427,9 +427,10 @@ class PrepareFrameAndViewForPrint : public blink::WebViewClient,
|
|||
// blink::WebFrameClient override:
|
||||
virtual blink::WebFrame* createChildFrame(
|
||||
blink::WebLocalFrame* parent,
|
||||
blink::WebTreeScopeType scope,
|
||||
const blink::WebString& name,
|
||||
blink::WebSandboxFlags sandboxFlags);
|
||||
virtual void frameDetached(blink::WebFrame* frame);
|
||||
virtual void frameDetached(blink::WebFrame* frame, DetachType type);
|
||||
|
||||
private:
|
||||
void CallOnReady();
|
||||
|
@ -548,7 +549,8 @@ void PrepareFrameAndViewForPrint::CopySelection(
|
|||
blink::WebView* web_view = blink::WebView::create(this);
|
||||
owns_web_view_ = true;
|
||||
content::RenderView::ApplyWebPreferences(prefs, web_view);
|
||||
web_view->setMainFrame(blink::WebLocalFrame::create(this));
|
||||
web_view->setMainFrame(
|
||||
blink::WebLocalFrame::create(blink::WebTreeScopeType::Document, this));
|
||||
frame_.Reset(web_view->mainFrame()->toWebLocalFrame());
|
||||
node_to_print_.reset();
|
||||
|
||||
|
@ -573,14 +575,17 @@ void PrepareFrameAndViewForPrint::didStopLoading() {
|
|||
|
||||
blink::WebFrame* PrepareFrameAndViewForPrint::createChildFrame(
|
||||
blink::WebLocalFrame* parent,
|
||||
blink::WebTreeScopeType scope,
|
||||
const blink::WebString& name,
|
||||
blink::WebSandboxFlags sandboxFlags) {
|
||||
blink::WebFrame* frame = blink::WebLocalFrame::create(this);
|
||||
blink::WebFrame* frame = blink::WebLocalFrame::create(scope, this);
|
||||
parent->appendChild(frame);
|
||||
return frame;
|
||||
}
|
||||
|
||||
void PrepareFrameAndViewForPrint::frameDetached(blink::WebFrame* frame) {
|
||||
void PrepareFrameAndViewForPrint::frameDetached(blink::WebFrame* frame,
|
||||
DetachType type) {
|
||||
DCHECK(type == DetachType::Remove);
|
||||
if (frame->parent())
|
||||
frame->parent()->removeChild(frame);
|
||||
frame->close();
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
'-Wno-deprecated-declarations',
|
||||
'-Wno-return-type',
|
||||
'-Wno-gnu-folding-constant',
|
||||
'-Wno-shift-negative-value',
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
|
@ -99,6 +100,7 @@
|
|||
'-Wno-unused-value',
|
||||
'-Wno-deprecated-declarations',
|
||||
'-Wno-return-type',
|
||||
'-Wno-shift-negative-value',
|
||||
# Required when building as shared library.
|
||||
'-fPIC',
|
||||
],
|
||||
|
|
|
@ -62,7 +62,7 @@ Módulos de ambos procesos:
|
|||
* [Estructura de directorio](development/source-code-directory-structure.md)
|
||||
* [Diferencias técnicas con NW.js (anteriormente conocido como node-webkit)](development/atom-shell-vs-node-webkit.md)
|
||||
* [Sistema de compilación](development/build-system-overview.md)
|
||||
* [Instrucciones de compilación (Mac)](development/build-instructions-mac.md)
|
||||
* [Instrucciones de compilación (Mac)](development/build-instructions-osx.md)
|
||||
* [Instrucciones de compilación (Windows)](development/build-instructions-windows.md)
|
||||
* [Instrucciones de compilación (Linux)](development/build-instructions-linux.md)
|
||||
* [Configurando un servidor de símbolos en el depurador](development/setting-up-symbol-server.md)
|
||||
|
|
|
@ -14,17 +14,17 @@ Electronでは、`package.json` の `main`で実行されるプロセスを __
|
|||
|
||||
Electronはウェブページを表示させるためにChromiumを使用しているので、Chromiumのマルチプロセスアーキテクチャが使用されることになります。Electronで実行されるウェブページはそれぞれ自身のプロセスで実行されます。それを __レンダラープロセス__ と呼びます。
|
||||
|
||||
通常、ブラウザのウェブページはサウンドボックス環境で実行されネイティブなリソースへのアクセスができません。Electronではウェブページからio.jsのAPIを使って、ネイティブリソースへの権限が与えられます。そのおかげでウェブページの中からJavaScriptを使って低レベルなオペレーティングシステムとのインタラクションが可能になります。
|
||||
通常、ブラウザのウェブページはサンドボックス環境で実行されネイティブなリソースへのアクセスができません。Electronではウェブページからio.jsのAPIを使って、ネイティブリソースへの権限が与えられます。そのおかげでウェブページの中からJavaScriptを使って低レベルなオペレーティングシステムとのインタラクションが可能になります。
|
||||
|
||||
### メインプロセスとリレンダラープロセスの違い
|
||||
### メインプロセスとレンダラープロセスの違い
|
||||
|
||||
メインプロセスは `BrowserWindow` インスタンスを作ることによってウェブページをつくります。それぞれの `BrowserWindow` インスタンスはそれ自身の リレンダラープロセス上でウェブページを実行します。`BrowserWindow` インスタンスが破棄されると、対応するリレンダラープロセスも終了されます。
|
||||
メインプロセスは `BrowserWindow` インスタンスを作ることによってウェブページをつくります。それぞれの `BrowserWindow` インスタンスはそれ自身の レンダラープロセス上でウェブページを実行します。`BrowserWindow` インスタンスが破棄されると、対応するレンダラープロセスも終了されます。
|
||||
|
||||
メインプロセスはすべてのウェブページとそれに対応するリレンダラープロセスを管理しています。それぞれのリレンダラープロセスは分離しているのでウェブページで実行されていることだけを気に留めておいてください。
|
||||
メインプロセスはすべてのウェブページとそれに対応するレンダラープロセスを管理しています。それぞれのレンダラープロセスは分離しているのでウェブページで実行されていることだけを気に留めておいてください。
|
||||
|
||||
ウェブページでは、GUI関連のAPIを呼ぶことはできません。なぜならば、ウェブページで管理しているネイティブのGUIリソースは非常に危険で簡単にリークしてしまうからです。もしウェブページ内でGUIを操作したい場合には、メインプロセスと通信をする必要があります。
|
||||
|
||||
Electronでは、メインプロセスとリレンダラープロセスとのコミュニケーションをするために[ipc](../api/ipc-renderer.md)モジュールを提供しています。またそれと、RPC形式の通信を行う[remote](../api/remote.md)モジュールもあります。
|
||||
Electronでは、メインプロセスとレンダラープロセスとのコミュニケーションをするために[ipc](../api/ipc-renderer.md)モジュールを提供しています。またそれと、RPC形式の通信を行う[remote](../api/remote.md)モジュールもあります。
|
||||
|
||||
## Electronアプリを作成する
|
||||
|
|
@ -17,14 +17,14 @@
|
|||
## API 레퍼런스
|
||||
|
||||
* [개요](api/synopsis.md)
|
||||
* [프로세스 객체](api/process.md)
|
||||
* [process](api/process.md)
|
||||
* [크롬 Command-Line 스위치 지원](api/chrome-command-line-switches.md)
|
||||
|
||||
커스텀 DOM Element:
|
||||
커스텀 DOM elements:
|
||||
|
||||
* [`File` 객체](api/file-object.md)
|
||||
* [`<webview>` 태그](api/web-view-tag.md)
|
||||
* [`window.open` 함수](api/window-open.md)
|
||||
* [`window.open` 메서드](api/window-open.md)
|
||||
|
||||
메인 프로세스를 위한 모듈들:
|
||||
|
||||
|
@ -40,6 +40,8 @@
|
|||
* [power-monitor](api/power-monitor.md)
|
||||
* [power-save-blocker](api/power-save-blocker.md)
|
||||
* [protocol](api/protocol.md)
|
||||
* [session](api/session.md)
|
||||
* [webContents](api/web-contents.md)
|
||||
* [tray](api/tray.md)
|
||||
|
||||
랜더러 프로세스를 위한 모듈들 (웹 페이지):
|
||||
|
@ -60,9 +62,9 @@
|
|||
|
||||
* [코딩 스타일](development/coding-style.md)
|
||||
* [소스 코드 디렉터리 구조](development/source-code-directory-structure.md)
|
||||
* [NW.js와 기술적으로 다른점 (이전 node-webkit)](development/atom-shell-vs-node-webkit.md)
|
||||
* [NW.js(node-webkit)와 기술적으로 다른점](development/atom-shell-vs-node-webkit.md)
|
||||
* [빌드 시스템 개요](development/build-system-overview.md)
|
||||
* [빌드 설명서 (Mac)](development/build-instructions-mac.md)
|
||||
* [빌드 설명서 (Mac)](development/build-instructions-osx.md)
|
||||
* [빌드 설명서 (Windows)](development/build-instructions-windows.md)
|
||||
* [빌드 설명서 (Linux)](development/build-instructions-linux.md)
|
||||
* [디버거에서 디버그 심볼 서버 설정](development/setting-up-symbol-server.md)
|
||||
|
|
|
@ -17,7 +17,7 @@ Squirrel은 어플리케이션이 **안전하고 투명한 업데이트**를 제
|
|||
Squirrel은 사용자에게 어플리케이션의 업데이트를 알릴 필요 없이 서버가 지시하는 버전을 받아온 후 자동으로 업데이트합니다.
|
||||
이 기능을 사용하면 Squirrel을 통해 클라이언트의 어플리케이션을 지능적으로 업데이트 할 수 있습니다.
|
||||
|
||||
요청시 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수도 있습니다.
|
||||
또한 요청시 커스텀 헤더 또는 요청 본문에 인증 정보를 포함시킬 수 있습니다.
|
||||
서버에선 이러한 요청을 분류 처리하여 적당한 업데이트를 제공할 수 있습니다.
|
||||
|
||||
Squirrel JSON 업데이트 요청시 처리는 반드시 어떤 업데이트가 필요한지 요청의 기준에 맞춰 동적으로 생성되어야 합니다.
|
||||
|
@ -76,6 +76,12 @@ Squirrel은 "url"로 `Accept: application/zip` 헤더와 함께 업데이트 zip
|
|||
|
||||
`pub_date`은 ISO 8601 표준에 따라 포맷된 날짜입니다.
|
||||
|
||||
## 업데이트 서버 구현
|
||||
|
||||
[Nuts](https://github.com/GitbookIO/nuts)는 위에서 설명한 업데이트 서버의 오픈 소스 구현입니다.
|
||||
이 구현은 Github 릴리즈와 완벽하게 통합되어 있습니다. Nuts는 `Squirrel.Mac`과 `Squirrel.Windows`를 지원하고 다운로드와 업데이트를 관리합니다.
|
||||
이 구현을 사용하면 cross-platform 지원을 신경 쓸 필요가 없습니다.
|
||||
|
||||
## Events
|
||||
|
||||
`autoUpdater` 객체는 다음과 같은 이벤트를 발생시킵니다:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# clipboard
|
||||
|
||||
`clipboard`는 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다:
|
||||
`clipboard` 모듈은 복사/붙여넣기 작업을 수행하는 방법을 제공합니다. 다음 예제는 클립보드에 문자열을 씁니다:
|
||||
|
||||
```javascript
|
||||
var clipboard = require('clipboard');
|
||||
|
@ -15,59 +15,65 @@ clipboard.writeText('Example String', 'selection');
|
|||
console.log(clipboard.readText('selection'));
|
||||
```
|
||||
|
||||
## clipboard.readText([type])
|
||||
## Methods
|
||||
|
||||
* `type` String
|
||||
`clipboard` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
**참고:** Experimental 마크가 붙은 API는 실험적인 기능이며 차후 최신 버전에서 제거될 수 있습니다.
|
||||
|
||||
### `clipboard.readText([type])`
|
||||
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드 컨텐츠를 `plain text`로 반환합니다.
|
||||
|
||||
## clipboard.writeText(text[, type])
|
||||
### `clipboard.writeText(text[, type])`
|
||||
|
||||
* `text` String
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드에 `plain text`로 문자열을 씁니다.
|
||||
|
||||
## clipboard.readHtml([type])
|
||||
### `clipboard.readHtml([type])`
|
||||
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드 컨텐츠를 `markup`으로 반환합니다.
|
||||
|
||||
## clipboard.writeHtml(markup[, type])
|
||||
### `clipboard.writeHtml(markup[, type])`
|
||||
|
||||
* `markup` String
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드에 `markup`으로 씁니다.
|
||||
|
||||
## clipboard.readImage([type])
|
||||
### `clipboard.readImage([type])`
|
||||
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드로부터 [NativeImage](native-image.md)로 이미지를 읽어들입니다.
|
||||
|
||||
## clipboard.writeImage(image[, type])
|
||||
### `clipboard.writeImage(image[, type])`
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드에 `image`를 씁니다.
|
||||
|
||||
## clipboard.clear([type])
|
||||
### `clipboard.clear([type])`
|
||||
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드에 저장된 모든 컨텐츠를 삭제합니다.
|
||||
|
||||
## clipboard.availableFormats([type])
|
||||
### clipboard.availableFormats([type])
|
||||
|
||||
클립보드의 `type`에 해당하는 지원하는 `format`을 문자열로 반환합니다.
|
||||
|
||||
## clipboard.has(data[, type])
|
||||
### `clipboard.has(data[, type])`
|
||||
|
||||
* `data` String
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드가 지정한 `data`의 형식을 지원하는지 확인합니다.
|
||||
|
||||
|
@ -76,24 +82,20 @@ var clipboard = require('clipboard');
|
|||
console.log(clipboard.has('<p>selection</p>'));
|
||||
```
|
||||
|
||||
**알림:** 이 API는 실험적인 기능이며 차후 최신버전에서 제외될 수 있습니다.
|
||||
|
||||
## clipboard.read(data[, type])
|
||||
### `clipboard.read(data[, type])` _Experimental_
|
||||
|
||||
* `data` String
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
클립보드로부터 `data`를 읽어들입니다.
|
||||
|
||||
**알림:** 이 API는 실험적인 기능이며 차후 최신버전에서 제외될 수 있습니다.
|
||||
|
||||
## clipboard.write(data[, type])
|
||||
### `clipboard.write(data[, type])` _Experimental_
|
||||
|
||||
* `data` Object
|
||||
* `text` String
|
||||
* `html` String
|
||||
* `image` [NativeImage](native-image.md)
|
||||
* `type` String
|
||||
* `type` String (optional)
|
||||
|
||||
```javascript
|
||||
var clipboard = require('clipboard');
|
||||
|
|
|
@ -1,30 +1,35 @@
|
|||
# content-tracing
|
||||
# contentTracing
|
||||
|
||||
`content-trace` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 추적하는데 사용됩니다.
|
||||
`content-tracing` 모듈은 Chromium 컨텐츠 모듈단에서 생성된 데이터를 수집하고 추적하는데 사용됩니다.
|
||||
이 모듈은 웹 인터페이스를 포함하고 있지 않으며 크롬 브라우저에서 `chrome://tracing/` 페이지를 열어 생성된 파일을 로드하면 결과를 볼 수 있습니다.
|
||||
|
||||
```javascript
|
||||
var tracing = require('content-tracing');
|
||||
tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
|
||||
var contentTracing = require('content-tracing');
|
||||
|
||||
contentTracing.startRecording('*', contentTracing.DEFAULT_OPTIONS, function() {
|
||||
console.log('Tracing started');
|
||||
|
||||
setTimeout(function() {
|
||||
tracing.stopRecording('', function(path) {
|
||||
contentTracing.stopRecording('', function(path) {
|
||||
console.log('Tracing data recorded to ' + path);
|
||||
});
|
||||
}, 5000);
|
||||
});
|
||||
```
|
||||
``
|
||||
|
||||
## tracing.getCategories(callback)
|
||||
## Methods
|
||||
|
||||
`content-tracing` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `contentTracing.getCategories(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
카테고리 그룹 세트를 가져옵니다. 카테고리 그룹은 도달된 코드 경로를 변경할 수 있습니다.
|
||||
|
||||
모든 child 프로세스가 `getCategories` 요청을 받으면 `callback`이 호출되며 인자에 카테고리 그룹의 배열이 전달됩니다.
|
||||
모든 child 프로세스가 `getCategories` 요청을 승인하면 `callback`이 한 번 호출되며 인자에 카테고리 그룹의 배열이 전달됩니다.
|
||||
|
||||
## tracing.startRecording(categoryFilter, traceOptions, callback)
|
||||
### `contentTracing.startRecording(categoryFilter, traceOptions, callback)`
|
||||
|
||||
* `categoryFilter` String
|
||||
* `traceOptions` String
|
||||
|
@ -33,7 +38,7 @@ tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
|
|||
모든 프로세스에서 레코딩을 시작합니다.
|
||||
|
||||
레코딩은 지역적으로 즉시 실행됩니다. 그리고 비동기로 child 프로세스는 곧 EnableRecording 요청을 받게 됩니다.
|
||||
모든 child 프로세스가 `startRecording` 요청을 받으면 `callback`이 호출됩니다.
|
||||
모든 child 프로세스가 `startRecording` 요청을 승인하면 `callback`이 한 번 호출됩니다.
|
||||
|
||||
`categoryFilter`는 어떤 카테고리 그룹이 트레이싱 되어야 하는지 필터링할 수 있습니다.
|
||||
필터는 `-` 접두사를 통해 특정 카테고리 그룹을 제외할 수 있습니다.
|
||||
|
@ -63,7 +68,7 @@ tracing.startRecording('*', tracing.DEFAULT_OPTIONS, function() {
|
|||
|
||||
`record-until-full`이 기본 모드, `enable-sampling`과 `enable-systrace`옵션은 포함되지 않음
|
||||
|
||||
## tracing.stopRecording(resultFilePath, callback)
|
||||
## `contentTracing.stopRecording(resultFilePath, callback)`
|
||||
|
||||
* `resultFilePath` String
|
||||
* `callback` Function
|
||||
|
@ -75,12 +80,12 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
|
|||
우리는 추적에 의한 런타임 오버헤드를 피하고자 합니다.
|
||||
그래서 추적이 끝나면 모든 child 프로세스에 보류된 추적 데이터를 플러시 할 것인지 물어봅니다.
|
||||
|
||||
모든 child 프로세스가 `stopRecording` 요청을 받으면 `callback`에 추적 데이터를 포함한 파일을 전달됩니다.
|
||||
모든 child 프로세스가 `stopRecording` 요청을 승인하면 `callback`에 추적 데이터 파일을 포함하여 한 번 호출됩니다.
|
||||
|
||||
추적 데이터는 `resultFilePath` 해당 경로가 비어있는 경우에 한 해 해당 경로에 작성되거나 임시 파일에 작성됩니다.
|
||||
실제 파일 경로는 null이 아닌 이상 `callback`을 통해 전달됩니다.
|
||||
|
||||
## tracing.startMonitoring(categoryFilter, traceOptions, callback)
|
||||
### `contentTracing.startMonitoring(categoryFilter, traceOptions, callback)`
|
||||
|
||||
* `categoryFilter` String
|
||||
* `traceOptions` String
|
||||
|
@ -90,17 +95,17 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
|
|||
|
||||
모니터링은 지역적으로 즉시 시작됩니다. 그리고 이내 자식 프로세스들이 `startMonitoring` 비동기 요청을 받습니다.
|
||||
|
||||
모든 자식 프로세스가 `startMonitoring` 요청을 받으면 `callback`이 호출됩니다.
|
||||
모든 자식 프로세스가 `startMonitoring` 요청을 승인하면 `callback`이 한 번 호출됩니다.
|
||||
|
||||
## tracing.stopMonitoring(callback);
|
||||
### `contentTracing.stopMonitoring(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
모든 프로세스에서 모니터링을 중단합니다.
|
||||
|
||||
모든 자식 프로세스가 `stopMonitoring` 요청을 받으면 `callback`이 호출됩니다.
|
||||
모든 자식 프로세스가 `stopMonitoring` 요청을 승인하면 `callback`이 한 번 호출됩니다.
|
||||
|
||||
## tracing.captureMonitoringSnapshot(resultFilePath, callback)
|
||||
### `contentTracing.captureMonitoringSnapshot(resultFilePath, callback)`
|
||||
|
||||
* `resultFilePath` String
|
||||
* `callback` Function
|
||||
|
@ -112,15 +117,15 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
|
|||
그리고 우리는 추적시 발생하는 불필요한 런타임 오버헤드를 피하고자 합니다.
|
||||
그래서 추적이 끝나면 반드시 비동기로 자식 프로세스들의 보류된 추적 데이터를 플러시 할 것인지 물어봅니다.
|
||||
|
||||
모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 받으면 추적 데이터 파일을 포함하는 `callback`이 호출됩니다.
|
||||
모든 자식 프로세스가 `captureMonitoringSnapshot` 요청을 승인하면 추적 데이터 파일을 포함하는 `callback`이 한 번 호출됩니다.
|
||||
|
||||
## tracing.getTraceBufferUsage(callback)
|
||||
### `contentTracing.getTraceBufferUsage(callback)`
|
||||
|
||||
* `callback` Function
|
||||
|
||||
추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 결정되면 `callback`이 호출됩니다.
|
||||
추적 버퍼 % 전체 상태의 프로세스간 최대치를 가져옵니다. TraceBufferUsage 값이 결정되면 `callback`이 한 번 호출됩니다.
|
||||
|
||||
## tracing.setWatchEvent(categoryName, eventName, callback)
|
||||
### `contentTracing.setWatchEvent(categoryName, eventName, callback)`
|
||||
|
||||
* `categoryName` String
|
||||
* `eventName` String
|
||||
|
@ -128,6 +133,6 @@ Child 프로세스는 일반적으로 추적 데이터와 희귀한 플러시
|
|||
|
||||
`callback`은 지정된 이벤트가 어떤 작업을 발생시킬 때마다 호출됩니다.
|
||||
|
||||
## tracing.cancelWatchEvent()
|
||||
### `contentTracing.cancelWatchEvent()`
|
||||
|
||||
Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 함수는 watch 이벤트 콜백과 race가 일어날 것입니다.
|
||||
Watch 이벤트를 중단합니다. 만약 추적이 활성화되어 있다면 이 메서드는 watch 이벤트 콜백과 race가 일어날 것입니다.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
# crash-reporter
|
||||
# crashReporter
|
||||
|
||||
다음 예제는 윈격 서버에 어플리케이션 오류 정보를 자동으로 보고하는 예제입니다:
|
||||
`crash-reporter` 모듈은 어플리케이션의 크래시 정보를 자동으로 원격 서버에 업로드하는데 사용합니다.
|
||||
|
||||
다음 예제는 윈격 서버에 어플리케이션 크래시 정보를 자동으로 보고하는 예제입니다:
|
||||
|
||||
```javascript
|
||||
crashReporter = require('crash-reporter');
|
||||
var crashReporter = require('crash-reporter');
|
||||
|
||||
crashReporter.start({
|
||||
productName: 'YourName',
|
||||
companyName: 'YourCompany',
|
||||
|
@ -12,38 +15,42 @@ crashReporter.start({
|
|||
});
|
||||
```
|
||||
|
||||
## crashReporter.start(options)
|
||||
## Methods
|
||||
|
||||
`crash-reporter` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `crashReporter.start(options)`
|
||||
|
||||
* `options` Object, properties:
|
||||
|
||||
* `options` Object
|
||||
* `productName` String, 기본값: Electron
|
||||
* `companyName` String, 기본값: GitHub, Inc
|
||||
* `submitUrl` String, 기본값: http://54.249.141.255:1127/post
|
||||
* Crash Reporter는 POST 방식으로 해당 URL에 전송됩니다.
|
||||
* 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다.
|
||||
* `autoSubmit` Boolean, 기본값: true
|
||||
* true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다.
|
||||
* `ignoreSystemCrashHandler` Boolean, 기본값: false
|
||||
* `extra` Object
|
||||
* 오류보고 시 같이 보낼 추가 정보를 지정하는 객체입니다.
|
||||
* 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다.
|
||||
* 문자열로 된 속성만 정상적으로 보내집니다.
|
||||
* 중첩 객체는 지원되지 않습니다. (Nested objects are not supported)
|
||||
|
||||
다른 crashReporter API들을 사용하기 전에 이 함수를 먼저 호출해야 합니다.
|
||||
다른 crashReporter API를 사용하기 전에 이 메서드를 먼저 호출해야 합니다.
|
||||
|
||||
|
||||
**알림:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` 클라이언트를 사용합니다.
|
||||
**참고:** OS X에선 Windows와 Linux의 `breakpad`와 달리 새로운 `crashpad` 클라이언트를 사용합니다.
|
||||
오류 수집 기능을 활성화 시키려면 오류를 수집하고 싶은 메인 프로세스나 랜더러 프로세스에서
|
||||
`crashReporter.start` 함수를 호출하여 `crashpad`를 초기화 해야합니다.
|
||||
`crashReporter.start` 메서드를 호출하여 `crashpad`를 초기화 해야합니다.
|
||||
|
||||
## crashReporter.getLastCrashReport()
|
||||
### `crashReporter.getLastCrashReport()`
|
||||
|
||||
마지막 오류보고의 날짜와 ID를 반환합니다.
|
||||
이전 오류보고가 없거나 Crash Reporter가 시작되지 않았을 경우 `null`이 반환됩니다.
|
||||
마지막 크래시 리포트의 날짜와 ID를 반환합니다.
|
||||
이전 크래시 리포트가 없거나 Crash Reporter가 시작되지 않았을 경우 `null`이 반환됩니다.
|
||||
|
||||
## crashReporter.getUploadedReports()
|
||||
### `crashReporter.getUploadedReports()`
|
||||
|
||||
모든 업로드된 오류보고를 반환합니다. 각 보고는 날짜와 업로드 ID를 포함하고 있습니다.
|
||||
모든 업로드된 크래시 리포트를 반환합니다. 각 보고는 날짜와 업로드 ID를 포함하고 있습니다.
|
||||
|
||||
# crash-reporter 오류보고 형식
|
||||
## crash-reporter 업로드 형식
|
||||
|
||||
Crash Reporter는 다음과 같은 데이터를 `submitUrl`에 `POST` 방식으로 전송합니다:
|
||||
|
||||
|
@ -56,5 +63,5 @@ Crash Reporter는 다음과 같은 데이터를 `submitUrl`에 `POST` 방식으
|
|||
* `_productName` String - Crash Reporter의 `options` 객체에서 정의한 제품명.
|
||||
* `prod` String - 기본 제품의 이름. 이 경우 Electron으로 표시됩니다.
|
||||
* `_companyName` String - Crash Reporter의 `options` 객체에서 정의한 회사명.
|
||||
* `upload_file_minidump` File - 오류보고 파일
|
||||
* `upload_file_minidump` File - 크래시 리포트 파일
|
||||
* Crash Reporter의 `options` 객체에서 정의한 `extra` 객체의 속성들.
|
||||
|
|
|
@ -1,34 +1,39 @@
|
|||
# dialog
|
||||
|
||||
`dialog` 모듈은 네이티브 시스템의 대화 상자를 조작할 때 사용할 수 있는 API입니다.
|
||||
웹 어플리케이션에서 일반 네이티브 어플리케이션과 같은 사용자 경험을 제공할 수 있습니다.
|
||||
`dialog` 모듈은 파일 열기, 알림과 같은 네이티브 시스템의 대화 상자를 조작할 때 사용할 수 있는 모듈입니다.
|
||||
이 모듈을 사용하면 웹 어플리케이션에서 일반 네이티브 어플리케이션과 비슷한 사용자 경험을 제공할 수 있습니다.
|
||||
|
||||
다음 예제는 파일과 디렉터리를 다중으로 선택하는 대화 상자를 표시하는 예제입니다:
|
||||
|
||||
```javascript
|
||||
var win = ...; // 대화 상자를 사용할 창 객체
|
||||
var win = ...; // 대화 상자를 사용할 BrowserWindow 객체
|
||||
var dialog = require('dialog');
|
||||
console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', 'multiSelections' ]}));
|
||||
```
|
||||
|
||||
**OS X 주의**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 `BrowserWindow` 객체의 참조를 제공하면 됩니다.
|
||||
**OS X 알림**: 대화 상자를 시트처럼 보여지게 하려면 `browserWindow` 인자에 `BrowserWindow` 객체의 참조를 제공하면 됩니다.
|
||||
|
||||
## dialog.showOpenDialog([browserWindow], [options], [callback])
|
||||
## Methods
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `options` Object
|
||||
`dialog` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `dialog.showOpenDialog([browserWindow][, options][, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow (optional)
|
||||
* `options` Object (optional)
|
||||
* `title` String
|
||||
* `defaultPath` String
|
||||
* `filters` Array
|
||||
* `properties` Array - 대화 상자가 사용할 기능(모드)이 담긴 배열입니다.
|
||||
다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory`
|
||||
* `callback` Function
|
||||
* `callback` Function (optional)
|
||||
|
||||
사용할 대화 상자의 기능이 담긴 배열입니다. 다음을 포함할 수 있습니다: `openFile`, `openDirectory`, `multiSelections`, `createDirectory`
|
||||
|
||||
작업에 성공하면 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외의 경우엔 `undefined`를 반환합니다.
|
||||
작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다.
|
||||
|
||||
`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다. 예제는 다음과 같습니다:
|
||||
`filters`를 지정하면 유저가 선택 가능한 파일 형식을 지정할 수 있습니다.
|
||||
유저가 선택할 수 있는 타입에 제한을 두려면 다음과 같이 할 수 있습니다:
|
||||
|
||||
```javascript
|
||||
{
|
||||
|
@ -42,32 +47,30 @@ console.log(dialog.showOpenDialog({ properties: [ 'openFile', 'openDirectory', '
|
|||
```
|
||||
|
||||
`extensions` 배열은 반드시 와일드카드와 마침표를 제외한 파일 확장자를 포함시켜야 합니다.
|
||||
예를 들어 `'png'`는 가능하지만 `'.png'`와 `'*.png'`는 안됩니다.
|
||||
(예를 들어 `'png'`는 가능하지만 `'.png'`와 `'*.png'`는 안됩니다)
|
||||
모든 파일을 보여주려면 `'*'`와 같은 와일드카드를 사용하면 됩니다. (다른 와일드카드는 지원하지 않습니다)
|
||||
|
||||
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filenames)`을 통해 전달됩니다.
|
||||
|
||||
Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 없습니다.
|
||||
그래서 이 두 플랫폼에선 `properties`를 `['openFile', 'openDirectory']`로 설정하면 디렉터리 선택 대화 상자가 표시됩니다.
|
||||
**참고:** Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동시에 사용할 수 없습니다.
|
||||
이러한 이유로 `properties`를 `['openFile', 'openDirectory']`로 설정하면 디렉터리 선택 대화 상자가 표시됩니다.
|
||||
|
||||
## dialog.showSaveDialog([browserWindow], [options], [callback])
|
||||
### `dialog.showSaveDialog([browserWindow][, options][, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `options` Object
|
||||
* `browserWindow` BrowserWindow (optional)
|
||||
* `options` Object (optional)
|
||||
* `title` String
|
||||
* `defaultPath` String
|
||||
* `filters` Array
|
||||
* `callback` Function
|
||||
* `callback` Function (optional)
|
||||
|
||||
작업에 성공하면
|
||||
|
||||
작업에 성공하면 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외의 경우엔 `undefined`를 반환합니다.
|
||||
작업에 성공하면 콜백으로 유저가 선택한 파일의 경로를 포함한 배열을 반환합니다. 그 외엔 `undefined`를 반환합니다.
|
||||
|
||||
`filters`를 지정하면 유저가 저장 가능한 파일 형식을 지정할 수 있습니다. 사용 방법은 `dialog.showOpenDialog`의 `filters` 속성과 같습니다.
|
||||
|
||||
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(filename)`을 통해 전달됩니다.
|
||||
|
||||
## dialog.showMessageBox([browserWindow], options, [callback])
|
||||
### `dialog.showMessageBox([browserWindow][, options][, callback])`
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `options` Object
|
||||
|
@ -78,26 +81,26 @@ Windows와 Linux에선 파일 선택 모드, 디렉터리 선택 모드를 동
|
|||
* `message` String - 대화 상자의 본문 내용입니다.
|
||||
* `detail` String - 메시지의 추가 정보입니다.
|
||||
* `icon` [NativeImage](native-image.md)
|
||||
* `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 때 반환되는 버튼의 index입니다.
|
||||
기본적으로 버튼 리스트가 "cancel" 또는 "no" 라벨을 가지고 있을 때 해당 버튼의 index를 반환합니다. 따로 두 라벨이 지정되지 않은 경우 0을 반환합니다.
|
||||
* `cancelId` Integer - 유저가 대화 상자의 버튼을 클릭하지 않고 대화 상자를 취소했을 때 반환되는 버튼의 인덱스입니다.
|
||||
기본적으로 버튼 리스트가 "cancel" 또는 "no" 라벨을 가지고 있을 때 해당 버튼의 인덱스를 반환합니다. 따로 두 라벨이 지정되지 않은 경우 0을 반환합니다.
|
||||
OS X와 Windows에선 `cancelId` 지정 여부에 상관없이 "Cancel" 버튼이 언제나 `cancelId`로 지정됩니다.
|
||||
* `noLink` Boolean - Windows Electron은 "Cancel"이나 "Yes"와 같은 흔히 사용되는 버튼을 찾으려고 시도하고
|
||||
대화 상자 내에서 해당 버튼을 커맨드 링크처럼 만듭니다. 이 기능으로 앱을 좀 더 Modern Windows 앱처럼 만들 수 있습니다.
|
||||
이 기능을 원하지 않으면 `noLink`를 true로 지정하면 됩니다.
|
||||
* `callback` Function
|
||||
|
||||
대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지는 창을 사용할 수 없습니다.
|
||||
완료시 유저가 선택한 버튼의 index를 반환합니다.
|
||||
대화 상자를 표시합니다. `browserWindow`를 지정하면 대화 상자가 완전히 닫힐 때까지 지정한 창을 사용할 수 없습니다.
|
||||
완료 시 유저가 선택한 버튼의 인덱스를 반환합니다.
|
||||
|
||||
역주: 부정을 표현하는 "아니오", "취소"와 같은 한글 단어는 지원되지 않습니다.
|
||||
만약 OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 해당 대화 상자를 끄게 되면 "확인"을 누른걸로 판단되어 버립니다.
|
||||
만약 OS X 또는 Windows에서 "확인", "취소"와 같은 순서로 버튼을 지정하게 될 때 Alt + f4로 해당 대화 상자를 끄게 되면 "확인"을 누른 것으로 판단되어 버립니다.
|
||||
이를 해결하려면 "Cancel"을 대신 사용하거나 BrowserWindow API를 사용하여 대화 상자를 직접 구현해야합니다.
|
||||
|
||||
`callback`이 전달되면 메소드가 비동기로 작동되며 결과는 `callback(response)`을 통해 전달됩니다.
|
||||
|
||||
## dialog.showErrorBox(title, content)
|
||||
### `dialog.showErrorBox(title, content)`
|
||||
|
||||
에러 메시지를 보여주는 모달 대화 상자를 표시합니다.
|
||||
에러 메시지를 보여주는 대화 상자를 표시합니다.
|
||||
|
||||
이 API는 `app` 모듈의 `ready` 이벤트가 발생하기 전에 사용할 수 있습니다.
|
||||
이 메소드는 보통 어플리케이션이 시작되기 전에 특정한 에러를 표시하기 위해 사용됩니다.
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
# `File` 객체
|
||||
|
||||
DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다. 유저가 직접적으로 HTML5 File API를 사용하여 작업할 때 파일의 경로를
|
||||
알 수 있도록 Electron은 파일시스템의 실제 파일 경로를 담은 `path` 속성을 File 인터페이스에 추가하였습니다.
|
||||
DOM의 File 인터페이스는 네이티브 파일을 추상화 합니다.
|
||||
유저가 직접 HTML5 File API를 이용하여 작업할 때 선택된 파일의 경로를 알 수 있도록
|
||||
Electron은 파일의 실제 경로를 담은 `path` 속성을 File 인터페이스에 추가하였습니다.
|
||||
|
||||
다음 예제는 drag n drop한 파일의 실제 경로를 가져옵니다:
|
||||
다음 예제는 앱으로 드래그 앤 드롭한 파일의 실제 경로를 가져옵니다:
|
||||
|
||||
```html
|
||||
<div id="holder">
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
# Frameless 윈도우
|
||||
# Frameless Window
|
||||
|
||||
Frameless 윈도우는 테두리가 없는 윈도우 창을 말합니다.
|
||||
Frameless Window는 [테두리](https://developer.mozilla.org/en-US/docs/Glossary/Chrome)가 없는 창입니다.
|
||||
이 기능은 윈도우 창의 일부분인 툴바와 같이 웹 페이지의 일부분이 아닌 부분을 보이지 않도록 합니다.
|
||||
[`BrowserWindow`](browser-window.md) 클래스의 옵션에서 설정할 수 있습니다.
|
||||
|
||||
## Frameless 윈도우 만들기
|
||||
## Frameless Window 만들기
|
||||
|
||||
Frameless 윈도우를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하기만 하면됩니다:
|
||||
Frameless Window를 만드려면 [BrowserWindow](browser-window.md) 객체의 `options`에서 `frame` 옵션을 `false`로 지정하면 됩니다:
|
||||
|
||||
```javascript
|
||||
var BrowserWindow = require('browser-window');
|
||||
|
@ -13,7 +15,7 @@ var win = new BrowserWindow({ width: 800, height: 600, frame: false });
|
|||
|
||||
## 투명한 창 만들기
|
||||
|
||||
Frameless 윈도우의 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 바꿔주기만 하면됩니다:
|
||||
Frameless Window의 창의 배경을 투명하게 만들고 싶다면 `transparent` 옵션을 `true`로 바꿔주기만 하면됩니다:
|
||||
|
||||
```javascript
|
||||
var win = new BrowserWindow({ transparent: true, frame: false });
|
||||
|
@ -21,21 +23,19 @@ var win = new BrowserWindow({ transparent: true, frame: false });
|
|||
|
||||
### API의 한계
|
||||
|
||||
|
||||
|
||||
* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 제공할 예정이지만 현재로써는
|
||||
* 투명한 영역을 통과하여 클릭할 수 없습니다. 우리는 이 문제를 해결하기 위해 API를 제공할 예정이었지만 현재로써는
|
||||
[upstream 버그](https://code.google.com/p/chromium/issues/detail?id=387234)로 인해 중단된 상태입니다.
|
||||
* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 플랫폼에선 윈도우 크래시가 일어납니다.
|
||||
* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 방법이 없습니다.
|
||||
* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 작동하지 않습니다.
|
||||
* 투명한 창은 크기를 조절할 수 없습니다. `resizable` 속성을 `true`로 할 경우 몇몇 플랫폼에선 크래시가 일어납니다.
|
||||
* `blur` 필터는 웹 페이지에서만 적용됩니다. 윈도우 아래 컨텐츠에는 블러 효과를 적용할 방법이 없습니다. (예시: 유저의 시스템에 열린 다른 어플리케이션)
|
||||
* Windows에선 DWM(데스크톱 창 관리자)가 비활성화되어 있을 경우 투명한 창이 작동하지 않습니다.
|
||||
* Linux를 사용할 경우 [alpha channel doesn't work on some NVidia drivers](https://code.google.com/p/chromium/issues/detail?id=369209)
|
||||
upstream 버그가 있으므로 CLI 옵션에 `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다.
|
||||
upstream 버그가 있는 관계로 투명한 창 기능을 사용하려면 CLI 옵션에 `--enable-transparent-visuals --disable-gpu`을 추가해야 합니다.
|
||||
이 옵션은 GPU의 사용을 중단하고 윈도우를 생성하는데 ARGB를 사용할 수 있도록 해줍니다.
|
||||
* OS X(Mac)에선 네이티브 윈도우의 그림자가 투명한 창에선 보이지 않습니다.
|
||||
* OS X(Mac)에선 네이티브 창에서 보여지는 그림자가 투명한 창에선 보이지 않습니다.
|
||||
|
||||
## 드래그 가능 위치 지정
|
||||
|
||||
기본적으로 Frameless 윈도우는 드래그 할 수 없습니다.
|
||||
기본적으로 Frameless Window는 드래그 할 수 없습니다.
|
||||
어플리케이션의 CSS에서 특정 범위를 `-webkit-app-region: drag`로 지정하면 OS의 기본 타이틀 바 처럼 드래그 되도록 할 수 있습니다.
|
||||
그리고 `-webkit-app-region: no-drag`를 지정해서 드래그 불가능 영역을 만들 수도 있습니다. 현재 사각형 형태의 범위만 지원합니다.
|
||||
|
||||
|
@ -54,13 +54,13 @@ button {
|
|||
}
|
||||
```
|
||||
|
||||
또한 커스텀 타이틀바를 만들어 사용할 때 타이틀바 내부의 버튼도 드래그 불가능 영역으로 지정해야 합니다.
|
||||
따로 커스텀 타이틀 바를 만들어 사용할 때는 타이틀 바 내부의 모든 버튼을 드래그 불가능 영역으로 지정해야 합니다.
|
||||
|
||||
## 텍스트 선택
|
||||
|
||||
한가지, Frameless 윈도우에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다.
|
||||
Frameless Window에서 텍스트가 선택되는 드래그 동작은 혼란을 야기할 수 있습니다.
|
||||
예를 들어 타이틀 바를 드래그 할 때 타이틀 바의 텍스트를 실수로 선택할 수 있습니다.
|
||||
이를 방지하기 위해선 다음과 같이 드래그 영역의 텍스트 선택 동작을 비활성화해야 할 필요가 있습니다:
|
||||
이를 방지하기 위해 다음과 같이 드래그 영역의 텍스트 선택 기능을 비활성화해야 할 필요가 있습니다:
|
||||
|
||||
```css
|
||||
.titlebar {
|
||||
|
@ -71,5 +71,5 @@ button {
|
|||
|
||||
## 컨텍스트 메뉴
|
||||
|
||||
몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 그래서 이 영역에서 오른쪽 클릭을 할 경우 시스템 메뉴가 팝업 됩니다.
|
||||
그래서 컨텍스트 메뉴 지정이 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 드래그 영역 내에 만들어선 안됩니다.
|
||||
몇몇 플랫폼에선 드래그 가능 영역이 non-client 프레임으로 처리됩니다. 이러한 플랫폼에선 드래그 가능 영역에서 오른쪽 클릭 할 경우 시스템 메뉴가 팝업 됩니다.
|
||||
이러한 이유로 컨텍스트 메뉴 지정 시 모든 플랫폼에서 정상적으로 작동하게 하려면 커스텀 컨텍스트 메뉴를 드래그 영역 내에 만들어선 안됩니다.
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
# global-shortcut
|
||||
|
||||
`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 설정 등록/해제 하는 방법을 제공합니다.
|
||||
이 모듈을 사용하여 사용자가 다양한 단축키 작업을 할 수 있도록 단축키를 정의 할 수 있습니다.
|
||||
참고로 설정된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 때도 여전히 계속 작동합니다.
|
||||
`global-shortcut` 모듈은 운영체제의 전역 키보드 단축키를 등록/해제 하는 방법을 제공합니다.
|
||||
이 모듈을 사용하여 사용자가 다양한 작업을 편하게 할 수 있도록 단축키를 정의 할 수 있습니다.
|
||||
|
||||
**참고:** 등록된 단축키는 어플리케이션이 백그라운드로 작동(창이 포커스 되지 않음) 할 때도 계속해서 작동합니다.
|
||||
이 모듈은 `app` 모듈의 `ready` 이벤트 이전에 사용할 수 없습니다.
|
||||
|
||||
```javascript
|
||||
|
@ -30,25 +31,29 @@ app.on('will-quit', function() {
|
|||
});
|
||||
```
|
||||
|
||||
## globalShortcut.register(accelerator, callback)
|
||||
## Methods
|
||||
|
||||
`global-shortcut` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `globalShortcut.register(accelerator, callback)`
|
||||
|
||||
* `accelerator` [Accelerator](accelerator.md)
|
||||
* `callback` Function
|
||||
|
||||
`accelerator`로 표현된 전역 단축키를 등록합니다. 유저로부터 등록된 단축키가 눌렸을 경우 `callback` 함수가 호출됩니다.
|
||||
|
||||
## globalShortcut.isRegistered(accelerator)
|
||||
### `globalShortcut.isRegistered(accelerator)`
|
||||
|
||||
* `accelerator` [Accelerator](accelerator.md)
|
||||
|
||||
지정된 `accelerator` 단축키가 등록되었는지 여부를 확인합니다. 반환값은 boolean(true, false) 입니다.
|
||||
|
||||
## globalShortcut.unregister(accelerator)
|
||||
### `globalShortcut.unregister(accelerator)`
|
||||
|
||||
* `accelerator` [Accelerator](accelerator.md)
|
||||
|
||||
`키코드`에 해당하는 전역 단축키를 등록 해제합니다.
|
||||
`accelerator`에 해당하는 전역 단축키를 등록 해제합니다.
|
||||
|
||||
## globalShortcut.unregisterAll()
|
||||
### `globalShortcut.unregisterAll()`
|
||||
|
||||
모든 전역 단축키 등록을 해제합니다.
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
# ipc (main process)
|
||||
|
||||
랜더러 프로세스(웹 페이지)로 부터 동기 또는 비동기로 메시지를 받아 처리합니다.
|
||||
`ipc` (main process) 모듈은 메인 프로세스에서 사용할 때 랜더러 프로세스(웹 페이지)에서 전달된 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다.
|
||||
랜더러 프로세스에서 메시지를 전달하면 이 모듈을 통해 메시지를 받을 수 있습니다.
|
||||
|
||||
랜더러로부터 발신된 메시지들은 모두 이 모듈에서 `channel` 이라는 특정 이벤트 이름을 통해 수신할 수 있습니다.
|
||||
동기 메시지는 `event.returnValue`를 이용하여 반환값(답장)을 설정할 수 있습니다. 비동기 메시지라면 `event.sender.send(...)`를 사용하면 됩니다.
|
||||
## 메시지 전송
|
||||
|
||||
또한 메인 프로세스에서 랜더러 프로세스로 메시지를 보내는 것도 가능합니다.
|
||||
물론 메인 프로세스에서 랜더러 프로세스로 메시지를 보내는 것도 가능합니다.
|
||||
자세한 내용은 [WebContents.send](browser-window.md#webcontentssendchannel-args)를 참고하세요.
|
||||
|
||||
보내진 메시지들을 처리하는 예제입니다:
|
||||
- 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다.
|
||||
- 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다.
|
||||
- 메시지를 비동기로 응답할 땐 `event.sender.send(...)` 메서드를 사용할 수 있습니다.
|
||||
|
||||
랜더러 프로세스와 메인 프로세스간에 메시지를 전달하고 받는 예제입니다:
|
||||
|
||||
```javascript
|
||||
// 메인 프로세스에서 처리.
|
||||
// 메인 프로세스
|
||||
var ipc = require('ipc');
|
||||
ipc.on('asynchronous-message', function(event, arg) {
|
||||
console.log(arg); // prints "ping"
|
||||
|
@ -25,7 +29,7 @@ ipc.on('synchronous-message', function(event, arg) {
|
|||
```
|
||||
|
||||
```javascript
|
||||
// 랜더러 프로세스에서의 처리 (web page).
|
||||
// 랜더러 프로세스 (web page)
|
||||
var ipc = require('ipc');
|
||||
console.log(ipc.sendSync('synchronous-message', 'ping')); // prints "pong"
|
||||
|
||||
|
@ -35,12 +39,33 @@ ipc.on('asynchronous-reply', function(arg) {
|
|||
ipc.send('asynchronous-message', 'ping');
|
||||
```
|
||||
|
||||
## Class: Event
|
||||
## 메시지 리스닝
|
||||
|
||||
### Event.returnValue
|
||||
`ipc` 모듈은 다음과 같은 이벤트 메서드를 가지고 있습니다:
|
||||
|
||||
동기 메시지를 설정합니다.
|
||||
### `ipc.on(channel, callback)`
|
||||
|
||||
### Event.sender
|
||||
* `channel` String - 이벤트 이름
|
||||
* `callback` Function
|
||||
|
||||
메시지를 보내온 sender `WebContents` 객체입니다.
|
||||
이벤트가 발생하면 `callback`에 `event` 객체와 `arg` 메시지가 포함되어 호출됩니다.
|
||||
|
||||
## IPC Events
|
||||
|
||||
`callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다:
|
||||
|
||||
### `Event.returnValue`
|
||||
|
||||
이 메시지를 지정하면 동기 메시지를 전달합니다.
|
||||
|
||||
### `Event.sender`
|
||||
|
||||
메시지를 보낸 `WebContents` 객체를 반환합니다.
|
||||
|
||||
### `Event.sender.send(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
* `channel` String - The event name.
|
||||
* `arg` (optional)
|
||||
|
||||
랜더러 프로세스로 비동기 메시지를 전달합니다.
|
||||
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
|
||||
|
|
|
@ -1,25 +1,45 @@
|
|||
# ipc (renderer)
|
||||
|
||||
`ipc` 모듈은 메인 프로세스로 메시지를 동기 또는 비동기로 보내고 받을 수 있는 몇 가지 방법을 제공합니다.
|
||||
만약 랜더러 프로세스에서 메인 프로세스의 모듈을 직접적으로 사용하고 싶다면 [remote](remote.md) 모듈을 사용하는 것을 고려해보는 것이 좋습니다.
|
||||
`ipc` (renderer) 모듈은 메인 프로세스로 동기 또는 비동기 메시지를 보내고 받는 방법을 제공합니다.
|
||||
물론 메인 프로세스로부터 받은 메시지에 응답할 수도 있습니다.
|
||||
|
||||
[ipc (main process)](ipc-main-process.md)에서 예제를 볼 수 있습니다.
|
||||
**참고:** 만약 랜더러 프로세스에서 메인 프로세스의 모듈을 직접적 사용하고 싶다면 [remote](remote.md) 모듈을 사용하는 것을 고려해보는 것이 좋습니다.
|
||||
|
||||
## ipc.send(channel[, args...])
|
||||
[ipc (main process)](ipc-main-process.md)에서 예제를 확인 할 수 있습니다.
|
||||
|
||||
지정한 `channel`을 통해 `args..`를 비동기로 메시지를 보냅니다. 메인 프로세스는 `ipc` 모듈의 `channel` 이벤트를 통해 메시지를 받을 수 있습니다.
|
||||
## Methods
|
||||
|
||||
## ipc.sendSync(channel[, args...])
|
||||
`ipc` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
지정한 `channel`을 통해 `args..`를 동기로 메시지를 보냅니다. 그리고 메인 프로세스에서 보낸 결과를 반환합니다.
|
||||
메인 프로세스는 `ipc` 모듈의 `channel` 이벤트를 통해 메시지를 받을 수 있습니다. 그리고 `event.returnValue`를 통해 반환값을 설정할 수 있습니다.
|
||||
**참고:** 이 메소드들을 사용하여 `message`를 보낼 땐 반드시 메인 프로세스의
|
||||
[`ipc (main process)`](ipc-main-process.md) 모듈에서도 이벤트 리스너를 등록해 두어야 합니다.
|
||||
|
||||
역자 주: `channel`은 이벤트 이름입니다.
|
||||
### `ipc.send(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
**알림:** 보통 개발자들은 해당 API를 사용하려 하지 않습니다. 동기 ipc 작업은 랜더러 프로세스의 모든 작업을 중단시킵니다.
|
||||
* `channel` String - 이벤트 이름
|
||||
* `arg` (optional)
|
||||
|
||||
## ipc.sendToHost(channel[, args...])
|
||||
`channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다.
|
||||
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
|
||||
메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다.
|
||||
|
||||
`ipc.send`와 비슷하지만 메시지를 메인 프로세스 대신 호스트 페이지로 보냅니다.
|
||||
### `ipc.sendSync(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
이 메소드는 보통 `<webview>`와 호스트 페이지 간의 통신에 사용됩니다.
|
||||
* `channel` String - 이벤트 이름
|
||||
* `arg` (optional)
|
||||
|
||||
`channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다.
|
||||
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
|
||||
메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 할 수 있습니다.
|
||||
|
||||
메인 프로세스에선 `ipc` 모듈의 `channel` 이벤트를 통해 받은 `event.returnValue`로 회신 할 수 있습니다.
|
||||
|
||||
**참고:** 동기 메시징은 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 이 메서드를 사용하는 것을 권장하지 않습니다.
|
||||
|
||||
### `ipc.sendToHost(channel[, arg1][, arg2][, ...])`
|
||||
|
||||
* `channel` String - 이벤트 이름
|
||||
* `arg` (optional)
|
||||
|
||||
`ipc.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 `<webview>`로 보냅니다.
|
||||
옵션으로 `arg`에 한 개 또는 여러 개의 메시지를 포함할 수 있습니다. 모든 타입을 사용할 수 있습니다.
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
# menu-item
|
||||
# MenuItem
|
||||
|
||||
`menu-item` 모듈은 어플리케이션 또는 컨텐츠 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다.
|
||||
|
||||
[`menu`](menu.md)에서 예제를 확인할 수 있습니다.
|
||||
|
||||
## Class: MenuItem
|
||||
|
||||
`MenuItem` 인스턴스 객체에서 사용할 수 있는 메서드입니다:
|
||||
|
||||
### new MenuItem(options)
|
||||
|
||||
* `options` Object
|
||||
* `click` Function - 메뉴 아이템이 클릭될 때 호출되는 콜백함수
|
||||
* `selector` String - First Responder가 클릭될 때 호출 되는 선택자 (OS X 전용)
|
||||
* `click` Function - 메뉴 아이템이 클릭될 때 `click(menuItem, browserWindow)` 형태로 호출 되는 콜백 함수
|
||||
* `role` String - 메뉴 아이템의 액션을 정의합니다. 이 속성을 지정하면 `click` 속성이 무시됩니다.
|
||||
* `type` String - `MenuItem`의 타입 `normal`, `separator`, `submenu`, `checkbox` 또는 `radio` 사용가능
|
||||
* `label` String
|
||||
* `sublabel` String
|
||||
|
@ -18,3 +24,29 @@
|
|||
* `submenu` Menu - 보조메뉴를 설정합니다. `type`이 `submenu`일 경우 반드시 설정해야합니다. 일반 메뉴 아이템일 경우 생략할 수 있습니다.
|
||||
* `id` String - 현재 메뉴 아이템에 대해 유일키를 지정합니다. 이 키는 이후 `position` 옵션에서 사용할 수 있습니다.
|
||||
* `position` String - 미리 지정한 `id`를 이용하여 메뉴 아이템의 위치를 세밀하게 조정합니다.
|
||||
|
||||
When creating menu items, it is recommended to specify `role` instead of
|
||||
manually implementing the behavior if there is matching action, so menu can have
|
||||
best native experience.
|
||||
|
||||
The `role` property can have following values:
|
||||
|
||||
* `undo`
|
||||
* `redo`
|
||||
* `cut`
|
||||
* `copy`
|
||||
* `paste`
|
||||
* `selectall`
|
||||
* `minimize` - Minimize current window
|
||||
* `close` - Close current window
|
||||
|
||||
On OS X `role` can also have following additional values:
|
||||
|
||||
* `about` - Map to the `orderFrontStandardAboutPanel` action
|
||||
* `hide` - Map to the `hide` action
|
||||
* `hideothers` - Map to the `hideOtherApplications` action
|
||||
* `unhide` - Map to the `unhideAllApplications` action
|
||||
* `front` - Map to the `arrangeInFront` action
|
||||
* `window` - The submenu is a "Window" menu
|
||||
* `help` - The submenu is a "Help" menu
|
||||
* `services` - The submenu is a "Services" menu
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# menu
|
||||
# Menu
|
||||
|
||||
`Menu` 클래스는 어플리케이션 메뉴와 컨텍스트 메뉴를 만들 때 사용됩니다.
|
||||
메뉴는 여러 개의 메뉴 아이템으로 구성되고 서브 메뉴를 가질 수도 있습니다.
|
||||
`menu` 클래스는 어플리케이션 메뉴와 [컨텍스트 메뉴](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/PopupGuide/ContextMenus)를 만들 때 사용됩니다.
|
||||
이 모듈은 메인 프로세스용 모듈이지만 `remote` 모듈을 통해 랜더러 프로세스에서도 사용할 수 있습니다.
|
||||
|
||||
각 메뉴는 여러 개의 [메뉴 아이템](menu-item.md)으로 구성되고 서브 메뉴를 가질 수도 있습니다.
|
||||
|
||||
다음 예제는 웹 페이지 내에서 [remote](remote.md) 모듈을 활용하여 동적으로 메뉴를 생성하는 예제입니다.
|
||||
|
||||
이 예제에서 만들어진 메뉴는 유저가 페이지에서 오른쪽 클릭을 할 때 마우스 위치에 팝업 형태로 표시됩니다:
|
||||
그리고 유저가 페이지에서 오른쪽 클릭을 할 때마다 마우스 위치에 팝업 형태로 메뉴를 표시합니다:
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
|
@ -26,69 +27,22 @@ window.addEventListener('contextmenu', function (e) {
|
|||
</script>
|
||||
```
|
||||
|
||||
다음 예제는 template API를 활용하여 어플리케이션 메뉴를 만드는 간단한 예제입니다:
|
||||
또 하나의 예를 들자면 다음 예제는 랜더러 프로세스에서 template API를 사용하여 어플리케이션 메뉴를 만듭니다:
|
||||
|
||||
**Windows 와 Linux 유저 주의:** 각 메뉴 아이템의 `selector` 멤버는 Mac 운영체제 전용입니다. [Accelerator 옵션](accelerator.md)
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
<script>
|
||||
var remote = require('remote');
|
||||
var Menu = remote.require('menu');
|
||||
```javascript
|
||||
var template = [
|
||||
{
|
||||
label: 'Electron',
|
||||
submenu: [
|
||||
{
|
||||
label: 'About Electron',
|
||||
selector: 'orderFrontStandardAboutPanel:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide Electron',
|
||||
accelerator: 'CmdOrCtrl+H',
|
||||
selector: 'hide:'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'CmdOrCtrl+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
selector: 'unhideAllApplications:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'CmdOrCtrl+Q',
|
||||
selector: 'terminate:'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Edit',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'CmdOrCtrl+Z',
|
||||
selector: 'undo:'
|
||||
role: 'undo'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+CmdOrCtrl+Z',
|
||||
selector: 'redo:'
|
||||
role: 'redo'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
|
@ -96,23 +50,23 @@ var template = [
|
|||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'CmdOrCtrl+X',
|
||||
selector: 'cut:'
|
||||
role: 'cut'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'CmdOrCtrl+C',
|
||||
selector: 'copy:'
|
||||
role: 'copy'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'CmdOrCtrl+V',
|
||||
selector: 'paste:'
|
||||
role: 'paste'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'CmdOrCtrl+A',
|
||||
selector: 'selectAll:'
|
||||
}
|
||||
role: 'selectall'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -121,71 +75,153 @@ var template = [
|
|||
{
|
||||
label: 'Reload',
|
||||
accelerator: 'CmdOrCtrl+R',
|
||||
click: function() { remote.getCurrentWindow().reload(); }
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.reload();
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle DevTools',
|
||||
accelerator: 'Alt+CmdOrCtrl+I',
|
||||
click: function() { remote.getCurrentWindow().toggleDevTools(); }
|
||||
label: 'Toggle Full Screen',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Ctrl+Command+F';
|
||||
else
|
||||
return 'F11';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'Toggle Developer Tools',
|
||||
accelerator: (function() {
|
||||
if (process.platform == 'darwin')
|
||||
return 'Alt+Command+I';
|
||||
else
|
||||
return 'Ctrl+Shift+I';
|
||||
})(),
|
||||
click: function(item, focusedWindow) {
|
||||
if (focusedWindow)
|
||||
focusedWindow.toggleDevTools();
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Window',
|
||||
role: 'window',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'CmdOrCtrl+M',
|
||||
selector: 'performMiniaturize:'
|
||||
role: 'minimize'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'CmdOrCtrl+W',
|
||||
selector: 'performClose:'
|
||||
role: 'close'
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Learn More',
|
||||
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
if (process.platform == 'darwin') {
|
||||
var name = require('app').getName();
|
||||
template.unshift({
|
||||
label: name,
|
||||
submenu: [
|
||||
{
|
||||
label: 'About ' + name,
|
||||
role: 'about'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
}
|
||||
]
|
||||
label: 'Services',
|
||||
role: 'services',
|
||||
submenu: []
|
||||
},
|
||||
{
|
||||
label: 'Help',
|
||||
submenu: []
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Hide ' + name,
|
||||
accelerator: 'Command+H',
|
||||
role: 'hide'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
role: 'hideothers:'
|
||||
},
|
||||
{
|
||||
label: 'Show All',
|
||||
role: 'unhide:'
|
||||
},
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
click: function() { app.quit(); }
|
||||
},
|
||||
]
|
||||
});
|
||||
// Window menu.
|
||||
template[3].submenu.push(
|
||||
{
|
||||
type: 'separator'
|
||||
},
|
||||
{
|
||||
label: 'Bring All to Front',
|
||||
role: 'front'
|
||||
}
|
||||
);
|
||||
}
|
||||
];
|
||||
|
||||
menu = Menu.buildFromTemplate(template);
|
||||
|
||||
Menu.setApplicationMenu(menu);
|
||||
</script>
|
||||
```
|
||||
|
||||
## Class: Menu
|
||||
|
||||
### new Menu()
|
||||
### `new Menu()`
|
||||
|
||||
새로운 메뉴를 생성합니다.
|
||||
|
||||
### Class Method: Menu.setApplicationMenu(menu)
|
||||
### Methods
|
||||
|
||||
`menu` 클래스는 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `Menu.setApplicationMenu(menu)`
|
||||
|
||||
* `menu` Menu
|
||||
|
||||
지정한 `menu`를 이용하여 어플리케이션 메뉴를 만듭니다. OS X에선 상단바에 표시되며 Windows와 Linux에선 각 창의 상단에 표시됩니다.
|
||||
지정한 `menu`를 어플리케이션 메뉴로 만듭니다. OS X에선 상단바에 표시되며 Windows와 Linux에선 각 창의 상단에 표시됩니다.
|
||||
|
||||
### Class Method: Menu.sendActionToFirstResponder(action)
|
||||
### `Menu.sendActionToFirstResponder(action)` _OS X_
|
||||
|
||||
* `action` String
|
||||
|
||||
`action`을 어플리케이션의 first responder에 전달합니다.
|
||||
이 함수는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다.
|
||||
이 메서드는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다.
|
||||
|
||||
**알림:** 이 함수는 OS X에서만 사용할 수 있습니다.
|
||||
**참고:** 이 메서드는 OS X에서만 사용할 수 있습니다.
|
||||
|
||||
### Class Method: Menu.buildFromTemplate(template)
|
||||
### `Menu.buildFromTemplate(template)`
|
||||
|
||||
* `template` Array
|
||||
|
||||
|
@ -193,57 +229,58 @@ Menu.setApplicationMenu(menu);
|
|||
|
||||
또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 프로퍼티로 변환됩니다.
|
||||
|
||||
### Menu.popup(browserWindow, [x, y])
|
||||
### `Menu.popup(browserWindow[, x, y])`
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `x` Number
|
||||
* `y` Number
|
||||
* `x` Number (optional)
|
||||
* `y` Number (만약 `x`를 지정했을 경우 `y`도 필수로 지정해야 합니다)
|
||||
|
||||
메뉴를 `browserWindow` 안에서 팝업으로 표시합니다.
|
||||
옵션으로 메뉴를 표시할 `(x,y)` 좌표를 임의로 지정할 수 있습니다. 따로 지정하지 않은 경우 마우스 커서 위치에 표시됩니다.
|
||||
메뉴를 `browserWindow` 내부 팝업으로 표시합니다.
|
||||
옵션으로 메뉴를 표시할 `(x,y)` 좌표를 지정할 수 있습니다.
|
||||
따로 좌표를 지정하지 않은 경우 마우스 커서 위치에 표시됩니다.
|
||||
|
||||
### Menu.append(menuItem)
|
||||
### `Menu.append(menuItem)`
|
||||
|
||||
* `menuItem` MenuItem
|
||||
|
||||
메뉴의 리스트 끝에 `menuItem`을 삽입합니다.
|
||||
|
||||
### Menu.insert(pos, menuItem)
|
||||
### `Menu.insert(pos, menuItem)`
|
||||
|
||||
* `pos` Integer
|
||||
* `menuItem` MenuItem
|
||||
|
||||
`pos` 위치에 `menuItem`을 삽입합니다.
|
||||
|
||||
### Menu.items
|
||||
### `Menu.items()`
|
||||
|
||||
메뉴가 가지고 있는 메뉴 아이템들의 배열입니다.
|
||||
|
||||
## OS X 어플리케이션 메뉴에 대해 알아 둬야 할 것들
|
||||
|
||||
OS X에선 Windows, Linux와 달리 완전히 다른 어플리케이션 메뉴 스타일을 가지고 있습니다.
|
||||
어플리케이션을 네이티브처럼 작동할 수 있도록 하기 위해선 다음의 몇 가지 유의 사항을 숙지해야 합니다.
|
||||
그래서 어플리케이션을 네이티브처럼 작동할 수 있도록 하기 위해 다음 몇 가지 유의 사항을 숙지해야 합니다.
|
||||
|
||||
### 기본 메뉴
|
||||
|
||||
OS X엔 `Services`나 `Windows`와 같은 많은 시스템 지정 기본 메뉴가 있습니다.
|
||||
기본 메뉴를 만들려면 다음 중 하나를 메뉴의 라벨로 지정하기만 하면 됩니다.
|
||||
기본 메뉴를 만들려면 반드시 다음 리스트 중 한 가지를 선택하여 메뉴의 `role`로 지정해야 합니다.
|
||||
그러면 Electron이 자동으로 인식하여 해당 메뉴를 기본 메뉴로 만듭니다:
|
||||
|
||||
* `Window`
|
||||
* `Help`
|
||||
* `Services`
|
||||
* `window`
|
||||
* `help`
|
||||
* `services`
|
||||
|
||||
### 기본 메뉴 아이템 동작
|
||||
### 메뉴 아이템 기본 동작
|
||||
|
||||
OS X는 몇몇의 메뉴 아이템에 대해 `About xxx`, `Hide xxx`, `Hide Others`와 같은 기본 동작을 제공하고 있습니다. (`selector`라고 불립니다)
|
||||
메뉴 아이템의 기본 동작을 지정하려면 메뉴 아이템의 `selector` 속성을 사용하면 됩니다.
|
||||
OS X는 몇가지 메뉴 아이템에 대해 `About xxx`, `Hide xxx`, `Hide Others`와 같은 기본 동작을 제공하고 있습니다.
|
||||
메뉴 아이템의 기본 동작을 지정하려면 반드시 메뉴 아이템의 `role` 속성을 지정해야 합니다.
|
||||
|
||||
### 메인 메뉴의 이름
|
||||
|
||||
OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번째 라벨은 언제나 어플리케이션의 이름이 됩니다.
|
||||
어플리케이션 이름을 변경하려면 앱 번들내의 `Info.plist` 파일을 수정해야합니다.
|
||||
자세한 내용은 [About Information Property List Files](https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html)을 참고하세요.
|
||||
자세한 내용은 [About Information Property List Files][AboutInformationPropertyListFiles] 문서를 참고하세요.
|
||||
|
||||
## 메뉴 아이템 위치
|
||||
|
||||
|
@ -257,7 +294,7 @@ OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번
|
|||
* `endof` - 이 아이템을 id의 논리 그룹에 맞춰서 각 그룹의 항목 뒤에 삽입합니다. (그룹은 분리자 아이템에 의해 만들어집니다)
|
||||
만약 참조된 아이템의 분리자 그룹이 존재하지 않을 경우 지정된 id로 새로운 분리자 그룹을 만든 후 해당 그룹의 뒤에 삽입됩니다.
|
||||
|
||||
위치를 지정한 아이템의 뒤에 위치가 지정되지 않은 아이템이 있을 경우 해당 아이템의 위치가 지정되기 전까지 이전에 위치가 지정된 아이템의 위치 지정을 따릅니다.
|
||||
위치를 지정한 아이템의 뒤에 위치가 지정되지 않은 아이템이 있을 경우 각 아이템의 위치가 지정되기 전까지 모든 아이템이 위치가 지정된 아이템의 뒤에 삽입됩니다.
|
||||
이에 따라 위치를 이동하고 싶은 특정 그룹의 아이템들이 있을 경우 해당 그룹의 맨 첫번째 메뉴 아이템의 위치만을 지정하면 됩니다.
|
||||
|
||||
### 예제
|
||||
|
@ -309,3 +346,5 @@ OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번
|
|||
- 2
|
||||
- 3
|
||||
```
|
||||
|
||||
[AboutInformationPropertyListFiles]: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
# NativeImage
|
||||
|
||||
Electron은 파일 경로나 `NativeImage` 인스턴스를 전달하여 사용하는 이미지 API를 가지고 있습니다. `null`을 전달할 경우 빈 이미지가 사용됩니다.
|
||||
Electron은 파일 경로 또는 `NativeImage` 인스턴스를 통해 이미지를 사용할 수 있는 API를 가지고 있습니다.
|
||||
`null`을 전달할 경우 빈 이미지가 생성됩니다.
|
||||
|
||||
예를 들어 트레이 메뉴를 만들거나 윈도우의 아이콘을 설정할 때 다음과 같이 `문자열`인 파일 경로를 전달할 수 있습니다:
|
||||
예를 들어 트레이 메뉴를 만들거나 윈도우의 아이콘을 설정할 때 다음과 같이 파일 경로를 전달하여 이미지를 사용할 수 있습니다:
|
||||
|
||||
```javascript
|
||||
var appIcon = new Tray('/Users/somebody/images/icon.png');
|
||||
var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'});
|
||||
```
|
||||
|
||||
또는 클립보드로부터 이미지를 읽어올 수 있습니다:
|
||||
이 예제는 클립보드로부터 가져온 `NativeImage`로 트레이 메뉴를 생성합니다:
|
||||
|
||||
```javascript
|
||||
var clipboard = require('clipboard');
|
||||
|
@ -19,7 +20,8 @@ var appIcon = new Tray(image);
|
|||
|
||||
## 지원하는 포맷
|
||||
|
||||
현재 `PNG` 와 `JPEG` 포맷을 지원하고 있습니다. 손실 없는 이미지 압축과 투명도 지원을 위해 `PNG` 사용을 권장합니다.
|
||||
현재 `PNG` 와 `JPEG` 이미지 포맷을 지원하고 있습니다.
|
||||
손실 없는 이미지 압축과 투명도 지원을 위해 `PNG` 사용을 권장합니다.
|
||||
|
||||
그리고 Windows에서는 `ICO` 포맷도 사용할 수 있습니다.
|
||||
|
||||
|
@ -27,9 +29,9 @@ var appIcon = new Tray(image);
|
|||
|
||||
플랫폼이 high-DPI를 지원하는 경우 `@2x`와 같이 이미지의 파일명 뒤에 접미사를 추가하여 고해상도 이미지로 지정할 수 있습니다.
|
||||
|
||||
예를 들어 `icon.png` 라는 기본 해상도의 이미지를 기준으로 크기를 두 배로 늘린 이미지를 `icon@2x.png`와 같이 이름을 지정하면 고해상도 이미지로 처리됩니다.
|
||||
예를 들어 `icon.png` 라는 기본 해상도의 이미지를 기준으로 크기를 두 배로 늘린 이미지를 `icon@2x.png` 처럼 지정하면 고해상도 이미지로 처리됩니다.
|
||||
|
||||
서로 다른 해상도(DPI)의 이미지를 지원하고 싶다면 다중 해상도의 이미지를 접미사를 붙여 한 폴더에 넣으면 됩니다. 이 이미지를 사용(로드)할 땐 접미사를 붙이지 않습니다:
|
||||
서로 다른 해상도(DPI)의 이미지를 같이 지원하고 싶다면 다중 해상도의 이미지를 접미사를 붙여 한 폴더에 같이 넣으면 됩니다. 이 이미지를 사용(로드)할 땐 따로 접미사를 붙이지 않습니다:
|
||||
|
||||
```text
|
||||
images/
|
||||
|
@ -64,69 +66,79 @@ var appIcon = new Tray('/Users/somebody/images/icon.png');
|
|||
|
||||
가장 일반적으로 템플릿 이미지는 밝고 어두운 테마 색상으로 변경할 수 있는 메뉴 바 아이콘 등에 사용되고 있습니다.
|
||||
|
||||
템플릿 이미지는 Mac 운영체제만 지원합니다.
|
||||
**참고:** 템플릿 이미지는 OS X 운영체제만 지원합니다.
|
||||
|
||||
템플릿 이미지를 지정하려면 다음 예제와 같이 파일명에 `Template` 문자열을 추가해야 합니다:
|
||||
|
||||
* `xxxTemplate.png`
|
||||
* `xxxTemplate@2x.png`
|
||||
|
||||
## nativeImage.createEmpty()
|
||||
## Methods
|
||||
|
||||
`NativeImage` 클래스는 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `NativeImage.createEmpty()`
|
||||
|
||||
빈 `NativeImage` 인스턴스를 만듭니다.
|
||||
|
||||
## nativeImage.createFromPath(path)
|
||||
### `NativeImage.createFromPath(path)`
|
||||
|
||||
* `path` String
|
||||
|
||||
`path`로부터 이미지를 로드하여 새로운 `NativeImage` 인스턴스를 만듭니다.
|
||||
|
||||
## nativeImage.createFromBuffer(buffer[, scaleFactor])
|
||||
### `NativeImage.createFromBuffer(buffer[, scaleFactor])`
|
||||
|
||||
* `buffer` [Buffer][buffer]
|
||||
* `scaleFactor` Double
|
||||
* `scaleFactor` Double (optional)
|
||||
|
||||
`buffer`로부터 이미지를 로드하여 새로운 `NativeImage` 인스턴스를 만듭니다. `scaleFactor`는 1.0이 기본입니다.
|
||||
|
||||
## nativeImage.createFromDataUrl(dataUrl)
|
||||
### `NativeImage.createFromDataUrl(dataUrl)`
|
||||
|
||||
* `dataUrl` String
|
||||
|
||||
`dataUrl`로부터 이미지를 로드하여 새로운 `NativeImage` 인스턴스를 만듭니다.
|
||||
|
||||
## Class: NativeImage
|
||||
## Instance Methods
|
||||
|
||||
이미지를 표현한 클래스입니다.
|
||||
`nativeImage` 인스턴스 객체에서 사용할 수 있는 메서드 입니다:
|
||||
|
||||
### NativeImage.toPng()
|
||||
```javascript
|
||||
var NativeImage = require('native-image');
|
||||
|
||||
var image = NativeImage.createFromPath('/Users/somebody/images/icon.png');
|
||||
```
|
||||
|
||||
### `image.toPng()`
|
||||
|
||||
`PNG` 이미지를 인코딩한 데이터를 [Buffer][buffer]로 반환합니다.
|
||||
|
||||
### NativeImage.toJpeg(quality)
|
||||
### `image.toJpeg(quality)`
|
||||
|
||||
* `quality` Integer (0 - 100 사이의 값)
|
||||
* `quality` Integer 0 - 100 사이의 값 (**required**)
|
||||
|
||||
`JPEG` 이미지를 인코딩한 데이터를 [Buffer][buffer]로 반환합니다.
|
||||
|
||||
### NativeImage.toDataUrl()
|
||||
### `image.toDataUrl()`
|
||||
|
||||
이미지의 data URL을 반환합니다.
|
||||
이미지를 data URL로 반환합니다.
|
||||
|
||||
### NativeImage.isEmpty()
|
||||
### `image.isEmpty()`
|
||||
|
||||
이미지가 비었는지를 체크합니다.
|
||||
이미지가 비었는지 확인합니다.
|
||||
|
||||
### NativeImage.getSize()
|
||||
### `image.getSize()`
|
||||
|
||||
이미지의 사이즈를 반환합니다.
|
||||
|
||||
### NativeImage.setTemplateImage(option)
|
||||
### `image.setTemplateImage(option)`
|
||||
|
||||
* `option` Boolean
|
||||
|
||||
해당 이미지를 템플릿 이미지로 설정합니다.
|
||||
|
||||
### NativeImage.isTemplateImage()
|
||||
### `image.isTemplateImage()`
|
||||
|
||||
이미지가 템플릿 이미지인지 확인합니다.
|
||||
|
||||
|
|
|
@ -16,18 +16,22 @@ app.on('ready', function() {
|
|||
});
|
||||
```
|
||||
|
||||
## Event: suspend
|
||||
## Events
|
||||
|
||||
`power-monitor` 모듈은 다음과 같은 이벤트를 가지고 있습니다:
|
||||
|
||||
## Event: `suspend`
|
||||
|
||||
시스템이 절전모드로 진입할 때 발생하는 이벤트입니다.
|
||||
|
||||
## Event: resume
|
||||
## Event: `resume`
|
||||
|
||||
시스템의 절전모드가 해제될 때 발생하는 이벤트입니다.
|
||||
|
||||
## Event: on-ac
|
||||
## Event: `on-ac`
|
||||
|
||||
시스템이 AC 어뎁터 충전기를 사용하기 시작할 때 발생하는 이벤트입니다.
|
||||
|
||||
## Event: on-battery
|
||||
## Event: `on-battery`
|
||||
|
||||
시스템이 배터리를 사용하기 시작할 때 발생하는 이벤트입니다.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# power-save-blocker
|
||||
# powerSaveBlocker
|
||||
|
||||
`power-save-blocker` 모듈은 시스템이 저전력 모드(슬립)로 진입하는 것을 막고 앱 및 화면이 항상 활성화되어 있는 상태를 만들 수 있도록 해줍니다.
|
||||
`power-save-blocker` 모듈은 시스템이 저전력(슬립) 모드로 진입하는 것을 막고 앱 시스템과 화면이 항상 활성화 상태를 유지할 수 있도록 하는 몇가지 유틸리티를 제공하는 모듈입니다.
|
||||
|
||||
예제:
|
||||
|
||||
|
@ -13,31 +13,34 @@ console.log(powerSaveBlocker.isStarted(id));
|
|||
powerSaveBlocker.stop(id);
|
||||
```
|
||||
|
||||
## powerSaveBlocker.start(type)
|
||||
## Methods
|
||||
|
||||
`powerSaveBlocker` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `powerSaveBlocker.start(type)`
|
||||
|
||||
* `type` String - Power save blocker 종류
|
||||
* `prevent-app-suspension` - 저전력 모드 등으로 인한 어플리케이션 작동 중단을 방지합니다.
|
||||
시스템을 항시 활성화 상태로 만듭니다, 하지만 화면은 자동으로 꺼질 수 있습니다. 사용 예시: 파일 다운로드, 음악 재생 등.
|
||||
시스템을 항시 활성화 상태로 만듭니다. 하지만 화면은 자동으로 꺼질 수 있습니다. 사용 예시: 파일 다운로드, 음악 재생 등.
|
||||
* `prevent-display-sleep`- 슬립 모드 등으로 인한 어플리케이션의 작동 중단을 방지합니다.
|
||||
시스템을 항시 활성화 상태로 만들고 슬립 모드(화면 꺼짐)를 방지합니다. 사용 예시: 비디오 재생 등.
|
||||
|
||||
Power save blocker를 시작하고 시스템이 저전력 모드(슬립)로 진입하는 것을 막습니다. 정수로 된 식별 ID를 반환합니다.
|
||||
시스템이 저전력 모드(슬립)로 진입하는 것을 막기 시작합니다. 정수로 된 식별 ID를 반환합니다.
|
||||
|
||||
**알림:**
|
||||
`prevent-display-sleep` 모드는 `prevent-app-suspension` 보다 우선순위가 높습니다.
|
||||
가장 높은 우선순위의 모드만 작동합니다. 다시 말해 `prevent-display-sleep` 모드는 언제나 `prevent-app-suspension` 모드의 효과를 덮어씌웁니다.
|
||||
**참고:** `prevent-display-sleep` 모드는 `prevent-app-suspension` 보다 우선 순위가 높습니다.
|
||||
두 모드 중 가장 높은 우선 순위의 모드만 작동합니다. 다시 말해 `prevent-display-sleep` 모드는 언제나 `prevent-app-suspension` 모드의 효과를 덮어씌웁니다.
|
||||
|
||||
예를 들어 A-요청이 `prevent-app-suspension` 모드를 사용하고 B-요청이 `prevent-display-sleep`를 사용하는 API 호출이 있었다 치면
|
||||
`prevent-display-sleep` 모드를 사용하는 B의 작동이 중단(stop)되기 전까지 작동하다 B가 중단되면 `prevent-app-suspension` 모드를 사용하는 A가 작동하기 시작합니다.
|
||||
|
||||
## powerSaveBlocker.stop(id)
|
||||
### `powerSaveBlocker.stop(id)`
|
||||
|
||||
* `id` Integer - `powerSaveBlocker.start`로 부터 반환되는 power save blocker 식별 ID.
|
||||
|
||||
설정한 power save blocker를 중지합니다.
|
||||
|
||||
## powerSaveBlocker.isStarted(id)
|
||||
### `powerSaveBlocker.isStarted(id)`
|
||||
|
||||
* `id` Integer - `powerSaveBlocker.start`로 부터 반환되는 power save blocker 식별 ID.
|
||||
|
||||
해당하는 id의 `powerSaveBlocker`가 실행중인지 확인합니다.
|
||||
지정한 id의 `powerSaveBlocker`가 실행 중인지 확인합니다.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# 프로세스 객체
|
||||
# process
|
||||
|
||||
Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점이 있습니다:
|
||||
|
||||
|
@ -7,6 +7,16 @@ Electron의 `process` 객체는 기존의 node와는 달리 약간의 차이점
|
|||
* `process.versions['chrome']` String - Chromium의 버전.
|
||||
* `process.resourcesPath` String - JavaScript 소스코드의 경로.
|
||||
|
||||
## process.hang
|
||||
## Methods
|
||||
|
||||
`process` 객체는 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `process.hang()`
|
||||
|
||||
현재 프로세스의 주 스레드를 중단시킵니다.
|
||||
|
||||
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
|
||||
|
||||
* `maxDescriptors` Integer
|
||||
|
||||
`maxDescriptors`에 file descriptor 소프트 리미트를 설정하거나 OS 하드 리미트를 설정합니다. 값은 현재 프로세스에 대해 낮은 값이어야 합니다.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
`protocol` 모듈은 이미 있는 프로토콜의 동작을 가로채거나 새로운 프로토콜을 만들 수 있는 기능을 제공합니다.
|
||||
|
||||
다음 예제는 `file://` 프로토콜과 같은 일을 하는 커스텀 프로토콜을 설정합니다:
|
||||
다음 예제는 `file://` 프로토콜과 비슷한 일을 하는 커스텀 프로토콜을 설정합니다:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
|
@ -20,24 +20,28 @@ app.on('ready', function() {
|
|||
});
|
||||
```
|
||||
|
||||
**알림:** 이 모듈은 `ready` 이벤트가 호출된 이후에만 사용할 수 있습니다.
|
||||
**참고:** 이 모듈은 `app` 모듈의 `ready` 이벤트가 발생한 이후에만 사용할 수 있습니다.
|
||||
|
||||
## protocol.registerStandardSchemes(schemes)
|
||||
## Methods
|
||||
|
||||
`protocol` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `protocol.registerStandardSchemes(schemes)`
|
||||
|
||||
* `schemes` Array - 표준 스킴으로 등록할 커스텀 스킴 리스트
|
||||
|
||||
표준 스킴의 형식은 RFC 3986 [일반 URI 구문](https://tools.ietf.org/html/rfc3986#section-3) 표준을 따릅니다.
|
||||
표준 `scheme`의 형식은 RFC 3986 [일반 URI 구문](https://tools.ietf.org/html/rfc3986#section-3) 표준을 따릅니다.
|
||||
이 형식은 `file:`과 `filesystem:`을 포함합니다.
|
||||
|
||||
## protocol.registerFileProtocol(scheme, handler[, completion])
|
||||
### `protocol.registerFileProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme`에 파일을 응답으로 보내는 프로토콜을 등록합니다.
|
||||
`handler`는 `request`가 `scheme`와 함께 생성될 때 `handler(request, callback)` 형식으로 호출됩니다.
|
||||
`completion`은 `scheme`가 성공적으로 등록되었을 때 `completion(null)` 형식으로 호출되고
|
||||
`handler`는 `scheme`와 함께 `request`가 생성될 때 `handler(request, callback)` 형식으로 호출됩니다.
|
||||
`completion` 콜백은 `scheme`가 성공적으로 등록되었을 때 `completion(null)` 형식으로 호출되고
|
||||
등록에 실패했을 땐 `completion(error)` 형식으로 에러 내용을 담아 호출됩니다.
|
||||
|
||||
`request`를 처리할 때 반드시 파일 경로 또는 `path` 속성을 포함하는 객체를 인자에 포함하여 `callback`을 호출해야 합니다.
|
||||
|
@ -45,16 +49,16 @@ app.on('ready', function() {
|
|||
|
||||
만약 `callback`이 아무 인자도 없이 호출되거나 숫자나 `error` 프로퍼티를 가진 객체가 인자로 전달될 경우
|
||||
`request`는 지정한 `error` 코드(숫자)를 출력합니다.
|
||||
사용할 수 있는 에러 코드는 다음 링크에서 확인할 수 있습니다: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h
|
||||
사용할 수 있는 에러 코드는 [네트워크 에러 목록](https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h)에서 확인할 수 있습니다.
|
||||
|
||||
기본적으로 스킴은 `http:`와 같이 처리됩니다. `file:`과 같이 "일반적인 URI 문법"과는 다르게 인식되는 프로토콜은
|
||||
기본적으로 `scheme`은 `http:`와 같이 처리됩니다. `file:`과 같이 "일반적인 URI 문법"과는 다르게 인식되는 프로토콜은
|
||||
`protocol.registerStandardSchemes`을 사용하여 표준 스킴으로 처리되도록 할 수 있습니다.
|
||||
|
||||
## protocol.registerBufferProtocol(scheme, handler[, completion])
|
||||
### `protocol.registerBufferProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme`에 `Buffer`를 응답으로 보내는 프로토콜을 등록합니다.
|
||||
반드시 `Buffer` 또는 `data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 `callback`을 호출해야 합니다.
|
||||
|
@ -70,76 +74,75 @@ protocol.registerBufferProtocol('atom', function(request, callback) {
|
|||
});
|
||||
```
|
||||
|
||||
## protocol.registerStringProtocol(scheme, handler[, completion])
|
||||
### `protocol.registerStringProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme`에 `문자열`를 응답으로 보내는 프로토콜을 등록합니다.
|
||||
`scheme`에 `문자열`을 응답으로 보내는 프로토콜을 등록합니다.
|
||||
반드시 `문자열` 또는 `data`, `mimeType`, `chart` 속성을 포함한 객체 중 하나를 인자에 포함하여 `callback`을 호출해야 합니다.
|
||||
|
||||
## protocol.registerHttpProtocol(scheme, handler[, completion])
|
||||
### `protocol.registerHttpProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme`에 HTTP 요청을 응답으로 보내는 프로토콜을 등록합니다.
|
||||
반드시 `url`, `method`, `referer`, `session` 속성을 포함하는 객체를 인자에 포함하여 `callback`을 호출해야 합니다.
|
||||
|
||||
기본적으로 HTTP 요청은 현재 세션을 재사용합니다. 만약 서로 다른 세션에 요청을 보내고 싶으면 `session`을 `null`로 지정해야 합니다.
|
||||
|
||||
## protocol.unregisterProtocol(scheme[, completion])
|
||||
### `protocol.unregisterProtocol(scheme[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme`의 커스텀 프로토콜 등록을 해제합니다.
|
||||
|
||||
## protocol.isProtocolHandled(scheme, callback)
|
||||
### `protocol.isProtocolHandled(scheme, callback)`
|
||||
|
||||
* `scheme` String
|
||||
* `callback` Function
|
||||
|
||||
`scheme`에 동작(handler)이 등록되어 있는지 여부를 확인합니다. `callback`으로 결과(boolean)가 반환됩니다.
|
||||
|
||||
## protocol.interceptFileProtocol(scheme, handler[, completion])
|
||||
### `protocol.interceptFileProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme` 프로토콜을 가로채고 `handler`를 파일 전송에 대한 새로운 동작으로 사용합니다.
|
||||
|
||||
## protocol.interceptStringProtocol(scheme, handler[, completion])
|
||||
### `protocol.interceptStringProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme` 프로토콜을 가로채고 `handler`를 문자열 전송에 대한 새로운 동작으로 사용합니다.
|
||||
|
||||
## protocol.interceptBufferProtocol(scheme, handler[, completion])
|
||||
### `protocol.interceptBufferProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme` 프로토콜을 가로채고 `handler`를 `Buffer` 전송에 대한 새로운 동작으로 사용합니다.
|
||||
|
||||
## protocol.interceptHttpProtocol(scheme, handler[, completion])
|
||||
### `protocol.interceptHttpProtocol(scheme, handler[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `handler` Function
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
`scheme` 프로토콜을 가로채고 `handler`를 HTTP 프로토콜의 요청에 대한 새로운 동작으로 사용합니다.
|
||||
|
||||
## protocol.uninterceptProtocol(scheme[, completion])
|
||||
### `protocol.uninterceptProtocol(scheme[, completion])`
|
||||
|
||||
* `scheme` String
|
||||
* `completion` Function
|
||||
* `completion` Function (optional)
|
||||
|
||||
가로챈 `scheme`를 삭제하고 기본 핸들러로 복구합니다.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# remote
|
||||
|
||||
`remote` 모듈은 메인 프로세스와 랜더러 프로세스 사이에 inter-process 통신을 간단하게 추상화 한 모듈입니다.
|
||||
`remote` 모듈은 메인 프로세스와 랜더러 프로세스(웹 페이지) 사이의 inter-process (IPC) 통신을 간단하게 추상화 한 모듈입니다.
|
||||
|
||||
Electron의 랜더러 프로세스에선 GUI와 관련 없는 모듈만 사용할 수 있습니다.
|
||||
기본적으로 랜더러 프로세스에서 메인 프로세스의 API를 사용하려면 inter-process 통신을 사용해야 합니다.
|
||||
하지만 `remote` 모듈을 사용하면 따로 inter-process 통신을 사용하지 않고 직접 명시적으로 사용할 수 있습니다.
|
||||
기본적으로 랜더러 프로세스에서 메인 프로세스의 API를 사용하려면 메인 프로세스와 inter-process 통신을 해야 합니다.
|
||||
하지만 `remote` 모듈을 사용하면 따로 inter-process 통신을 하지 않고 직접 명시적으로 모듈을 사용할 수 있습니다.
|
||||
Java의 [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation)와 개념이 비슷합니다.
|
||||
|
||||
다음 예제는 랜더러 프로세스에서 브라우저 창을 만드는 예제입니다:
|
||||
|
@ -12,21 +12,22 @@ Java의 [RMI](http://en.wikipedia.org/wiki/Java_remote_method_invocation)와 개
|
|||
```javascript
|
||||
var remote = require('remote');
|
||||
var BrowserWindow = remote.require('browser-window');
|
||||
|
||||
var win = new BrowserWindow({ width: 800, height: 600 });
|
||||
win.loadUrl('https://github.com');
|
||||
```
|
||||
|
||||
알림: 반대로 하려면(메인 프로세스에서 랜더러 프로세스에 접근) [webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code) API를 사용하면 됩니다.
|
||||
**참고:** 반대로 메인 프로세스에서 랜더러 프로세스에 접근 하려면 [webContents.executeJavascript](browser-window.md#webcontents-executejavascript-code) 메서드를 사용하면 됩니다.
|
||||
|
||||
## Remote 객체
|
||||
|
||||
`remote` 모듈로부터 반환된 각 객체(함수 포함)는 메인 프로세스의 객체를 추상화 한 객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다)
|
||||
Remote 모듈의 함수를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 동기형 inter-process 메시지를 보냅니다.
|
||||
`remote` 모듈로부터 반환된 각 객체(메서드 포함)는 메인 프로세스의 객체를 추상화 한 객체입니다. (우리는 그것을 remote 객체 또는 remote 함수라고 부릅니다)
|
||||
Remote 모듈의 메서드를 호출하거나, 객체에 접근하거나, 생성자로 객체를 생성하는 등의 작업은 실질적으로 동기형 inter-process 메시지를 보냅니다.
|
||||
|
||||
위의 예제에서 사용한 두 `BrowserWindow`와 `win`은 remote 객체입니다. 그리고 `new BrowserWindow`이 생성하는 `BrowserWindow` 객체는 랜더러 프로세스에서 생성되지 않습니다.
|
||||
대신에 이 `BrowserWindow` 객체는 메인 프로세스에서 생성되며 랜더러 프로세스에 `win` 객체와 같이 이에 대응하는 remote 객체를 반환합니다.
|
||||
|
||||
## Remote 객체의 일생
|
||||
## Remote 객체의 생명 주기
|
||||
|
||||
Electron은 랜더러 프로세스의 remote 객체가 살아있는 한(다시 말해서 GC(garbage collection)가 일어나지 않습니다) 대응하는 메인 프로세스의 객체는 릴리즈되지 않습니다.
|
||||
Remote 객체가 GC 되려면 대응하는 메인 프로세스 내부 객체의 참조가 해제되어야만 합니다.
|
||||
|
@ -38,50 +39,89 @@ Remote 객체가 GC 되려면 대응하는 메인 프로세스 내부 객체의
|
|||
|
||||
## 메인 프로세스로 콜백 넘기기
|
||||
|
||||
몇몇 메인 프로세스의 API는 콜백 함수를 사용합니다. 그리고 보통 remote 함수를 호출할 때 콜백 함수를 넘길 것입니다.
|
||||
`remote` 모듈은 이를 지원합니다. 하지만 반드시 주의해서 사용해야 합니다.
|
||||
메인 프로세스의 코드는 `remote` 모듈을 통해 랜더러 프로세스가 전달하는 콜백 함수를 받을 수 있습니다.
|
||||
하지만 이 작업은 반드시 주의를 기울여 사용해야 합니다.
|
||||
|
||||
첫째, 데드락을 피하기 위해 메인 프로세스로 전달된 콜백들은 비동기로 호출됩니다.
|
||||
그래서 전달된 콜백들이 언제나 값을 반환할 것이라고 기대하면 안 됩니다.
|
||||
이러한 이유로 메인 프로세스로 전달된 콜백들의 반환 값을 내부 함수에서 언제나 정상적으로 받을 것이라고 예측해선 안됩니다.
|
||||
|
||||
둘째, 콜백들은 메인 프로세스로 전송되고 호출된 후에도 자동으로 참조가 릴리즈 되지 않습니다.
|
||||
참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 남아있게 됩니다.
|
||||
예를 들어 메인 프로세스에서 `Array.map` 같은 메서드를 사용할 때 랜더러 프로세스에서 전달된 함수를 사용해선 안됩니다:
|
||||
|
||||
다음 코드를 보면 느낌이 팟 하고 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 설치합니다:
|
||||
```javascript
|
||||
// mapNumbers.js 메인 프로세스
|
||||
exports.withRendererCallback = function(mapper) {
|
||||
return [1,2,3].map(mapper);
|
||||
}
|
||||
|
||||
exports.withLocalCallback = function() {
|
||||
return exports.mapNumbers(function(x) {
|
||||
return x + 1;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
```javascript
|
||||
// 랜더러 프로세스
|
||||
var mapNumbers = require("remote").require("mapNumbers");
|
||||
|
||||
var withRendererCb = mapNumbers.withRendererCallback(function(x) {
|
||||
return x + 1;
|
||||
})
|
||||
|
||||
var withLocalCb = mapNumbers.withLocalCallback()
|
||||
|
||||
console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4]
|
||||
```
|
||||
|
||||
보다시피 랜더러 콜백의 동기 반환 값은 예상되지 않은 처리입니다.
|
||||
그리고 메인 프로세스에서 처리한 함수의 반환 값과 일치하지 않습니다.
|
||||
|
||||
둘째, 콜백들은 메인 프로세스로 전달, 호출된 이후에도 자동으로 함수의 참조가 릴리즈 되지 않습니다.
|
||||
함수 참조는 메인 프로세스에서 GC가 일어나기 전까지 계속 프로세스에 남아있게 됩니다.
|
||||
|
||||
다음 코드를 보면 느낌이 올 것입니다. 이 예제는 remote 객체에 `close` 이벤트 콜백을 설치합니다:
|
||||
|
||||
```javascript
|
||||
var remote = require('remote');
|
||||
|
||||
remote.getCurrentWindow().on('close', function() {
|
||||
// blabla...
|
||||
});
|
||||
```
|
||||
|
||||
문제는 이 이벤트는 명시적으로 제거하지 않는 이상 계속해서 메인 프로세스에 남아있게 된다는 것입니다.
|
||||
그래서 매 창을 새로고침 할 때마다 콜백이 새롭게 설치되며 이전 콜백은 떨궈져 누수가 됩니다.
|
||||
설상가상으로 이전에 설치한 콜백의 콘텍스트가 릴리즈 되고 나서 `close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다.
|
||||
하지만 이 코드 처럼 이벤트를 명시적으로 제거하지 않는 이상 콜백 함수의 참조가 계속해서 메인 프로세스에 남아있게 됩니다.
|
||||
만약 명시적으로 콜백을 제거하지 않으면 매 번 창을 새로고침 할 때마다 콜백을 새로 설치합니다.
|
||||
게다가 이전 콜백이 제거되지 않고 계속해서 쌓이면서 메모리 누수가 발생합니다.
|
||||
|
||||
일반적으로 정확히 무엇을 할 것인지 잘 알고 있지 않는 이상 웬만하면 메인 프로세스로 콜백 함수를 넘기는 건 자제하는 게 좋습니다.
|
||||
설상가상으로 이전에 설치된 콜백의 콘텍스트가 릴리즈 되고 난 후(예: 페이지 새로고침) `close` 이벤트가 발생하면 예외가 발생하고 메인 프로세스가 작동 중지됩니다.
|
||||
|
||||
## remote.require(module)
|
||||
이러한 문제를 피하려면 랜더러 프로세스에서 메인 프로세스로 넘긴 함수의 참조를 사용 후 확실하게 제거해야 합니다.
|
||||
작업 후 이벤트 콜백을 포함하여 책임 있게 함수의 참조를 제거하거나 메인 프로세스에서 랜더러 프로세스가 종료될 때 내부적으로 함수 참조를 제거하도록 설계해야 합니다.
|
||||
|
||||
## Methods
|
||||
|
||||
`remote` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `remote.require(module)`
|
||||
|
||||
* `module` String
|
||||
|
||||
메인 프로세스의 `require(module)` API를 실행한 후 결과 객체를 반환합니다.
|
||||
|
||||
## remote.getCurrentWindow()
|
||||
### `remote.getCurrentWindow()`
|
||||
|
||||
현재 웹 페이지가 들어있는 [BrowserWindow](browser-window.md) 객체를 반환합니다.
|
||||
현재 웹 페이지가 들어있는 [`BrowserWindow`](browser-window.md) 객체를 반환합니다.
|
||||
|
||||
## remote.getCurrentWebContents()
|
||||
### `remote.getCurrentWebContents()`
|
||||
|
||||
현재 웹 페이지의 WebContents 객체를 반환합니다.
|
||||
현재 웹 페이지의 [`WebContents`](web-contents.md) 객체를 반환합니다.
|
||||
|
||||
## remote.getGlobal(name)
|
||||
### `remote.getGlobal(name)`
|
||||
|
||||
* `name` String
|
||||
|
||||
메인 프로세스의 전역 변수(`name`)를 가져옵니다. (예시: `global[name]`)
|
||||
|
||||
## remote.process
|
||||
### `remote.process`
|
||||
|
||||
메인 프로세스의 `process` 객체를 반환합니다. `remote.getGlobal('process')`와 같습니다. 하지만 캐시 됩니다.
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
|
||||
`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다.
|
||||
|
||||
한가지 주의할 점은 랜더러 / DevTools에선 이 모듈의 이름인 `screen`은 이미 DOM 속성에 `window.screen`로 존재 하므로 `screen = require('screen')`를
|
||||
사용할 수 없습니다. 밑의 예제와 같이 `atomScreen`등의 이름으로 변수 이름을 대체하여 사용해야 합니다.
|
||||
**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다.
|
||||
밑의 예제와 같이 `atomScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다.
|
||||
|
||||
다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다:
|
||||
|
||||
|
@ -51,43 +51,57 @@ app.on('ready', function() {
|
|||
});
|
||||
```
|
||||
|
||||
## Event: display-added
|
||||
## Events
|
||||
|
||||
`screen` 모듈은 다음과 같은 이벤트를 가지고 있습니다:
|
||||
|
||||
### Event: 'display-added'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `newDisplay` Object
|
||||
|
||||
새로운 디스플레이가 추가되면 발생하는 이벤트입니다.
|
||||
|
||||
## Event: display-removed
|
||||
### Event: 'display-removed'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `oldDisplay` Object
|
||||
|
||||
기존의 디스플레이가 제거되면 발생하는 이벤트입니다.
|
||||
|
||||
## Event: display-metrics-changed
|
||||
### Event: 'display-metrics-changed'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `display` Object
|
||||
* `changedMetrics` Array
|
||||
|
||||
`display`의 하나 또는 다수의 매트릭스가 변경될 때 발생하는 이벤트입니다.
|
||||
`display`에서 하나 또는 다수의 매트릭스가 변경될 때 발생하는 이벤트입니다.
|
||||
`changedMetrics`는 변경에 대한 정보를 담은 문자열의 배열입니다.
|
||||
`bounds`, `workArea`, `scaleFactor`, `rotation`등이 변경될 수 있습니다.
|
||||
|
||||
## screen.getCursorScreenPoint()
|
||||
## Methods
|
||||
|
||||
`screen` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `screen.getCursorScreenPoint()`
|
||||
|
||||
현재 마우스 포인터의 절대 위치를 반환합니다.
|
||||
|
||||
## screen.getPrimaryDisplay()
|
||||
### `screen.getPrimaryDisplay()`
|
||||
|
||||
기본 디스플레이를 반환합니다.
|
||||
|
||||
## screen.getAllDisplays()
|
||||
### `screen.getAllDisplays()`
|
||||
|
||||
사용 가능한 모든 디스플레이를 배열로 반환합니다.
|
||||
|
||||
## screen.getDisplayNearestPoint(point)
|
||||
### `screen.getDisplayNearestPoint(point)`
|
||||
|
||||
* `point` Object
|
||||
* `x` Integer
|
||||
|
@ -95,7 +109,7 @@ app.on('ready', function() {
|
|||
|
||||
지정한 좌표에 가까운 디스플레이를 반환합니다.
|
||||
|
||||
## screen.getDisplayMatching(rect)
|
||||
### `screen.getDisplayMatching(rect)`
|
||||
|
||||
* `rect` Object
|
||||
* `x` Integer
|
||||
|
|
|
@ -1,34 +1,39 @@
|
|||
# shell
|
||||
|
||||
`shell` 모듈은 데스크톱 환경 통합에 관련하여 제공되는 모듈입니다.
|
||||
`shell` 모듈은 데스크톱 환경 통합에 관련한 유틸리티를 제공하는 모듈입니다.
|
||||
|
||||
다음 예제는 기본 브라우저로 설정된 URL을 엽니다:
|
||||
다음 예제는 설정된 URL을 유저의 기본 브라우저로 엽니다:
|
||||
|
||||
```javascript
|
||||
var shell = require('shell');
|
||||
shell.openExternal('https://github.com');
|
||||
```
|
||||
|
||||
## shell.showItemInFolder(fullPath)
|
||||
## Methods
|
||||
|
||||
`shell` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
### `shell.showItemInFolder(fullPath)`
|
||||
|
||||
* `fullPath` String
|
||||
|
||||
지정한 파일을 탐색기에서 보여줍니다. 가능한 경우 탐색기 내에서 파일을 선택합니다.
|
||||
|
||||
## shell.openItem(fullPath)
|
||||
### `shell.openItem(fullPath)`
|
||||
|
||||
* `fullPath` String
|
||||
|
||||
지정한 파일을 데스크톱 기본 프로그램으로 엽니다.
|
||||
|
||||
## shell.openExternal(url)
|
||||
### `shell.openExternal(url)`
|
||||
|
||||
* `url` String
|
||||
|
||||
제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 mailto: URL은 해당 URL을 기본 메일 에이전트로 엽니다.)
|
||||
제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.)
|
||||
|
||||
역주: 폴더는 'file:\\\\C:\\'와 같이 지정하여 열 수 있습니다. (`\\`로 경로를 표현한 이유는 Escape 문자열을 참고하세요.)
|
||||
|
||||
## shell.moveItemToTrash(fullPath)
|
||||
### `shell.moveItemToTrash(fullPath)`
|
||||
|
||||
* `fullPath` String
|
||||
|
||||
|
@ -36,6 +41,6 @@ Move the given file to trash and returns boolean status for the operation.
|
|||
|
||||
지정한 파일을 휴지통으로 이동합니다. 작업의 성공여부를 boolean 형으로 리턴합니다.
|
||||
|
||||
## shell.beep()
|
||||
### `shell.beep()`
|
||||
|
||||
비프음을 재생합니다.
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
# 개요
|
||||
|
||||
Electron은 모든 [node.js's built-in 모듈](http://nodejs.org/api/)과 third-party node 모듈을 완벽하게 지원합니다. ([네이티브 모듈](../tutorial/using-native-node-modules.md)을 포함해서)
|
||||
Electron은 모든 [Node.js의 built-in 모듈](http://nodejs.org/api/)과 third-party node 모듈을 완벽하게 지원합니다. ([네이티브 모듈](../tutorial/using-native-node-modules.md) 포함)
|
||||
|
||||
Electron은 네이티브 데스크톱 어플리케이션을 개발 할 수 있도록 추가적인 built-in 모듈을 제공합니다.
|
||||
몇몇 모듈은 메인 프로세스에서만 사용할 수 있고 어떤 모듈은 랜더러 프로세스에서만 사용할 수 있습니다. 또한 두 프로세스 모두 사용할 수 있는 모듈도 있습니다.
|
||||
기본적인 규칙은 다음과 같습니다: GUI와 저 수준 시스템에 관련된 모듈은 오직 메인 프로세스에서만 사용할 수 있습니다.
|
||||
[메인 프로세스 vs. 랜더러 프로세스](../tutorial/quick-start.md#메인 프로세스) 컨셉에 익숙해야 이 모듈들을 사용하기 쉬우므로 해당 문서를 정독하는 것을 권장합니다.
|
||||
몇몇 모듈은 메인 프로세스에서만 사용할 수 있고 어떤 모듈은 랜더러 프로세스(웹 페이지)에서만 사용할 수 있습니다.
|
||||
또한 두 프로세스 모두 사용할 수 있는 모듈도 있습니다.
|
||||
|
||||
기본적인 규칙으로 [GUI](https://en.wikipedia.org/wiki/Graphical_user_interface)와 저 수준 시스템에 관련된 모듈들은 오직 메인 프로세스에서만 사용할 수 있습니다.
|
||||
[메인 프로세스 vs. 랜더러 프로세스](../tutorial/quick-start.md#메인 프로세스) 컨셉에 익숙해야 이 모듈들을 사용하기 쉬우므로 관련 문서를 읽어 보는 것을 권장합니다.
|
||||
|
||||
메인 프로세스 스크립트는 일반 `node.js` 스크립트와 같습니다:
|
||||
메인 프로세스 스크립트는 일반 Node.js 스크립트와 비슷합니다:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
|
@ -22,7 +23,7 @@ app.on('ready', function() {
|
|||
});
|
||||
```
|
||||
|
||||
웹 페이지 역시 예외적인 node module을 사용할 수 있다는 점을 제외하면 일반 웹 페이지와 다를게 없습니다:
|
||||
랜더러 프로세스도 예외적인 node module들을 사용할 수 있다는 점을 제외하면 일반 웹 페이지와 크게 다를게 없습니다:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
|
|
|
@ -29,19 +29,25 @@ __플랫폼별 한계:__
|
|||
* 앱 알림 표시기는 컨텍스트 메뉴를 가지고 있을 때만 보입니다.
|
||||
* Linux에서 앱 알림 표시기가 사용될 경우, `clicked` 이벤트는 무시됩니다.
|
||||
|
||||
이러한 이유로 만약 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면, 설계시 `clicked` 이벤트에 의존하지 말아야합니다.
|
||||
그리고 언제나 컨텍스트 메뉴를 포함해서 사용해야 합니다.
|
||||
이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `clicked` 이벤트에 의존해선 안됩니다.
|
||||
그리고 언제나 컨텍스트 메뉴를 포함해야 합니다.
|
||||
|
||||
## Class: Tray
|
||||
|
||||
`Tray`는 [EventEmitter][event-emitter]를 상속 받았습니다.
|
||||
|
||||
### new Tray(image)
|
||||
### `new Tray(image)`
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
|
||||
전달된 `image`를 이용하여 트레이 아이콘을 만듭니다.
|
||||
|
||||
## Events
|
||||
|
||||
`Tray` 모듈은 다음과 같은 이벤트를 가지고 있습니다:
|
||||
|
||||
**참고:** 몇가지 이벤트는 특정한 플랫폼에서만 작동합니다.
|
||||
|
||||
### Event: 'clicked'
|
||||
|
||||
* `event` Event
|
||||
|
@ -57,9 +63,9 @@ __플랫폼별 한계:__
|
|||
|
||||
트레이 아이콘이 클릭될 때 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ `bounds`는 OS X 와 Windows 7 이후 버전에서만 작동합니다.
|
||||
__주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다.
|
||||
|
||||
### Event: 'right-clicked'
|
||||
### Event: 'right-clicked' _OS X_ _Windows_
|
||||
|
||||
* `event` Event
|
||||
* `altKey` Boolean
|
||||
|
@ -74,9 +80,7 @@ __주의:__ `bounds`는 OS X 와 Windows 7 이후 버전에서만 작동합니
|
|||
|
||||
트레이 아이콘을 오른쪽 클릭될 때 호출 됩니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X 와 Windows 운영체제에서만 작동합니다.
|
||||
|
||||
### Event: 'double-clicked'
|
||||
### Event: 'double-clicked' _OS X_ _Windows_
|
||||
|
||||
* `event` Event
|
||||
* `altKey` Boolean
|
||||
|
@ -91,76 +95,66 @@ __주의:__ 이 기능은 OS X 와 Windows 운영체제에서만 작동합니다
|
|||
|
||||
트레이 아이콘이 더블 클릭될 때 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X 와 Windows 운영체제에서만 작동합니다.
|
||||
|
||||
### Event: 'balloon-show'
|
||||
### Event: 'balloon-show' _Windows_
|
||||
|
||||
알림풍선이 보여질 때 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ 이 기능은 Windows에서만 작동합니다.
|
||||
|
||||
### Event: 'balloon-clicked'
|
||||
### Event: 'balloon-clicked' _Windows_
|
||||
|
||||
알림풍선이 클릭될 때 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ 이 기능은 Windows에서만 작동합니다.
|
||||
|
||||
### Event: 'balloon-closed'
|
||||
### Event: 'balloon-closed' _Windows_
|
||||
|
||||
알림풍선이 시간이 지나 사라지거나 유저가 클릭하여 닫을 때 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ 이 기능은 Windows에서만 작동합니다.
|
||||
|
||||
### Event: 'drop-files'
|
||||
### Event: 'drop-files' _OS X_
|
||||
|
||||
* `event`
|
||||
* `files` Array - 드롭된 파일의 경로
|
||||
|
||||
트레이 아이콘에 파일이 드롭되면 발생하는 이벤트입니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X에서만 작동합니다.
|
||||
## Methods
|
||||
|
||||
### Tray.destroy()
|
||||
`Tray` 모듈은 다음과 같은 메서드를 가지고 있습니다:
|
||||
|
||||
**참고:** 몇가지 메서드는 특정한 플랫폼에서만 작동합니다.
|
||||
|
||||
### `Tray.destroy()`
|
||||
|
||||
트레이 아이콘을 즉시 삭제시킵니다.
|
||||
|
||||
### Tray.setImage(image)
|
||||
### `Tray.setImage(image)`
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
|
||||
`image`를 사용하여 트레이 아이콘의 이미지를 설정합니다.
|
||||
|
||||
### Tray.setPressedImage(image)
|
||||
### `Tray.setPressedImage(image)` _OS X_
|
||||
|
||||
* `image` [NativeImage](native-image.md)
|
||||
|
||||
`image`를 사용하여 트레이 아이콘이 눌렸을 때의 이미지를 설정합니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X에서만 작동합니다.
|
||||
|
||||
### Tray.setToolTip(toolTip)
|
||||
### `Tray.setToolTip(toolTip)`
|
||||
|
||||
* `toolTip` String
|
||||
|
||||
트레이 아이콘의 툴팁 텍스트를 설정합니다.
|
||||
|
||||
### Tray.setTitle(title)
|
||||
### `Tray.setTitle(title)` _OS X_
|
||||
|
||||
* `title` String
|
||||
|
||||
상태바에서 트레이 아이콘 옆에 표시되는 제목 텍스트를 설정합니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X에서만 작동합니다.
|
||||
|
||||
### Tray.setHighlightMode(highlight)
|
||||
### `Tray.setHighlightMode(highlight)` _OS X_
|
||||
|
||||
* `highlight` Boolean
|
||||
|
||||
트레이 아이콘을 클릭했을 때 하이라이트 될지 설정합니다.
|
||||
|
||||
__주의:__ 이 기능은 OS X에서만 작동합니다.
|
||||
|
||||
### Tray.displayBalloon(options)
|
||||
### `Tray.displayBalloon(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `icon` [NativeImage](native-image.md)
|
||||
|
@ -169,19 +163,15 @@ __주의:__ 이 기능은 OS X에서만 작동합니다.
|
|||
|
||||
트레이에 알림풍선을 생성합니다.
|
||||
|
||||
__알림:__ 이 기능은 Windows에서만 작동합니다.
|
||||
### `Tray.popContextMenu([position])` _OS X_ _Windows_
|
||||
|
||||
### Tray.popContextMenu([position])
|
||||
|
||||
* `position` Object - 팝 메뉴 위치
|
||||
* `position` Object (optional) - 팝업 메뉴 위치
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
`position`은 Windows에서만 사용할 수 있으며 기본값은 (0, 0)입니다.
|
||||
|
||||
__주의:__ 이 기능은 Windows 와 OS X에서만 작동합니다.
|
||||
|
||||
### Tray.setContextMenu(menu)
|
||||
### `Tray.setContextMenu(menu)`
|
||||
|
||||
* `menu` Menu
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# web-frame
|
||||
|
||||
`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 해줍니다.
|
||||
`web-frame` 모듈은 현재 웹 페이지의 랜더링 상태를 설정 할 수 있도록 관련 유틸리티를 제공하는 모듈입니다.
|
||||
|
||||
다음 예제는 현재 페이지를 200% 줌 합니다.
|
||||
다음 예제는 현재 페이지를 200% 줌 합니다:
|
||||
|
||||
```javascript
|
||||
var webFrame = require('web-frame');
|
||||
|
@ -30,6 +30,13 @@ webFrame.setZoomFactor(2);
|
|||
|
||||
현재 줌 레벨을 반환합니다.
|
||||
|
||||
## webFrame.setZoomLevelLimits(minimumLevel, maximumLevel)
|
||||
|
||||
* `minimumLevel` Number
|
||||
* `maximumLevel` Number
|
||||
|
||||
줌 레벨의 최대, 최소치를 지정합니다.
|
||||
|
||||
## webFrame.setSpellCheckProvider(language, autoCorrectWord, provider)
|
||||
|
||||
* `language` String
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# `window.open` 함수
|
||||
# `window.open` 메서드
|
||||
|
||||
`window.open` 함수가 호출되면 새 창에서 새로운 페이지를 불러옵니다.
|
||||
이 창은 `url`로 부터 만들어진 `BrowserWindow`의 새 인스턴스이며 본 객체 대신 페이지의 컨트롤이 제한된 프록시 객체를 반환합니다.
|
||||
`window.open` 메서드가 호출되면 새 창을 생성하고 `url` 페이지를 불러옵니다.
|
||||
이 창은 지정한 `url`을 로드하여 만들어진 `BrowserWindow`의 새 인스턴스이며 본래 창 객체 대신 페이지의 컨트롤이 제한된 프록시 객체를 반환합니다.
|
||||
|
||||
프록시 객체는 기존의 웹 페이지와 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
|
||||
프록시 객체는 브라우저의 웹 페이지 창과 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
|
||||
창의 모든 컨트롤을 가지려면 `BrowserWindow`를 직접 생성하여 작업해야 합니다.
|
||||
|
||||
## window.open(url, [frameName[, features]])
|
||||
|
@ -19,7 +19,7 @@
|
|||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
부모 윈도우에 메시지를 보냅니다. 특정한 origin을 지정할 수도 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
|
||||
부모 윈도우에 메시지를 보냅니다. origin을 특정할 수 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
|
||||
|
||||
## Class: BrowserWindowProxy
|
||||
|
||||
|
@ -52,6 +52,6 @@ Forcefully closes the child window without calling its unload event.
|
|||
* `message` String
|
||||
* `targetOrigin` String
|
||||
|
||||
자식 윈도우에 메시지를 보냅니다. 특정한 origin을 지정할 수도 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
|
||||
자식 윈도우에 메시지를 보냅니다. origin을 특정할 수 있으며 `*`를 지정하면 따로 origin 설정을 사용하지 않습니다.
|
||||
|
||||
참고로 자식 윈도우의 `window.opener` 객체에는 다른 속성 없이 이 함수 하나만 구현되어 있습니다.
|
||||
참고로 자식 윈도우의 `window.opener` 객체에는 다른 속성 없이 이 메서드 한 개만 구현되어 있습니다.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# NW.js와 기술적으로 다른점 (이전 node-webkit)
|
||||
|
||||
__알림: Electron은 이전까지 Atom Shell로 불려졌습니다.__
|
||||
__주의: Electron은 Atom Shell의 새로운 이름입니다.__
|
||||
|
||||
NW.js 처럼 Electron은 JavaScript와 HTML 그리고 Node 통합환경을 제공함으로써 웹 페이지에서 저수준 시스템에 접근할 수 있는 웹 기반 데스크탑 어플리케이션을 작성할 수 있도록 합니다.
|
||||
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
|
||||
* Python 2.7.x. 몇몇 CentOS와 같은 배포판들은 아직도 Python 2.6.x 버전을 사용합니다. 그래서 `python -V`를 통해 버전을 확인해 줄 필요가 있습니다.
|
||||
* Node.js v0.12.x. Node를 설치하는 방법은 여러가지가 있습니다. 그중 하나는 [Node.js](http://nodejs.org) 사이트에서 소스코드를 받아 빌드하는 방법입니다.
|
||||
이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 또는 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories) 에서 받아올 수도 있습니다.
|
||||
이렇게 하면 Node를 일반 유저로 홈 디렉터리에 설치할 수 있습니다. 또는 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories)에서 소스 파일을 받아올 수 있습니다.
|
||||
자세한 내용은 [Node.js 설치 방법](https://github.com/joyent/node/wiki/Installation) 을 참고하세요.
|
||||
* Clang 3.4 또는 최신 버전
|
||||
* GTK+ 와 libnotify의 개발용 헤더
|
||||
|
||||
Ubuntu를 사용하고 있다면 다음 커맨드로 설치하면 합니다:
|
||||
Ubuntu를 사용하고 있다면 다음과 같이 라이브러리를 설치해야 합니다:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
|
||||
|
@ -18,7 +18,15 @@ $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \
|
|||
libxss1 libnss3-dev gcc-multilib g++-multilib
|
||||
```
|
||||
|
||||
다른 배포판의 경우 yum과 같은 패키지 매니저를 통해 패키지를 설치 할 수 있습니다. 패키지의 이름은 대부분 비슷할 것입니다.
|
||||
Fedora를 사용하고 있다면 다음과 같이 라이브러리를 설치해야 합니다:
|
||||
|
||||
```bash
|
||||
$ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring-devel \
|
||||
xorg-x11-server-utils libcap-devel cups-devel libXtst-devel \
|
||||
alsa-lib-devel libXrandr-devel GConf2-devel nss-devel
|
||||
```
|
||||
|
||||
다른 배포판의 경우 pacman 같은 패키지 매니저를 통해 패키지를 설치 할 수 있습니다. 패키지의 이름은 대부분 위 예시와 비슷할 것입니다.
|
||||
또는 소스코드를 내려받아 직접 빌드하는 방법도 있습니다.
|
||||
|
||||
## 가상머신을 사용하여 빌드 하는 경우
|
||||
|
@ -78,7 +86,7 @@ $ ./script/create-dist.py
|
|||
이 스크립트는 매우 작은 배포판을 `dist` 디렉터리에 생성합니다.
|
||||
create-dist.py 스크립트를 실행한 이후 1.3GB를 초과하는 공간을 차지하는 out/R 폴더의 실행파일 바이너리는 삭제해도 됩니다.
|
||||
|
||||
`Debug` 타겟만 빌드 할 수도 있습니다:
|
||||
또는 `Debug` 타겟만 빌드 할 수 있습니다:
|
||||
|
||||
```bash
|
||||
$ ./script/build.py -c D
|
||||
|
|
|
@ -34,7 +34,7 @@ $ ./script/bootstrap.py -v
|
|||
$ ./script/build.py
|
||||
```
|
||||
|
||||
`Debug` 타겟만 빌드 할 수도 있습니다:
|
||||
또는 `Debug` 타겟만 빌드 할 수 있습니다:
|
||||
|
||||
```bash
|
||||
$ ./script/build.py -c D
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
* [git](http://git-scm.com)
|
||||
|
||||
현재 Windows를 설치하지 않았다면 [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads)에서
|
||||
사용기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드할 수도 있습니다.
|
||||
사용 기한이 정해져있는 무료 가상머신 버전의 Windows를 받아 Electron을 빌드하는 방법도 있습니다.
|
||||
|
||||
Electron은 전적으로 command-line 스크립트를 사용하여 빌드합니다. 그렇기에 Electron을 개발하는데 아무런 에디터나 사용할 수 있습니다.
|
||||
하지만 이 말은 Visual Studio를 개발을 위해 사용할 수 없다는 말이 됩니다. 나중에 Visual Studio를 이용한 빌드 방법도 제공할 예정입니다.
|
||||
|
@ -40,7 +40,7 @@ python script\bootstrap.py -v
|
|||
python script\build.py
|
||||
```
|
||||
|
||||
`Debug` 타겟만 빌드 할 수도 있습니다:
|
||||
또는 `Debug` 타겟만 빌드 할 수 있습니다:
|
||||
|
||||
```powershell
|
||||
python script\build.py -c D
|
||||
|
@ -72,6 +72,15 @@ python script\cpplint.py
|
|||
python script\test.py
|
||||
```
|
||||
|
||||
테스트 실행시 `runas`와 같은 네이티브 모듈을 포함하는데 이 모듈은 디버그 빌드에서 같이 사용할 수 없습니다.
|
||||
하지만 여전히 릴리즈 빌드에선 사용할 수 있습니다.
|
||||
|
||||
릴리즈 빌드로 테스트를 실행하려면 다음 커맨드를 사용하면 됩니다:
|
||||
|
||||
```powershell
|
||||
python script\test.py -R
|
||||
```
|
||||
|
||||
## 문제 해결
|
||||
|
||||
### Command xxxx not found
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# 디버거에서 디버그 심볼 서버 설정
|
||||
|
||||
디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 라이브러리에서 함수에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다.
|
||||
디버그 심볼은 디버깅 세션을 더 좋게 개선해 줍니다. 디버그 심볼은 실행 파일과 동적 링크 라이브러리에서 메서드에 대한 정보를 담고 있으며 명료한 함수 호출 스텍 정보를 제공합니다.
|
||||
심볼 서버는 유저가 크기가 큰 디버깅용 파일을 필수적으로 다운로드 받지 않고도 디버거가 알맞은 심볼, 바이너리 그리고 소스를 자동적으로 로드할 수 있도록 해줍니다.
|
||||
서버 사용법은 [Microsoft의 심볼 서버](http://support.microsoft.com/kb/311503)와 비슷합니다. 이 문서를 참조하세요.
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue