Merge remote-tracking branch 'refs/remotes/atom/master'
This commit is contained in:
commit
4a2bfa0b06
42 changed files with 388 additions and 340 deletions
24
CODE_OF_CONDUCT.md
Normal file
24
CODE_OF_CONDUCT.md
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
||||
|
||||
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
- The use of sexualized language or imagery
|
||||
- Personal attacks
|
||||
- Trolling or insulting/derogatory comments
|
||||
- Public or private harassment
|
||||
- Publishing other's private information, such as physical or electronic addresses, without explicit permission
|
||||
- Other unethical or unprofessional conduct
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting a project maintainer at [atom@github.com](mailto:atom@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. Maintainers are obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
|
||||
This Code of Conduct is adapted from the Contributor Covenant, version 1.3.0, available from http://contributor-covenant.org/version/1/3/0/
|
|
@ -2,8 +2,9 @@
|
|||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable behavior to atom@github.com.
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to atom@github.com.
|
||||
|
||||
The following is a set of guidelines for contributing to Electron.
|
||||
These are just guidelines, not rules, use your best judgment and feel free to
|
||||
|
|
|
@ -16,9 +16,7 @@ Cross-Platform 데스크톱 어플리케이션을 개발할 수 있도록 해주
|
|||
Electron에 대한 중요한 알림을 받고 싶다면 Twitter에서
|
||||
[@ElectronJS](https://twitter.com/electronjs)를 팔로우 하세요.
|
||||
|
||||
이 프로젝트는 [기여자 규약 1.2](http://contributor-covenant.org/version/1/2/0/)을
|
||||
준수합니다. 따라서 이 프로젝트의 개발에 참여하려면 이 계약을 지켜야 합니다. 받아들일 수
|
||||
없는 행위를 발견했을 경우 atom@github.com로 보고 하십시오.
|
||||
[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)
|
||||
|
||||
## 다운로드
|
||||
|
||||
|
|
|
@ -14,9 +14,9 @@ editor](https://github.com/atom/atom).
|
|||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0/).
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to atom@github.com.
|
||||
This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to atom@github.com.
|
||||
|
||||
## Downloads
|
||||
|
||||
|
@ -67,6 +67,7 @@ locations:
|
|||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
- [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)*
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -23,9 +23,6 @@ GlobalShortcut::GlobalShortcut() {
|
|||
}
|
||||
|
||||
GlobalShortcut::~GlobalShortcut() {
|
||||
}
|
||||
|
||||
void GlobalShortcut::Destroy() {
|
||||
UnregisterAll();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -19,9 +19,6 @@ PowerMonitor::PowerMonitor() {
|
|||
}
|
||||
|
||||
PowerMonitor::~PowerMonitor() {
|
||||
}
|
||||
|
||||
void PowerMonitor::Destroy() {
|
||||
base::PowerMonitor::Get()->RemoveObserver(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
@ -162,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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
@ -634,6 +627,15 @@ void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
|||
web_contents()->GetController().LoadURLWithParams(params);
|
||||
}
|
||||
|
||||
void WebContents::DownloadURL(const GURL& url) {
|
||||
auto browser_context = web_contents()->GetBrowserContext();
|
||||
auto download_manager =
|
||||
content::BrowserContext::GetDownloadManager(browser_context);
|
||||
|
||||
download_manager->DownloadUrl(
|
||||
content::DownloadUrlParameters::FromWebContents(web_contents(), url));
|
||||
}
|
||||
|
||||
GURL WebContents::GetURL() const {
|
||||
return web_contents()->GetURL();
|
||||
}
|
||||
|
@ -987,82 +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("_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 {
|
||||
|
|
|
@ -54,12 +54,10 @@ 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);
|
||||
void DownloadURL(const GURL& url);
|
||||
GURL GetURL() const;
|
||||
base::string16 GetTitle() const;
|
||||
bool IsLoading() const;
|
||||
|
@ -144,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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ frameToGuest = {}
|
|||
|
||||
# Copy attribute of |parent| to |child| if it is not defined in |child|.
|
||||
mergeOptions = (child, parent) ->
|
||||
for own key, value of parent when key not in child
|
||||
for own key, value of parent when key not in Object.keys child
|
||||
if typeof value is 'object'
|
||||
child[key] = mergeOptions {}, value
|
||||
else
|
||||
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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)... };
|
||||
|
|
|
@ -288,6 +288,7 @@ registerWebViewElement = ->
|
|||
'replace'
|
||||
'replaceMisspelling'
|
||||
'getId'
|
||||
'downloadURL'
|
||||
'inspectServiceWorker'
|
||||
'print'
|
||||
'printToPDF'
|
||||
|
|
|
@ -242,6 +242,13 @@ const options = {"extraHeaders" : "pragma: no-cache\n"}
|
|||
webContents.loadURL(url, options)
|
||||
```
|
||||
|
||||
### `webContents.downloadURL(url)`
|
||||
|
||||
* `url` URL
|
||||
|
||||
Initiates a download of the resource at `url` without navigating. The
|
||||
`will-download` event of `session` will be triggered.
|
||||
|
||||
### `webContents.getURL()`
|
||||
|
||||
Returns URL of the current web page.
|
||||
|
|
|
@ -164,6 +164,7 @@ The `webview` tag has the following methods:
|
|||
**Note:** The webview element must be loaded before using the methods.
|
||||
|
||||
**Example**
|
||||
|
||||
```javascript
|
||||
webview.addEventListener("dom-ready", function() {
|
||||
webview.openDevTools();
|
||||
|
|
|
@ -262,6 +262,7 @@ describe 'browser-window module', ->
|
|||
w.loadURL "file://#{fixtures}/pages/window-open.html"
|
||||
|
||||
it 'emits when link with target is called', (done) ->
|
||||
@timeout 10000
|
||||
w.webContents.once 'new-window', (e, url, frameName) ->
|
||||
e.preventDefault()
|
||||
assert.equal url, 'http://host/'
|
||||
|
|
|
@ -87,23 +87,43 @@ describe 'session module', ->
|
|||
res.end mockPDF
|
||||
downloadServer.close()
|
||||
|
||||
it 'can download successfully', (done) ->
|
||||
assertDownload = (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) ->
|
||||
assert.equal state, 'completed'
|
||||
assert.equal filename, 'mock.pdf'
|
||||
assert.equal url, "http://127.0.0.1:#{port}/"
|
||||
assert.equal mimeType, 'application/pdf'
|
||||
assert.equal receivedBytes, mockPDF.length
|
||||
assert.equal totalBytes, mockPDF.length
|
||||
assert.equal disposition, contentDisposition
|
||||
assert fs.existsSync downloadFilePath
|
||||
fs.unlinkSync downloadFilePath
|
||||
|
||||
it 'can download using BrowserWindow.loadURL', (done) ->
|
||||
downloadServer.listen 0, '127.0.0.1', ->
|
||||
{port} = downloadServer.address()
|
||||
ipcRenderer.sendSync 'set-download-option', false
|
||||
w.loadURL "#{url}:#{port}"
|
||||
ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) ->
|
||||
assert.equal state, 'completed'
|
||||
assert.equal filename, 'mock.pdf'
|
||||
assert.equal url, "http://127.0.0.1:#{port}/"
|
||||
assert.equal mimeType, 'application/pdf'
|
||||
assert.equal receivedBytes, mockPDF.length
|
||||
assert.equal totalBytes, mockPDF.length
|
||||
assert.equal disposition, contentDisposition
|
||||
assert fs.existsSync downloadFilePath
|
||||
fs.unlinkSync downloadFilePath
|
||||
assertDownload event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port
|
||||
done()
|
||||
|
||||
it 'can download using WebView.downloadURL', (done) ->
|
||||
downloadServer.listen 0, '127.0.0.1', ->
|
||||
{port} = downloadServer.address()
|
||||
ipcRenderer.sendSync 'set-download-option', false
|
||||
|
||||
webview = new WebView
|
||||
webview.src = "file://#{fixtures}/api/blank.html"
|
||||
webview.addEventListener 'did-finish-load', ->
|
||||
webview.downloadURL "#{url}:#{port}/"
|
||||
|
||||
ipcRenderer.once 'download-done', (event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) ->
|
||||
assertDownload event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port
|
||||
document.body.removeChild(webview)
|
||||
done()
|
||||
|
||||
document.body.appendChild webview
|
||||
|
||||
it 'can cancel download', (done) ->
|
||||
downloadServer.listen 0, '127.0.0.1', ->
|
||||
{port} = downloadServer.address()
|
||||
|
|
|
@ -75,13 +75,22 @@ describe 'chromium feature', ->
|
|||
|
||||
it 'inherit options of parent window', (done) ->
|
||||
listener = (event) ->
|
||||
size = remote.getCurrentWindow().getSize()
|
||||
assert.equal event.data, "size: #{size.width} #{size.height}"
|
||||
[width, height] = remote.getCurrentWindow().getSize()
|
||||
assert.equal event.data, "size: #{width} #{height}"
|
||||
b.close()
|
||||
done()
|
||||
window.addEventListener 'message', listener
|
||||
b = window.open "file://#{fixtures}/pages/window-open-size.html", '', 'show=no'
|
||||
|
||||
it 'does not override child options', (done) ->
|
||||
size = {width: 350, height: 450}
|
||||
listener = (event) ->
|
||||
assert.equal event.data, "size: #{size.width} #{size.height}"
|
||||
b.close()
|
||||
done()
|
||||
window.addEventListener 'message', listener
|
||||
b = window.open "file://#{fixtures}/pages/window-open-size.html", '', "show=no,width=#{size.width},height=#{size.height}"
|
||||
|
||||
describe 'window.opener', ->
|
||||
@timeout 10000
|
||||
|
||||
|
|
2
spec/fixtures/pages/window-open-size.html
vendored
2
spec/fixtures/pages/window-open-size.html
vendored
|
@ -2,7 +2,7 @@
|
|||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
var size = require('electron').remote.getCurrentWindow().getSize();
|
||||
window.opener.postMessage('size: ' + size.width + ' ' + size.height, '*')
|
||||
window.opener.postMessage('size: ' + size[0] + ' ' + size[1], '*')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
2
vendor/native_mate
vendored
2
vendor/native_mate
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 93984941005bab194a2d47aff655d525c064efcb
|
||||
Subproject commit e859228db163c27410fb200c2df0715478fdf0d7
|
Loading…
Reference in a new issue