Merge commit '58567834c7' into web-contents-download-url

Conflicts:
	atom/browser/api/atom_api_web_contents.cc
This commit is contained in:
Charlie Hess 2015-12-03 10:31:51 -08:00
commit f2797d2eab
55 changed files with 555 additions and 402 deletions

View file

@ -322,14 +322,6 @@ void Cookies::OnSetCookies(const CookiesCallback& callback,
callback));
}
mate::ObjectTemplateBuilder Cookies::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("get", &Cookies::Get)
.SetMethod("remove", &Cookies::Remove)
.SetMethod("set", &Cookies::Set);
}
net::CookieStore* Cookies::GetCookieStore() {
return request_context_getter_->GetURLRequestContext()->cookie_store();
}
@ -341,6 +333,15 @@ mate::Handle<Cookies> Cookies::Create(
return mate::CreateHandle(isolate, new Cookies(browser_context));
}
// static
void Cookies::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.SetMethod("get", &Cookies::Get)
.SetMethod("remove", &Cookies::Remove)
.SetMethod("set", &Cookies::Set);
}
} // namespace api
} // namespace atom

View file

@ -7,8 +7,8 @@
#include <string>
#include "atom/browser/api/trackable_object.h"
#include "base/callback.h"
#include "native_mate/wrappable.h"
#include "native_mate/handle.h"
#include "net/cookies/canonical_cookie.h"
@ -33,7 +33,7 @@ namespace atom {
namespace api {
class Cookies : public mate::Wrappable {
class Cookies : public mate::TrackableObject<Cookies> {
public:
// node.js style callback function(error, result)
typedef base::Callback<void(v8::Local<v8::Value>, v8::Local<v8::Value>)>
@ -42,6 +42,10 @@ class Cookies : public mate::Wrappable {
static mate::Handle<Cookies> Create(v8::Isolate* isolate,
content::BrowserContext* browser_context);
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
explicit Cookies(content::BrowserContext* browser_context);
~Cookies();
@ -70,10 +74,6 @@ class Cookies : public mate::Wrappable {
void OnSetCookies(const CookiesCallback& callback,
bool set_success);
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
private:
// Must be called on IO thread.
net::CookieStore* GetCookieStore();

View file

@ -70,29 +70,20 @@ DownloadItem::DownloadItem(content::DownloadItem* download_item) :
}
DownloadItem::~DownloadItem() {
Destroy();
}
void DownloadItem::Destroy() {
if (download_item_) {
download_item_->RemoveObserver(this);
auto iter = g_download_item_objects.find(download_item_->GetId());
if (iter != g_download_item_objects.end())
g_download_item_objects.erase(iter);
download_item_ = nullptr;
}
}
bool DownloadItem::IsDestroyed() const {
return download_item_ == nullptr;
if (download_item_)
OnDownloadDestroyed(download_item_);
}
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
}
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) {
Destroy();
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) {
download_item_->RemoveObserver(this);
auto iter = g_download_item_objects.find(download_item_->GetId());
if (iter != g_download_item_objects.end())
g_download_item_objects.erase(iter);
download_item_ = nullptr;
}
int64 DownloadItem::GetReceivedBytes() {
@ -144,9 +135,11 @@ void DownloadItem::Cancel() {
download_item_->Cancel(true);
}
mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
// static
void DownloadItem::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.MakeDestroyable()
.SetMethod("pause", &DownloadItem::Pause)
.SetMethod("resume", &DownloadItem::Resume)
.SetMethod("cancel", &DownloadItem::Cancel)

View file

@ -17,7 +17,7 @@ namespace atom {
namespace api {
class DownloadItem : public mate::EventEmitter,
class DownloadItem : public mate::TrackableObject<DownloadItem>,
public content::DownloadItem::Observer {
public:
class SavePathData : public base::SupportsUserData::Data {
@ -32,6 +32,10 @@ class DownloadItem : public mate::EventEmitter,
content::DownloadItem* item);
static void* UserDataKey();
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
explicit DownloadItem(content::DownloadItem* download_item);
~DownloadItem();
@ -53,13 +57,6 @@ class DownloadItem : public mate::EventEmitter,
void SetSavePath(const base::FilePath& path);
private:
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
bool IsDestroyed() const override;
void Destroy();
content::DownloadItem* download_item_;
DISALLOW_COPY_AND_ASSIGN(DownloadItem);

View file

@ -23,9 +23,6 @@ GlobalShortcut::GlobalShortcut() {
}
GlobalShortcut::~GlobalShortcut() {
}
void GlobalShortcut::Destroy() {
UnregisterAll();
}

View file

@ -27,9 +27,6 @@ class GlobalShortcut : public extensions::GlobalShortcutListener::Observer,
GlobalShortcut();
~GlobalShortcut() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;

View file

@ -27,14 +27,6 @@ Menu::Menu()
Menu::~Menu() {
}
void Menu::Destroy() {
model_.reset();
}
bool Menu::IsDestroyed() const {
return !model_;
}
void Menu::AfterInit(v8::Isolate* isolate) {
mate::Dictionary wrappable(isolate, GetWrapper(isolate));
mate::Dictionary delegate;
@ -159,6 +151,7 @@ bool Menu::IsVisibleAt(int index) const {
void Menu::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.MakeDestroyable()
.SetMethod("insertItem", &Menu::InsertItemAt)
.SetMethod("insertCheckItem", &Menu::InsertCheckItemAt)
.SetMethod("insertRadioItem", &Menu::InsertRadioItemAt)

View file

@ -39,11 +39,7 @@ class Menu : public mate::TrackableObject<Menu>,
Menu();
~Menu() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable:
bool IsDestroyed() const override;
void AfterInit(v8::Isolate* isolate) override;
// ui::SimpleMenuModel::Delegate:

View file

@ -19,7 +19,6 @@ class MenuMac : public Menu {
protected:
MenuMac();
void Destroy() override;
void Popup(Window* window) override;
void PopupAt(Window* window, int x, int y) override;

View file

@ -18,11 +18,6 @@ namespace api {
MenuMac::MenuMac() {
}
void MenuMac::Destroy() {
menu_controller_.reset();
Menu::Destroy();
}
void MenuMac::Popup(Window* window) {
NativeWindow* native_window = window->window();
if (!native_window)

View file

@ -19,9 +19,6 @@ PowerMonitor::PowerMonitor() {
}
PowerMonitor::~PowerMonitor() {
}
void PowerMonitor::Destroy() {
base::PowerMonitor::Get()->RemoveObserver(this);
}

View file

@ -23,9 +23,6 @@ class PowerMonitor : public mate::TrackableObject<PowerMonitor>,
PowerMonitor();
~PowerMonitor() override;
// mate::TrackableObject:
void Destroy() override;
// base::PowerObserver implementations:
void OnPowerStateChange(bool on_battery_power) override;
void OnSuspend() override;

View file

@ -45,11 +45,6 @@ PowerSaveBlocker::PowerSaveBlocker()
PowerSaveBlocker::~PowerSaveBlocker() {
}
void PowerSaveBlocker::Destroy() {
power_save_blocker_types_.clear();
power_save_blocker_.reset();
}
void PowerSaveBlocker::UpdatePowerSaveBlocker() {
if (power_save_blocker_types_.empty()) {
power_save_blocker_.reset();

View file

@ -28,9 +28,6 @@ class PowerSaveBlocker : public mate::TrackableObject<PowerSaveBlocker> {
PowerSaveBlocker();
~PowerSaveBlocker() override;
// mate::TrackableObject:
void Destroy() override;
// mate::Wrappable implementations:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;

View file

@ -253,7 +253,6 @@ Session::Session(AtomBrowserContext* browser_context)
Session::~Session() {
content::BrowserContext::GetDownloadManager(browser_context())->
RemoveObserver(this);
Destroy();
}
void Session::OnDownloadCreated(content::DownloadManager* manager,
@ -271,14 +270,6 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
}
}
bool Session::IsDestroyed() const {
return !browser_context_;
}
void Session::Destroy() {
browser_context_ = nullptr;
}
void Session::ResolveProxy(const GURL& url, ResolveProxyCallback callback) {
new ResolveProxyHelper(browser_context(), url, callback);
}
@ -376,20 +367,6 @@ v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, cookies_);
}
mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetMethod("resolveProxy", &Session::ResolveProxy)
.SetMethod("clearCache", &Session::ClearCache)
.SetMethod("clearStorageData", &Session::ClearStorageData)
.SetMethod("setProxy", &Session::SetProxy)
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
.SetProperty("cookies", &Session::Cookies);
}
// static
mate::Handle<Session> Session::CreateFrom(
v8::Isolate* isolate, AtomBrowserContext* browser_context) {
@ -410,6 +387,22 @@ mate::Handle<Session> Session::FromPartition(
static_cast<AtomBrowserContext*>(browser_context.get()));
}
// static
void Session::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.MakeDestroyable()
.SetMethod("resolveProxy", &Session::ResolveProxy)
.SetMethod("clearCache", &Session::ClearCache)
.SetMethod("clearStorageData", &Session::ClearStorageData)
.SetMethod("setProxy", &Session::SetProxy)
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
.SetMethod("setCertificateVerifyProc", &Session::SetCertVerifyProc)
.SetProperty("cookies", &Session::Cookies);
}
void ClearWrapSession() {
g_wrap_session.Reset();
}

View file

@ -48,6 +48,10 @@ class Session: public mate::TrackableObject<Session>,
AtomBrowserContext* browser_context() const { return browser_context_.get(); }
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
explicit Session(AtomBrowserContext* browser_context);
~Session();
@ -56,15 +60,7 @@ class Session: public mate::TrackableObject<Session>,
void OnDownloadCreated(content::DownloadManager* manager,
content::DownloadItem* item) override;
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
bool IsDestroyed() const override;
private:
// mate::TrackableObject:
void Destroy() override;
void ResolveProxy(const GURL& url, ResolveProxyCallback callback);
void ClearCache(const net::CompletionCallback& callback);
void ClearStorageData(mate::Arguments* args);

View file

@ -94,14 +94,6 @@ void Tray::OnDragEnded() {
Emit("drag-end");
}
bool Tray::IsDestroyed() const {
return !tray_icon_;
}
void Tray::Destroy() {
tray_icon_.reset();
}
void Tray::SetImage(mate::Arguments* args, const gfx::Image& image) {
tray_icon_->SetImage(image);
}
@ -137,9 +129,11 @@ void Tray::DisplayBalloon(mate::Arguments* args,
}
void Tray::PopUpContextMenu(mate::Arguments* args) {
mate::Handle<Menu> menu;
args->GetNext(&menu);
gfx::Point pos;
args->GetNext(&pos);
tray_icon_->PopUpContextMenu(pos);
tray_icon_->PopUpContextMenu(pos, menu.IsEmpty() ? nullptr : menu->model());
}
void Tray::SetContextMenu(mate::Arguments* args, Menu* menu) {
@ -160,8 +154,7 @@ v8::Local<v8::Object> Tray::ModifiersToObject(v8::Isolate* isolate,
void Tray::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.SetMethod("destroy", &Tray::Destroy, true)
.SetMethod("isDestroyed", &Tray::IsDestroyed, true)
.MakeDestroyable()
.SetMethod("setImage", &Tray::SetImage)
.SetMethod("setPressedImage", &Tray::SetPressedImage)
.SetMethod("setToolTip", &Tray::SetToolTip)

View file

@ -54,12 +54,6 @@ class Tray : public mate::TrackableObject<Tray>,
void OnDragExited() override;
void OnDragEnded() override;
// mate::Wrappable:
bool IsDestroyed() const override;
// mate::TrackableObject:
void Destroy() override;
void SetImage(mate::Arguments* args, const gfx::Image& image);
void SetPressedImage(mate::Arguments* args, const gfx::Image& image);
void SetToolTip(mate::Arguments* args, const std::string& tool_tip);

View file

@ -194,8 +194,6 @@ namespace api {
namespace {
v8::Persistent<v8::ObjectTemplate> template_;
// The wrapWebContents function which is implemented in JavaScript
using WrapWebContentsCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapWebContentsCallback g_wrap_web_contents;
@ -290,7 +288,15 @@ WebContents::WebContents(v8::Isolate* isolate,
}
WebContents::~WebContents() {
Destroy();
if (type_ == WEB_VIEW && managed_web_contents()) {
// When force destroying the "destroyed" event is not emitted.
WebContentsDestroyed();
guest_delegate_->Destroy();
Observe(nullptr);
DestroyWebContents();
}
}
bool WebContents::AddMessageToConsole(content::WebContents* source,
@ -591,19 +597,6 @@ void WebContents::NavigationEntryCommitted(
details.is_in_page, details.did_replace_entry);
}
void WebContents::Destroy() {
session_.Reset();
if (type_ == WEB_VIEW && managed_web_contents()) {
// When force destroying the "destroyed" event is not emitted.
WebContentsDestroyed();
guest_delegate_->Destroy();
Observe(nullptr);
DestroyWebContents();
}
}
int WebContents::GetID() const {
return web_contents()->GetRenderProcessHost()->GetID();
}
@ -996,83 +989,73 @@ v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
}
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
if (template_.IsEmpty())
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
.SetMethod("destroy", &WebContents::Destroy, true)
.SetMethod("isDestroyed", &WebContents::IsDestroyed, true)
.SetMethod("getId", &WebContents::GetID)
.SetMethod("equal", &WebContents::Equal)
.SetMethod("_loadURL", &WebContents::LoadURL)
.SetMethod("downloadURL", &WebContents::DownloadURL)
.SetMethod("_getURL", &WebContents::GetURL)
.SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("isLoading", &WebContents::IsLoading)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("_stop", &WebContents::Stop)
.SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
.SetMethod("insertCSS", &WebContents::InsertCSS)
.SetMethod("savePage", &WebContents::SavePage)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("enableDeviceEmulation",
&WebContents::EnableDeviceEmulation)
.SetMethod("disableDeviceEmulation",
&WebContents::DisableDeviceEmulation)
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
.SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
.SetMethod("cut", &WebContents::Cut)
.SetMethod("copy", &WebContents::Copy)
.SetMethod("paste", &WebContents::Paste)
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
.SetMethod("delete", &WebContents::Delete)
.SetMethod("selectAll", &WebContents::SelectAll)
.SetMethod("unselect", &WebContents::Unselect)
.SetMethod("replace", &WebContents::Replace)
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
.SetMethod("focus", &WebContents::Focus)
.SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage, true)
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
.SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
.SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker)
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
.SetMethod("print", &WebContents::Print)
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
.SetProperty("session", &WebContents::Session, true)
.SetProperty("devToolsWebContents",
&WebContents::DevToolsWebContents, true)
.Build());
return mate::ObjectTemplateBuilder(
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
}
bool WebContents::IsDestroyed() const {
return !web_contents();
// static
void WebContents::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.MakeDestroyable()
.SetMethod("getId", &WebContents::GetID)
.SetMethod("equal", &WebContents::Equal)
.SetMethod("_loadURL", &WebContents::LoadURL)
.SetMethod("downloadURL", &WebContents::DownloadURL)
.SetMethod("_getURL", &WebContents::GetURL)
.SetMethod("getTitle", &WebContents::GetTitle)
.SetMethod("isLoading", &WebContents::IsLoading)
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
.SetMethod("_stop", &WebContents::Stop)
.SetMethod("_goBack", &WebContents::GoBack)
.SetMethod("_goForward", &WebContents::GoForward)
.SetMethod("_goToOffset", &WebContents::GoToOffset)
.SetMethod("isCrashed", &WebContents::IsCrashed)
.SetMethod("setUserAgent", &WebContents::SetUserAgent)
.SetMethod("getUserAgent", &WebContents::GetUserAgent)
.SetMethod("insertCSS", &WebContents::InsertCSS)
.SetMethod("savePage", &WebContents::SavePage)
.SetMethod("_executeJavaScript", &WebContents::ExecuteJavaScript)
.SetMethod("openDevTools", &WebContents::OpenDevTools)
.SetMethod("closeDevTools", &WebContents::CloseDevTools)
.SetMethod("isDevToolsOpened", &WebContents::IsDevToolsOpened)
.SetMethod("enableDeviceEmulation",
&WebContents::EnableDeviceEmulation)
.SetMethod("disableDeviceEmulation",
&WebContents::DisableDeviceEmulation)
.SetMethod("toggleDevTools", &WebContents::ToggleDevTools)
.SetMethod("inspectElement", &WebContents::InspectElement)
.SetMethod("setAudioMuted", &WebContents::SetAudioMuted)
.SetMethod("isAudioMuted", &WebContents::IsAudioMuted)
.SetMethod("undo", &WebContents::Undo)
.SetMethod("redo", &WebContents::Redo)
.SetMethod("cut", &WebContents::Cut)
.SetMethod("copy", &WebContents::Copy)
.SetMethod("paste", &WebContents::Paste)
.SetMethod("pasteAndMatchStyle", &WebContents::PasteAndMatchStyle)
.SetMethod("delete", &WebContents::Delete)
.SetMethod("selectAll", &WebContents::SelectAll)
.SetMethod("unselect", &WebContents::Unselect)
.SetMethod("replace", &WebContents::Replace)
.SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling)
.SetMethod("focus", &WebContents::Focus)
.SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
.SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
.SetMethod("unregisterServiceWorker",
&WebContents::UnregisterServiceWorker)
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
.SetMethod("print", &WebContents::Print)
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
.SetProperty("session", &WebContents::Session)
.SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents);
}
AtomBrowserContext* WebContents::GetBrowserContext() const {

View file

@ -54,9 +54,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
static mate::Handle<WebContents> Create(
v8::Isolate* isolate, const mate::Dictionary& options);
// mate::TrackableObject:
void Destroy() override;
int GetID() const;
bool Equal(const WebContents* web_contents) const;
void LoadURL(const GURL& url, const mate::Dictionary& options);
@ -145,16 +142,15 @@ class WebContents : public mate::TrackableObject<WebContents>,
v8::Local<v8::Value> Session(v8::Isolate* isolate);
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
// mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype);
protected:
explicit WebContents(content::WebContents* web_contents);
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
~WebContents();
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
bool IsDestroyed() const override;
// content::WebContentsDelegate:
bool AddMessageToConsole(content::WebContents* source,
int32 level,

View file

@ -157,8 +157,8 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
}
Window::~Window() {
if (window_)
Destroy();
if (!window_->IsClosed())
window_->CloseContents(nullptr);
}
void Window::WillCloseWindow(bool* prevent_default) {
@ -166,19 +166,19 @@ void Window::WillCloseWindow(bool* prevent_default) {
}
void Window::OnWindowClosed() {
if (api_web_contents_) {
api_web_contents_->DestroyWebContents();
api_web_contents_ = nullptr;
web_contents_.Reset();
}
api_web_contents_->DestroyWebContents();
RemoveFromWeakMap();
window_->RemoveObserver(this);
// We can not call Destroy here because we need to call Emit first, but we
// also do not want any method to be used, so just mark as destroyed here.
MarkDestroyed();
Emit("closed");
// Clean up the resources after window has been closed.
base::MessageLoop::current()->DeleteSoon(FROM_HERE, window_.release());
// Destroy the native class when window is closed.
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
}
void Window::OnWindowBlur() {
@ -276,15 +276,6 @@ mate::Wrappable* Window::New(v8::Isolate* isolate, mate::Arguments* args) {
return new Window(isolate, options);
}
bool Window::IsDestroyed() const {
return !window_ || window_->IsClosed();
}
void Window::Destroy() {
if (window_)
window_->CloseContents(nullptr);
}
void Window::Close() {
window_->Close();
}
@ -622,8 +613,7 @@ v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
void Window::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype) {
mate::ObjectTemplateBuilder(isolate, prototype)
.SetMethod("destroy", &Window::Destroy, true)
.SetMethod("isDestroyed", &Window::IsDestroyed, true)
.MakeDestroyable()
.SetMethod("close", &Window::Close)
.SetMethod("focus", &Window::Focus)
.SetMethod("isFocused", &Window::IsFocused)
@ -695,8 +685,8 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("showDefinitionForSelection",
&Window::ShowDefinitionForSelection)
#endif
.SetProperty("id", &Window::ID, true)
.SetProperty("webContents", &Window::WebContents, true);
.SetProperty("id", &Window::ID)
.SetProperty("webContents", &Window::WebContents);
}
// static

View file

@ -77,13 +77,7 @@ class Window : public mate::TrackableObject<Window>,
void OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) override;
#endif
// mate::Wrappable:
bool IsDestroyed() const override;
private:
// mate::TrackableObject:
void Destroy() override;
// APIs for NativeWindow.
void Close();
void Focus();

View file

@ -65,7 +65,6 @@ wrapDownloadItem = (downloadItem) ->
deprecate.property downloadItem, 'url', 'getURL'
deprecate.property downloadItem, 'filename', 'getFilename'
deprecate.property downloadItem, 'mimeType', 'getMimeType'
deprecate.property downloadItem, 'hasUserGesture', 'hasUserGesture'
deprecate.rename downloadItem, 'getUrl', 'getURL'
downloadItemBindings._setWrapDownloadItem wrapDownloadItem

View file

@ -30,11 +30,11 @@ class IDUserData : public base::SupportsUserData::Data {
TrackableObjectBase::TrackableObjectBase()
: weak_map_id_(0), wrapped_(nullptr), weak_factory_(this) {
RegisterDestructionCallback(
base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr()));
cleanup_ = RegisterDestructionCallback(GetDestroyClosure());
}
TrackableObjectBase::~TrackableObjectBase() {
cleanup_.Run();
}
void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
@ -42,6 +42,18 @@ void TrackableObjectBase::AfterInit(v8::Isolate* isolate) {
AttachAsUserData(wrapped_);
}
void TrackableObjectBase::MarkDestroyed() {
GetWrapper(isolate())->SetAlignedPointerInInternalField(0, nullptr);
}
base::Closure TrackableObjectBase::GetDestroyClosure() {
return base::Bind(&TrackableObjectBase::Destroy, weak_factory_.GetWeakPtr());
}
void TrackableObjectBase::Destroy() {
delete this;
}
void TrackableObjectBase::AttachAsUserData(base::SupportsUserData* wrapped) {
if (weak_map_id_ != 0) {
wrapped->SetUserData(kTrackedObjectKey, new IDUserData(weak_map_id_));
@ -63,9 +75,9 @@ int32_t TrackableObjectBase::GetIDFromWrappedClass(base::SupportsUserData* w) {
}
// static
void TrackableObjectBase::RegisterDestructionCallback(
const base::Closure& closure) {
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(closure);
base::Closure TrackableObjectBase::RegisterDestructionCallback(
const base::Closure& c) {
return atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(c);
}
} // namespace mate

View file

@ -12,6 +12,7 @@
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "native_mate/object_template_builder.h"
namespace base {
class SupportsUserData;
@ -30,26 +31,32 @@ class TrackableObjectBase : public mate::EventEmitter {
// Wrap TrackableObject into a class that SupportsUserData.
void AttachAsUserData(base::SupportsUserData* wrapped);
// Subclasses should implement this to destroy their native types.
virtual void Destroy() = 0;
protected:
~TrackableObjectBase() override;
// mate::Wrappable:
void AfterInit(v8::Isolate* isolate) override;
// Mark the JS object as destroyed.
void MarkDestroyed();
// Returns a closure that can destroy the native class.
base::Closure GetDestroyClosure();
// Get the weak_map_id from SupportsUserData.
static int32_t GetIDFromWrappedClass(base::SupportsUserData* wrapped);
// Register a callback that should be destroyed before JavaScript environment
// gets destroyed.
static void RegisterDestructionCallback(const base::Closure& closure);
static base::Closure RegisterDestructionCallback(const base::Closure& c);
int32_t weak_map_id_;
base::SupportsUserData* wrapped_;
private:
void Destroy();
base::Closure cleanup_;
base::WeakPtrFactory<TrackableObjectBase> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(TrackableObjectBase);
@ -91,11 +98,6 @@ class TrackableObject : public TrackableObjectBase {
return std::vector<v8::Local<v8::Object>>();
}
TrackableObject() {
RegisterDestructionCallback(
base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
}
// Removes this instance from the weak map.
void RemoveFromWeakMap() {
if (weak_map_ && weak_map_->Has(weak_map_id()))
@ -103,28 +105,49 @@ class TrackableObject : public TrackableObjectBase {
}
protected:
TrackableObject() {}
~TrackableObject() override {
RemoveFromWeakMap();
}
void AfterInit(v8::Isolate* isolate) override {
if (!weak_map_)
if (!weak_map_) {
weak_map_.reset(new atom::IDWeakMap);
RegisterDestructionCallback(
base::Bind(&TrackableObject<T>::ReleaseAllWeakReferences));
}
weak_map_id_ = weak_map_->Add(isolate, GetWrapper(isolate));
TrackableObjectBase::AfterInit(isolate);
}
private:
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override {
if (template_.IsEmpty()) {
auto templ = v8::ObjectTemplate::New(isolate);
T::BuildPrototype(isolate, templ);
template_.Reset(isolate, templ);
}
return ObjectTemplateBuilder(
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
}
// Releases all weak references in weak map, called when app is terminating.
static void ReleaseAllWeakReferences() {
weak_map_.reset();
}
static v8::Persistent<v8::ObjectTemplate> template_;
static scoped_ptr<atom::IDWeakMap> weak_map_;
DISALLOW_COPY_AND_ASSIGN(TrackableObject);
};
template<typename T>
v8::Persistent<v8::ObjectTemplate> TrackableObject<T>::template_;
template<typename T>
scoped_ptr<atom::IDWeakMap> TrackableObject<T>::weak_map_;

View file

@ -25,6 +25,11 @@
namespace atom {
template<typename T>
void Erase(T* container, typename T::iterator iter) {
container->erase(iter);
}
// static
AtomBrowserMainParts* AtomBrowserMainParts::self_ = NULL;
@ -56,9 +61,10 @@ bool AtomBrowserMainParts::SetExitCode(int code) {
return true;
}
void AtomBrowserMainParts::RegisterDestructionCallback(
base::Closure AtomBrowserMainParts::RegisterDestructionCallback(
const base::Closure& callback) {
destruction_callbacks_.push_back(callback);
auto iter = destructors_.insert(destructors_.end(), callback);
return base::Bind(&Erase<std::list<base::Closure>>, &destructors_, iter);
}
void AtomBrowserMainParts::PreEarlyInitialization() {
@ -150,8 +156,13 @@ void AtomBrowserMainParts::PostMainMessageLoopRun() {
// Make sure destruction callbacks are called before message loop is
// destroyed, otherwise some objects that need to be deleted on IO thread
// won't be freed.
for (const auto& callback : destruction_callbacks_)
// We don't use ranged for loop because iterators are getting invalided when
// the callback runs.
for (auto iter = destructors_.begin(); iter != destructors_.end();) {
base::Closure& callback = *iter;
++iter;
callback.Run();
}
// Destroy JavaScript environment immediately after running destruction
// callbacks.

View file

@ -36,7 +36,8 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
// Register a callback that should be destroyed before JavaScript environment
// gets destroyed.
void RegisterDestructionCallback(const base::Closure& callback);
// Returns a closure that can be used to remove |callback| from the list.
base::Closure RegisterDestructionCallback(const base::Closure& callback);
Browser* browser() { return browser_.get(); }
@ -82,7 +83,7 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
base::Timer gc_timer_;
// List of callbacks should be executed before destroying JS env.
std::list<base::Closure> destruction_callbacks_;
std::list<base::Closure> destructors_;
static AtomBrowserMainParts* self_;

View file

@ -39,11 +39,12 @@ createGuest = (embedder, url, frameName, options) ->
# When |embedder| is destroyed we should also destroy attached guest, and if
# guest is closed by user then we should prevent |embedder| from double
# closing guest.
guestId = guest.id
closedByEmbedder = ->
guest.removeListener 'closed', closedByUser
guest.destroy()
closedByUser = ->
embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guest.id
embedder.send 'ATOM_SHELL_GUEST_WINDOW_MANAGER_WINDOW_CLOSED', guestId
embedder.removeListener 'render-view-deleted', closedByEmbedder
embedder.once 'render-view-deleted', closedByEmbedder
guest.once 'closed', closedByUser

View file

@ -26,7 +26,8 @@ void TrayIcon::DisplayBalloon(const gfx::Image& icon,
const base::string16& contents) {
}
void TrayIcon::PopUpContextMenu(const gfx::Point& pos) {
void TrayIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
}
void TrayIcon::NotifyClicked(const gfx::Rect& bounds, int modifiers) {

View file

@ -47,7 +47,9 @@ class TrayIcon {
const base::string16& title,
const base::string16& contents);
virtual void PopUpContextMenu(const gfx::Point& pos);
// Popups the menu.
virtual void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model);
// Set the context menu for this icon.
virtual void SetContextMenu(ui::SimpleMenuModel* menu_model) = 0;

View file

@ -29,7 +29,8 @@ class TrayIconCocoa : public TrayIcon,
void SetToolTip(const std::string& tool_tip) override;
void SetTitle(const std::string& title) override;
void SetHighlightMode(bool highlight) override;
void PopUpContextMenu(const gfx::Point& pos) override;
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
protected:

View file

@ -23,6 +23,7 @@ const CGFloat kVerticalTitleMargin = 2;
atom::TrayIconCocoa* trayIcon_; // weak
AtomMenuController* menuController_; // weak
BOOL isHighlightEnable_;
BOOL forceHighlight_;
BOOL inMouseEventSequence_;
base::scoped_nsobject<NSImage> image_;
base::scoped_nsobject<NSImage> alternateImage_;
@ -39,6 +40,8 @@ const CGFloat kVerticalTitleMargin = 2;
image_.reset([image copy]);
trayIcon_ = icon;
isHighlightEnable_ = YES;
forceHighlight_ = NO;
inMouseEventSequence_ = NO;
if ((self = [super initWithFrame: CGRectZero])) {
// Setup the image view.
@ -238,7 +241,19 @@ const CGFloat kVerticalTitleMargin = 2;
[self setNeedsDisplay:YES];
}
- (void)popUpContextMenu {
- (void)popUpContextMenu:(ui::SimpleMenuModel*)menu_model {
// Show a custom menu.
if (menu_model) {
base::scoped_nsobject<AtomMenuController> menuController(
[[AtomMenuController alloc] initWithModel:menu_model]);
forceHighlight_ = YES; // Should highlight when showing menu.
[self setNeedsDisplay:YES];
[statusItem_ popUpStatusItemMenu:[menuController menu]];
forceHighlight_ = NO;
[self setNeedsDisplay:YES];
return;
}
if (menuController_ && ![menuController_ isMenuOpen]) {
// Redraw the dray icon to show highlight if it is enabled.
[self setNeedsDisplay:YES];
@ -288,6 +303,8 @@ const CGFloat kVerticalTitleMargin = 2;
}
- (BOOL)shouldHighlight {
if (isHighlightEnable_ && forceHighlight_)
return true;
BOOL isMenuOpen = menuController_ && [menuController_ isMenuOpen];
return isHighlightEnable_ && (inMouseEventSequence_ || isMenuOpen);
}
@ -338,8 +355,9 @@ void TrayIconCocoa::SetHighlightMode(bool highlight) {
[status_item_view_ setHighlight:highlight];
}
void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos) {
[status_item_view_ popUpContextMenu];
void TrayIconCocoa::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
[status_item_view_ popUpContextMenu:menu_model];
}
void TrayIconCocoa::SetContextMenu(ui::SimpleMenuModel* menu_model) {

View file

@ -13,6 +13,7 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/screen.h"
#include "ui/views/controls/menu/menu_runner.h"
namespace atom {
@ -45,8 +46,7 @@ NotifyIcon::~NotifyIcon() {
Shell_NotifyIcon(NIM_DELETE, &icon_data);
}
void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
int modifiers,
void NotifyIcon::HandleClickEvent(int modifiers,
bool left_mouse_click,
bool double_button_click) {
NOTIFYICONIDENTIFIER icon_id;
@ -66,7 +66,7 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
return;
} else if (!double_button_click) { // single right click
if (menu_model_)
PopUpContextMenu(cursor_pos);
PopUpContextMenu(gfx::Point(), menu_model_);
else
NotifyRightClicked(gfx::Rect(rect), modifiers);
}
@ -142,24 +142,26 @@ void NotifyIcon::DisplayBalloon(const gfx::Image& icon,
LOG(WARNING) << "Unable to create status tray balloon.";
}
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos) {
void NotifyIcon::PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) {
// Returns if context menu isn't set.
if (!menu_model_)
if (!menu_model)
return;
// Set our window as the foreground window, so the context menu closes when
// we click away from it.
if (!SetForegroundWindow(window_))
return;
// Show menu at mouse's position by default.
gfx::Rect rect(pos, gfx::Size());
if (pos.IsOrigin())
rect.set_origin(gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
views::MenuRunner menu_runner(
menu_model_,
menu_model,
views::MenuRunner::CONTEXT_MENU | views::MenuRunner::HAS_MNEMONICS);
ignore_result(menu_runner.RunMenuAt(
NULL,
NULL,
gfx::Rect(pos, gfx::Size()),
views::MENU_ANCHOR_TOPLEFT,
ui::MENU_SOURCE_MOUSE));
NULL, NULL, rect, views::MENU_ANCHOR_TOPLEFT, ui::MENU_SOURCE_MOUSE));
}
void NotifyIcon::SetContextMenu(ui::SimpleMenuModel* menu_model) {

View file

@ -33,8 +33,7 @@ class NotifyIcon : public TrayIcon {
// Handles a click event from the user - if |left_button_click| is true and
// there is a registered observer, passes the click event to the observer,
// otherwise displays the context menu if there is one.
void HandleClickEvent(const gfx::Point& cursor_pos,
int modifiers,
void HandleClickEvent(int modifiers,
bool left_button_click,
bool double_button_click);
@ -52,7 +51,8 @@ class NotifyIcon : public TrayIcon {
void DisplayBalloon(const gfx::Image& icon,
const base::string16& title,
const base::string16& contents) override;
void PopUpContextMenu(const gfx::Point& pos) override;
void PopUpContextMenu(const gfx::Point& pos,
ui::SimpleMenuModel* menu_model) override;
void SetContextMenu(ui::SimpleMenuModel* menu_model) override;
private:

View file

@ -15,7 +15,6 @@
#include "base/win/win_util.h"
#include "base/win/wrapped_window_proc.h"
#include "ui/events/event_constants.h"
#include "ui/gfx/screen.h"
#include "ui/gfx/win/hwnd_util.h"
namespace atom {
@ -172,10 +171,7 @@ LRESULT CALLBACK NotifyIconHost::WndProc(HWND hwnd,
case WM_CONTEXTMENU:
// Walk our icons, find which one was clicked on, and invoke its
// HandleClickEvent() method.
gfx::Point cursor_pos(
gfx::Screen::GetNativeScreen()->GetCursorScreenPoint());
win_icon->HandleClickEvent(
cursor_pos,
GetKeyboardModifers(),
(lparam == WM_LBUTTONDOWN || lparam == WM_LBUTTONDBLCLK),
(lparam == WM_LBUTTONDBLCLK || lparam == WM_RBUTTONDBLCLK));

View file

@ -18,6 +18,8 @@
namespace {
v8::Persistent<v8::ObjectTemplate> template_;
class Archive : public mate::Wrappable {
public:
static v8::Local<v8::Value> Create(v8::Isolate* isolate,
@ -101,15 +103,20 @@ class Archive : public mate::Wrappable {
// mate::Wrappable:
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) {
return mate::ObjectTemplateBuilder(isolate)
.SetValue("path", archive_->path())
.SetMethod("getFileInfo", &Archive::GetFileInfo)
.SetMethod("stat", &Archive::Stat)
.SetMethod("readdir", &Archive::Readdir)
.SetMethod("realpath", &Archive::Realpath)
.SetMethod("copyFileOut", &Archive::CopyFileOut)
.SetMethod("getFd", &Archive::GetFD)
.SetMethod("destroy", &Archive::Destroy);
if (template_.IsEmpty())
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
.SetValue("path", archive_->path())
.SetMethod("getFileInfo", &Archive::GetFileInfo)
.SetMethod("stat", &Archive::Stat)
.SetMethod("readdir", &Archive::Readdir)
.SetMethod("realpath", &Archive::Realpath)
.SetMethod("copyFileOut", &Archive::CopyFileOut)
.SetMethod("getFd", &Archive::GetFD)
.SetMethod("destroy", &Archive::Destroy)
.Build());
return mate::ObjectTemplateBuilder(
isolate, v8::Local<v8::ObjectTemplate>::New(isolate, template_));
}
private:

View file

@ -272,7 +272,8 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
}
scoped_ptr<ScopedTemporaryFile> temp_file(new ScopedTemporaryFile);
if (!temp_file->InitFromFile(&file_, info.offset, info.size))
base::FilePath::StringType ext = path.Extension();
if (!temp_file->InitFromFile(&file_, ext, info.offset, info.size))
return false;
#if defined(OS_POSIX)

View file

@ -28,20 +28,34 @@ ScopedTemporaryFile::~ScopedTemporaryFile() {
}
}
bool ScopedTemporaryFile::Init() {
bool ScopedTemporaryFile::Init(const base::FilePath::StringType& ext) {
if (!path_.empty())
return true;
base::ThreadRestrictions::ScopedAllowIO allow_io;
return base::CreateTemporaryFile(&path_);
if (!base::CreateTemporaryFile(&path_))
return false;
#if defined(OS_WIN)
// Keep the original extension.
if (!ext.empty()) {
base::FilePath new_path = path_.AddExtension(ext);
if (!base::Move(path_, new_path))
return false;
path_ = new_path;
}
#endif
return true;
}
bool ScopedTemporaryFile::InitFromFile(base::File* src,
const base::FilePath::StringType& ext,
uint64 offset, uint64 size) {
if (!src->IsValid())
return false;
if (!Init())
if (!Init(ext))
return false;
std::vector<char> buf(size);

View file

@ -22,11 +22,13 @@ class ScopedTemporaryFile {
ScopedTemporaryFile();
virtual ~ScopedTemporaryFile();
// Init an empty temporary file.
bool Init();
// Init an empty temporary file with a certain extension.
bool Init(const base::FilePath::StringType& ext);
// Init an temporary file and fill it with content of |path|.
bool InitFromFile(base::File* src, uint64 offset, uint64 size);
bool InitFromFile(base::File* src,
const base::FilePath::StringType& ext,
uint64 offset, uint64 size);
base::FilePath path() const { return path_; }

View file

@ -4,7 +4,9 @@
#include "atom/common/native_mate_converters/callback.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
namespace mate {
@ -56,31 +58,59 @@ v8::Local<v8::Value> BindFunctionWith(v8::Isolate* isolate,
} // namespace
// Destroy the class on UI thread when possible.
struct DeleteOnUIThread {
template<typename T>
static void Destruct(const T* x) {
if (Locker::IsBrowserProcess() &&
!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, x);
} else {
delete x;
}
}
};
// Like v8::Global, but ref-counted.
template<typename T>
class RefCountedGlobal : public base::RefCountedThreadSafe<RefCountedGlobal<T>,
DeleteOnUIThread> {
public:
RefCountedGlobal(v8::Isolate* isolate, v8::Local<v8::Value> value)
: handle_(isolate, v8::Local<T>::Cast(value)) {
}
bool IsAlive() const {
return !handle_.IsEmpty();
}
v8::Local<T> NewHandle(v8::Isolate* isolate) const {
return v8::Local<T>::New(isolate, handle_);
}
private:
v8::Global<T> handle_;
DISALLOW_COPY_AND_ASSIGN(RefCountedGlobal);
};
SafeV8Function::SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value)
: v8_function_(new RefCountedPersistent<v8::Function>(isolate, value)),
weak_factory_(this) {
Init();
: v8_function_(new RefCountedGlobal<v8::Function>(isolate, value)) {
}
SafeV8Function::SafeV8Function(const SafeV8Function& other)
: v8_function_(other.v8_function_),
weak_factory_(this) {
Init();
: v8_function_(other.v8_function_) {
}
v8::Local<v8::Function> SafeV8Function::NewHandle() const {
return v8_function_->NewHandle();
SafeV8Function::~SafeV8Function() {
}
void SafeV8Function::Init() {
if (Locker::IsBrowserProcess() && atom::AtomBrowserMainParts::Get())
atom::AtomBrowserMainParts::Get()->RegisterDestructionCallback(
base::Bind(&SafeV8Function::FreeHandle, weak_factory_.GetWeakPtr()));
bool SafeV8Function::IsAlive() const {
return v8_function_.get() && v8_function_->IsAlive();
}
void SafeV8Function::FreeHandle() {
Locker locker(v8_function_->isolate());
v8_function_ = nullptr;
v8::Local<v8::Function> SafeV8Function::NewHandle(v8::Isolate* isolate) const {
return v8_function_->NewHandle(isolate);
}
v8::Local<v8::Value> CreateFunctionFromTranslater(

View file

@ -19,23 +19,21 @@ namespace mate {
namespace internal {
// Manages the V8 function with RAII, and automatically cleans the handle when
// JavaScript context is destroyed, even when the class is not destroyed.
template<typename T>
class RefCountedGlobal;
// Manages the V8 function with RAII.
class SafeV8Function {
public:
SafeV8Function(v8::Isolate* isolate, v8::Local<v8::Value> value);
SafeV8Function(const SafeV8Function& other);
~SafeV8Function();
bool is_alive() const { return v8_function_.get(); }
v8::Local<v8::Function> NewHandle() const;
bool IsAlive() const;
v8::Local<v8::Function> NewHandle(v8::Isolate* isolate) const;
private:
void Init();
void FreeHandle();
scoped_refptr<RefCountedPersistent<v8::Function>> v8_function_;
base::WeakPtrFactory<SafeV8Function> weak_factory_;
scoped_refptr<RefCountedGlobal<v8::Function>> v8_function_;
};
// Helper to invoke a V8 function with C++ parameters.
@ -49,12 +47,12 @@ struct V8FunctionInvoker<v8::Local<v8::Value>(ArgTypes...)> {
ArgTypes... raw) {
Locker locker(isolate);
v8::EscapableHandleScope handle_scope(isolate);
if (!function.is_alive())
if (!function.IsAlive())
return v8::Null(isolate);
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
Locker::IsBrowserProcess() ?
nullptr : new blink::WebScopedRunV8Script(isolate));
v8::Local<v8::Function> holder = function.NewHandle();
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args = { ConvertToV8(isolate, raw)... };
@ -70,12 +68,12 @@ struct V8FunctionInvoker<void(ArgTypes...)> {
ArgTypes... raw) {
Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
if (!function.is_alive())
if (!function.IsAlive())
return;
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
Locker::IsBrowserProcess() ?
nullptr : new blink::WebScopedRunV8Script(isolate));
v8::Local<v8::Function> holder = function.NewHandle();
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args = { ConvertToV8(isolate, raw)... };
@ -91,12 +89,12 @@ struct V8FunctionInvoker<ReturnType(ArgTypes...)> {
Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
ReturnType ret = ReturnType();
if (!function.is_alive())
if (!function.IsAlive())
return ret;
scoped_ptr<blink::WebScopedRunV8Script> script_scope(
Locker::IsBrowserProcess() ?
nullptr : new blink::WebScopedRunV8Script(isolate));
v8::Local<v8::Function> holder = function.NewHandle();
v8::Local<v8::Function> holder = function.NewHandle(isolate);
v8::Local<v8::Context> context = holder->CreationContext();
v8::Context::Scope context_scope(context);
std::vector<v8::Local<v8::Value>> args = { ConvertToV8(isolate, raw)... };

View file

@ -30,6 +30,13 @@ process.once('loaded', function() {
});
```
## Properties
### `process.noAsar`
이 속성을 `true`로 지정하면 Node 빌트인 모듈의 `asar` 아카이브 지원을 비활성화 시킬
수 있습니다.
## Methods
`process` 객체는 다음과 같은 메서드를 가지고 있습니다:

View file

@ -184,12 +184,16 @@ __주의:__ `bounds`는 OS X 와 Windows에서만 작동합니다.
트레이에 풍선 팝업을 생성합니다.
### `Tray.popContextMenu([position])` _OS X_ _Windows_
### `Tray.popUpContextMenu([menu, position])` _OS X_ _Windows_
* `position` Object (optional) - 팝업 메뉴 위치
* `menu` Menu (optional)
* `position` Object (optional) - 팝업 메뉴의 위치
* `x` Integer
* `y` Integer
트레이 아이콘의 컨텍스트 메뉴를 팝업시킵니다. `menu`가 전달되면, `menu`가 트레이
메뉴의 컨텍스트 메뉴 대신 표시됩니다.
`position`은 Windows에서만 사용할 수 있으며 기본값은 (0, 0)입니다.
### `Tray.setContextMenu(menu)`

View file

@ -441,7 +441,7 @@ Returns:
프레임 문서의 로드가 끝나면 발생하는 이벤트입니다.
### Event: 'page-title-set'
### Event: 'page-title-updated'
Returns:
@ -449,7 +449,7 @@ Returns:
* `explicitSet` Boolean
탐색하는 동안에 페이지의 제목이 설정되면 발생하는 이벤트입니다. `explicitSet`는 파일
URL에서 합(synthesised)된 제목인 경우 false로 표시됩니다.
URL에서 합(synthesised)된 제목인 경우 false로 표시됩니다.
### Event: 'page-favicon-updated'

View file

@ -103,6 +103,14 @@ var originalFs = require('original-fs');
originalFs.readFileSync('/path/to/example.asar');
```
또한 `process.noAsar``true`로 지정하면 `fs` 모듈의 `asar` 지원을 비활성화 시킬 수
있습니다.
```javascript
process.noAsar = true;
fs.readFileSync('/path/to/example.asar');
```
## Node API의 한계
`asar` 아카이브를 Node API가 최대한 디렉터리 구조로 작동하도록 노력해왔지만 여전히

View file

@ -19,9 +19,9 @@
## node-inspector로 디버깅 하기
__참고:__ Electron은 node v0.11.13 버전을 사용합니다. 그리고 현재 node-inspector
유틸리티와 호환성 문제가 있습니다. 추가로 node-inspector 콘솔 내에서 메인 프로세스의
`process` 객체를 탐색할 경우 크래시가 발생할 수 있습니다.
__참고:__ Electron은 현재 node-inspector 유틸리티와 호환성 문제가 있습니다. 따라서
node-inspector 콘솔 내에서 메인 프로세스의 `process` 객체를 탐색할 경우 크래시가
발생할 수 있습니다.
### 1. [node-inspector][node-inspector] 서버 시작

View file

@ -4,6 +4,10 @@ Electron은 v0.34.0 버전부터 앱 패키지를 Mac App Store(MAS)에 제출
되었습니다. 이 가이드는 어플리케이션을 앱 스토어에 등록하는 방법과 빌드의 한계에 대한
설명을 제공합니다.
__참고:__ Mac App Store에 어플리케이션을 등록하려면
[Apple Developer Program][developer-program]에 등록되어 있어야 하며 비용이 발생할
수 있습니다.
## 앱 스토어에 어플리케이션을 등록하는 방법
다음 몇 가지 간단한 절차에 따라 앱 스토어에 어플리케이션을 등록하는 방법을 알아봅니다.
@ -109,6 +113,7 @@ productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RES
**역주:** [Mac 앱 배포 가이드 공식 문서](https://developer.apple.com/osx/distribution/kr/)
[developer-program]: https://developer.apple.com/support/compare-memberships/
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html
[nwjs-guide]: https://github.com/nwjs/nw.js/wiki/Mac-App-Store-%28MAS%29-Submission-Guideline#first-steps
[enable-app-sandbox]: https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html

View file

@ -40,8 +40,8 @@ selecione a *tag* que corresponde à sua versão.
### Módulos para o Processo Principal:
* [app](../../docs/api/app.md)
* [autoUpdater](../../docs/api/auto-updater.md)
* [app](api/app.md)
* [autoUpdater](api/auto-updater.md)
* [BrowserWindow](../../docs/api/browser-window.md)
* [contentTracing](../../docs/api/content-tracing.md)
* [dialog](../../docs/api/dialog.md)

View file

@ -1,7 +1,7 @@
# Acelerador (teclas de atalhos)
Um acelerador é uma string que representa um atalho de tecla. Isso pode conter
multiplos modificadores e códigos chaves, combinado pelo caracter `+`.
Um acelerador é uma string que representa um atalho de tecla. Ele pode conter
múltiplos modificadores e códigos chaves, combinados pelo caractere `+`.
Exemplos:
@ -11,13 +11,13 @@ Exemplos:
## Aviso sobre plataformas
No Linux e no Windows a tecla `Command` não tem nenhum efeito,
então use `CommandOrControl` que representa a tecla `Command` existente no OSX e
então use `CommandOrControl` que representa a tecla `Command` existente no OS X e
`Control` no Linux e no Windows para definir aceleradores (atalhos).
A chave `Super` está mapeada para a tecla `Windows` para Windows e Linux,
e para a tecla `Cmd` para OSX.
e para a tecla `Cmd` para OS X.
## Modificadores disponiveis
## Modificadores disponíveis
* `Command` (ou `Cmd` abreviado)
* `Control` (ou `Ctrl` abreviado)
@ -26,21 +26,21 @@ e para a tecla `Cmd` para OSX.
* `Shift`
* `Super`
## Códigos chaves disponiveis
## Códigos chaves disponíveis
* `0` to `9`
* `A` to `Z`
* `F1` to `F24`
* Punctuations like `~`, `!`, `@`, `#`, `$`, etc.
* `0` até `9`
* `A` até `Z`
* `F1` até `F24`
* Pontuações como `~`, `!`, `@`, `#`, `$`, etc.
* `Plus`
* `Space`
* `Backspace`
* `Delete`
* `Insert`
* `Return` (or `Enter` as alias)
* `Up`, `Down`, `Left` and `Right`
* `Home` and `End`
* `PageUp` and `PageDown`
* `Escape` (or `Esc` for short)
* `VolumeUp`, `VolumeDown` and `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
* `Return` (ou `Enter` como pseudônimo)
* `Up`, `Down`, `Left` e `Right`
* `Home` e `End`
* `PageUp` e `PageDown`
* `Escape` (ou `Esc` abreviado)
* `VolumeUp`, `VolumeDown` e `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` e `MediaPlayPause`

View file

@ -0,0 +1,85 @@
# autoUpdater
Este módulo oferece uma interface para o framework de atualização automática `Squirrel`.
## Avisos sobre Plataformas
Embora o `autoUpdater` ofereça uma API uniforme para diferentes plataformas, existem diferenças sutis em cada plataforma.
### OS X
No OS X, o módulo `autoUpdater` é construído sobre o [Squirrel.Mac][squirrel-mac], o que significa que você não precisa de nenhuma configuração especial para fazê-lo funcionar. Para requerimentos de servidor, você pode ler [Server Support][server-support].
### Windows
No Windows, você deve instalar seu aplicativo na máquina de um usuário antes que possa usar o auto-updater, então é recomendado utilizar o módulo [grunt-electron-installer][installer] para gerar um instalador do Windows.
O instalador gerado com Squirrel irá criar um ícone de atalho com um [Application User Model ID][app-user-model-id] no formato `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, por exemplo: `com.squirrel.slack.Slack` e `com.squirrel.code.Code`. Você precisa usar o mesmo ID para seu aplicativo a API `app.setAppUserModelId`, senão o Windows não conseguirá fixar seu aplicativo corretamente na barra de tarefas.
A configuração do servidor também é diferente do OS X. Você pode ler a documentação do [Squirrel.Windows][squirrel-windows] para mais detalhes.
### Linux
Não há suporte nativo do auto-updater para Linux, então é recomendado utilizar o gerenciador de pacotes da distribuição para atualizar seu aplicativo.
## Eventos
O objeto `autoUpdater` emite os seguintes eventos:
### Evento: 'error'
Retorna:
* `error` Error
Emitido quando há um erro durante a atualização.
### Evento: 'checking-for-update'
Emitido quando está verificando se uma atualização foi inicializada.
### Evento: 'update-available'
Emitido quando há uma atualização disponível. A autalização é baixada automaticamente.
### Evento: 'update-not-available'
Emitido quando não há uma atualização disponível.
### Evento: 'update-downloaded'
Retorna:
* `event` Event
* `releaseNotes` String
* `releaseName` String
* `releaseDate` Date
* `updateURL` String
Emitido quando uma atualização foi baixada.
No Windows apenas `releaseName` está disponível.
## Métodos
O objeto `autoUpdater` possui os seguintes métodos:
### `autoUpdater.setFeedURL(url)`
* `url` String
Define a `url` e inicializa o auto-updater. A `url` não pode ser alterada uma vez que foi definida.
### `autoUpdater.checkForUpdates()`
Pergunta ao servidor se há uma atualização. Você deve chamar `setFeedURL` antes de usar esta API.
### `autoUpdater.quitAndInstall()`
Reinicia o aplicativo e instala a atualização após esta ter sido baixada. Só deve ser chamado após o `update-downloaded` ter sido emitido.
[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac
[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
[installer]: https://github.com/atom/grunt-electron-installer
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx

View file

@ -1,22 +1,48 @@
# process
O objeto `process` no Electron tem as seguintes diferenças de um upstream node:
O objeto `process` no Electron tem as seguintes diferenças do objeto no upstream node:
* `process.type` String - Tipo de processo, pode ser `browser` (i.e. main process)
* `process.type` String - Tipo de processo, pode ser `browser` (processo principal)
ou `renderer`.
* `process.versions['electron']` String - Versão do Electron.
* `process.versions['chrome']` String - Versão do Chromium.
* `process.resourcesPath` String - Caminho para os códigos fontes JavaScript.
* `process.resourcesPath` String - Caminho para o código fonte JavaScript.
* `process.mas` Boolean - Para build da Mac App Store, este valor é `true`, para outros builds é `undefined`.
## Eventos
### Evento: 'loaded'
Emitido quando o Electron carregou seu script de inicialização interno e está começando a carregar a página web ou o script principal.
Pode ser utilizado pelo script pré-carregamento (preload.js abaixo) para adicionar símbolos globais do Node removidos para o escopo global quando a integração do node é desligada:
```js
// preload.js
var _setImmediate = setImmediate;
var _clearImmediate = clearImmediate;
process.once('loaded', function() {
global.setImmediate = _setImmediate;
global.clearImmediate = _clearImmediate;
});
```
## Propriedades
### `process.noAsar`
Definir isto para `true` pode desabilitar o suporte para arquivos `asar` nos módulos nativos do Node.
# Métodos
O objeto `process` tem os seguintes método:
O objeto `process` tem os seguintes métodos:
### `process.hang`
Afeta a thread principal do processo atual.
Faz com que o *thread* principal do processo congele.
## process.setFdLimit(MaxDescritores) _OS X_ _Linux_
### `process.setFdLimit(maxDescriptors)` _OS X_ _Linux_
* `maxDescriptors` Integer
Define o limite do arquivo descritor para `maxDescriptors` ou para o limite do OS,
o que for menor para o processo atual.
o que for menor para o processo atual.

View file

@ -1,11 +1,11 @@
# shell
O módulo `shell` fornece funções relacionadas intereções com o OS do usuário.
O módulo `shell` fornece funções relacionadas à integração com o desktop.
Um exemplo para abrir uma URL no browser padrão do usuário:
```javascript
var shell = require('shell');
const shell = require('shell');
shell.openExternal('https://github.com');
```
@ -17,26 +17,26 @@ O módulo `shell` tem os seguintes métodos:
* `fullPath` String
Exibe o arquivo no gerenciador de arquivos padrão do sistema. Se possivel, seleciona o arquivo automaticamente.
Exibe o arquivo num gerenciador de arquivos. Se possivel, seleciona o arquivo.
### `shell.openItem(fullPath)`
* `fullPath` String
Abre o arquivo em seu programa padrão.
Abre o arquivo de maneira padrão do desktop.
### `shell.openExternal(url)`
* `url` String
Abre o arquivo seguido de um protocol em seu programa padrão. (Por
exemplo, mailto:foo@bar.com.)
Abre a URL de protocolo externo de maneira padrão do desktop. (Por
exemplo, mailto: URLs no programa de email padrão do usuário)
### `shell.moveItemToTrash(fullPath)`
* `fullPath` String
Move o arquivo para a lixeira e retorna um boolean com o resultado da operação.
Move o arquivo para a lixeira e retorna um status boolean com o resultado da operação.
### `shell.beep()`

View file

@ -187,12 +187,16 @@ when the tray icon is clicked. Defaults to true.
Displays a tray balloon.
### `Tray.popUpContextMenu([position])` _OS X_ _Windows_
### `Tray.popUpContextMenu([menu, position])` _OS X_ _Windows_
* `position` Object (optional)- The pop up position.
* `menu` Menu (optional)
* `position` Object (optional) - The pop up position.
* `x` Integer
* `y` Integer
Popups the context menu of tray icon. When `menu` is passed, the `menu` will
showed instead of the tray's context menu.
The `position` is only available on Windows, and it is (0, 0) by default.
### `Tray.setContextMenu(menu)`

View file

@ -19,7 +19,7 @@ Like `--debug` but pauses the script on the first line.
## Use node-inspector for Debugging
__Note:__ Electron uses node v0.11.13, which currently doesn't work very well
__Note:__ Electron doesn't currently work very well
with node-inspector, and the main process will crash if you inspect the
`process` object under node-inspector's console.

View file

@ -424,6 +424,8 @@ describe 'asar package', ->
assert.equal internalModuleReadFile(p).toString().trim(), 'a'
describe 'process.noAsar', ->
errorName = if process.platform is 'win32' then 'ENOENT' else 'ENOTDIR'
beforeEach ->
process.noAsar = true
afterEach ->
@ -432,22 +434,22 @@ describe 'asar package', ->
it 'disables asar support in sync API', ->
file = path.join fixtures, 'asar', 'a.asar', 'file1'
dir = path.join fixtures, 'asar', 'a.asar', 'dir1'
assert.throws (-> fs.readFileSync file), /ENOTDIR/
assert.throws (-> fs.lstatSync file), /ENOTDIR/
assert.throws (-> fs.realpathSync file), /ENOTDIR/
assert.throws (-> fs.readdirSync dir), /ENOTDIR/
assert.throws (-> fs.readFileSync file), new RegExp(errorName)
assert.throws (-> fs.lstatSync file), new RegExp(errorName)
assert.throws (-> fs.realpathSync file), new RegExp(errorName)
assert.throws (-> fs.readdirSync dir), new RegExp(errorName)
it 'disables asar support in async API', (done) ->
file = path.join fixtures, 'asar', 'a.asar', 'file1'
dir = path.join fixtures, 'asar', 'a.asar', 'dir1'
fs.readFile file, (error) ->
assert.equal error.code, 'ENOTDIR'
assert.equal error.code, errorName
fs.lstat file, (error) ->
assert.equal error.code, 'ENOTDIR'
assert.equal error.code, errorName
fs.realpath file, (error) ->
assert.equal error.code, 'ENOTDIR'
assert.equal error.code, errorName
fs.readdir dir, (error) ->
assert.equal error.code, 'ENOTDIR'
assert.equal error.code, errorName
done()
it 'treats *.asar as normal file', ->