commit
fd9eadd1fa
55 changed files with 779 additions and 192 deletions
2
atom.gyp
2
atom.gyp
|
@ -4,7 +4,7 @@
|
||||||
'product_name%': 'Electron',
|
'product_name%': 'Electron',
|
||||||
'company_name%': 'GitHub, Inc',
|
'company_name%': 'GitHub, Inc',
|
||||||
'company_abbr%': 'github',
|
'company_abbr%': 'github',
|
||||||
'version%': '0.33.1',
|
'version%': '0.33.3',
|
||||||
},
|
},
|
||||||
'includes': [
|
'includes': [
|
||||||
'filenames.gypi',
|
'filenames.gypi',
|
||||||
|
|
201
atom/browser/api/atom_api_download_item.cc
Normal file
201
atom/browser/api/atom_api_download_item.cc
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/api/atom_api_download_item.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||||
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
|
#include "atom/common/node_includes.h"
|
||||||
|
#include "base/memory/linked_ptr.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "native_mate/dictionary.h"
|
||||||
|
#include "net/base/filename_util.h"
|
||||||
|
|
||||||
|
namespace mate {
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct Converter<content::DownloadItem::DownloadState> {
|
||||||
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
|
content::DownloadItem::DownloadState state) {
|
||||||
|
std::string download_state;
|
||||||
|
switch (state) {
|
||||||
|
case content::DownloadItem::COMPLETE:
|
||||||
|
download_state = "completed";
|
||||||
|
break;
|
||||||
|
case content::DownloadItem::CANCELLED:
|
||||||
|
download_state = "cancelled";
|
||||||
|
break;
|
||||||
|
case content::DownloadItem::INTERRUPTED:
|
||||||
|
download_state = "interrupted";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ConvertToV8(isolate, download_state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mate
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// The wrapDownloadItem funtion which is implemented in JavaScript
|
||||||
|
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
|
||||||
|
WrapDownloadItemCallback g_wrap_download_item;
|
||||||
|
|
||||||
|
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
|
||||||
|
|
||||||
|
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) :
|
||||||
|
path_(path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
const base::FilePath& DownloadItem::SavePathData::path() {
|
||||||
|
return path_;
|
||||||
|
}
|
||||||
|
|
||||||
|
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
|
||||||
|
download_item_(download_item) {
|
||||||
|
download_item_->AddObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
|
||||||
|
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) {
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 DownloadItem::GetReceivedBytes() {
|
||||||
|
return download_item_->GetReceivedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 DownloadItem::GetTotalBytes() {
|
||||||
|
return download_item_->GetTotalBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
const GURL& DownloadItem::GetUrl() {
|
||||||
|
return download_item_->GetURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DownloadItem::GetMimeType() {
|
||||||
|
return download_item_->GetMimeType();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DownloadItem::HasUserGesture() {
|
||||||
|
return download_item_->HasUserGesture();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DownloadItem::GetFilename() {
|
||||||
|
return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(),
|
||||||
|
GetContentDisposition(),
|
||||||
|
std::string(),
|
||||||
|
download_item_->GetSuggestedFilename(),
|
||||||
|
GetMimeType(),
|
||||||
|
std::string()).LossyDisplayName());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DownloadItem::GetContentDisposition() {
|
||||||
|
return download_item_->GetContentDisposition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::SetSavePath(const base::FilePath& path) {
|
||||||
|
download_item_->SetUserData(UserDataKey(), new SavePathData(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::Pause() {
|
||||||
|
download_item_->Pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::Resume() {
|
||||||
|
download_item_->Resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DownloadItem::Cancel() {
|
||||||
|
download_item_->Cancel(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder(
|
||||||
|
v8::Isolate* isolate) {
|
||||||
|
return mate::ObjectTemplateBuilder(isolate)
|
||||||
|
.SetMethod("pause", &DownloadItem::Pause)
|
||||||
|
.SetMethod("resume", &DownloadItem::Resume)
|
||||||
|
.SetMethod("cancel", &DownloadItem::Cancel)
|
||||||
|
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
|
||||||
|
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
|
||||||
|
.SetMethod("getUrl", &DownloadItem::GetUrl)
|
||||||
|
.SetMethod("getMimeType", &DownloadItem::GetMimeType)
|
||||||
|
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
|
||||||
|
.SetMethod("getFilename", &DownloadItem::GetFilename)
|
||||||
|
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
|
||||||
|
.SetMethod("setSavePath", &DownloadItem::SetSavePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) {
|
||||||
|
g_wrap_download_item = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearWrapDownloadItem() {
|
||||||
|
g_wrap_download_item.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
mate::Handle<DownloadItem> DownloadItem::Create(
|
||||||
|
v8::Isolate* isolate, content::DownloadItem* item) {
|
||||||
|
auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
|
||||||
|
g_wrap_download_item.Run(handle.ToV8());
|
||||||
|
g_download_item_objects[item->GetId()] = make_linked_ptr(
|
||||||
|
new v8::Global<v8::Value>(isolate, handle.ToV8()));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void* DownloadItem::UserDataKey() {
|
||||||
|
return &kDownloadItemSavePathKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace api
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void Initialize(v8::Local<v8::Object> exports, v8::Local<v8::Value> unused,
|
||||||
|
v8::Local<v8::Context> context, void* priv) {
|
||||||
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
|
mate::Dictionary dict(isolate, exports);
|
||||||
|
dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem);
|
||||||
|
dict.SetMethod("_clearWrapDownloadItem", &atom::api::ClearWrapDownloadItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize);
|
72
atom/browser/api/atom_api_download_item.h
Normal file
72
atom/browser/api/atom_api_download_item.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||||
|
#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/api/trackable_object.h"
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "content/public/browser/download_item.h"
|
||||||
|
#include "native_mate/handle.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
class DownloadItem : public mate::EventEmitter,
|
||||||
|
public content::DownloadItem::Observer {
|
||||||
|
public:
|
||||||
|
class SavePathData : public base::SupportsUserData::Data {
|
||||||
|
public:
|
||||||
|
explicit SavePathData(const base::FilePath& path);
|
||||||
|
const base::FilePath& path();
|
||||||
|
private:
|
||||||
|
base::FilePath path_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
|
||||||
|
content::DownloadItem* item);
|
||||||
|
static void* UserDataKey();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit DownloadItem(content::DownloadItem* download_item);
|
||||||
|
~DownloadItem();
|
||||||
|
|
||||||
|
// Override content::DownloadItem::Observer methods
|
||||||
|
void OnDownloadUpdated(content::DownloadItem* download) override;
|
||||||
|
void OnDownloadDestroyed(content::DownloadItem* download) override;
|
||||||
|
|
||||||
|
void Pause();
|
||||||
|
void Resume();
|
||||||
|
void Cancel();
|
||||||
|
int64 GetReceivedBytes();
|
||||||
|
int64 GetTotalBytes();
|
||||||
|
std::string GetMimeType();
|
||||||
|
bool HasUserGesture();
|
||||||
|
std::string GetFilename();
|
||||||
|
std::string GetContentDisposition();
|
||||||
|
const GURL& GetUrl();
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace api
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_
|
|
@ -8,6 +8,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "atom/browser/api/atom_api_cookies.h"
|
#include "atom/browser/api/atom_api_cookies.h"
|
||||||
|
#include "atom/browser/api/atom_api_download_item.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
#include "atom/common/native_mate_converters/callback.h"
|
#include "atom/common/native_mate_converters/callback.h"
|
||||||
|
@ -101,19 +102,6 @@ struct Converter<ClearStorageDataOptions> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
|
||||||
struct Converter<content::DownloadItem*> {
|
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
||||||
content::DownloadItem* val) {
|
|
||||||
mate::Dictionary dict(isolate, v8::Object::New(isolate));
|
|
||||||
dict.Set("url", val->GetURL());
|
|
||||||
dict.Set("filename", val->GetSuggestedFilename());
|
|
||||||
dict.Set("mimeType", val->GetMimeType());
|
|
||||||
dict.Set("hasUserGesture", val->HasUserGesture());
|
|
||||||
return dict.GetHandle();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mate
|
} // namespace mate
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
@ -245,11 +233,12 @@ Session::~Session() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
void Session::OnDownloadCreated(content::DownloadManager* manager,
|
||||||
content::DownloadItem* item) {
|
content::DownloadItem* item) {
|
||||||
auto web_contents = item->GetWebContents();
|
auto web_contents = item->GetWebContents();
|
||||||
bool prevent_default = Emit("will-download", item,
|
bool prevent_default = Emit(
|
||||||
api::WebContents::CreateFrom(isolate(),
|
"will-download",
|
||||||
web_contents));
|
DownloadItem::Create(isolate(), item),
|
||||||
|
api::WebContents::CreateFrom(isolate(), web_contents));
|
||||||
if (prevent_default) {
|
if (prevent_default) {
|
||||||
item->Cancel(true);
|
item->Cancel(true);
|
||||||
item->Remove();
|
item->Remove();
|
||||||
|
|
|
@ -2,6 +2,7 @@ EventEmitter = require('events').EventEmitter
|
||||||
|
|
||||||
bindings = process.atomBinding 'app'
|
bindings = process.atomBinding 'app'
|
||||||
sessionBindings = process.atomBinding 'session'
|
sessionBindings = process.atomBinding 'session'
|
||||||
|
downloadItemBindings = process.atomBinding 'download_item'
|
||||||
|
|
||||||
app = bindings.app
|
app = bindings.app
|
||||||
app.__proto__ = EventEmitter.prototype
|
app.__proto__ = EventEmitter.prototype
|
||||||
|
@ -10,6 +11,15 @@ wrapSession = (session) ->
|
||||||
# session is an Event Emitter.
|
# session is an Event Emitter.
|
||||||
session.__proto__ = EventEmitter.prototype
|
session.__proto__ = EventEmitter.prototype
|
||||||
|
|
||||||
|
wrapDownloadItem = (download_item) ->
|
||||||
|
# download_item is an Event Emitter.
|
||||||
|
download_item.__proto__ = EventEmitter.prototype
|
||||||
|
# Be compatible with old APIs.
|
||||||
|
download_item.url = download_item.getUrl()
|
||||||
|
download_item.filename = download_item.getFilename()
|
||||||
|
download_item.mimeType = download_item.getMimeType()
|
||||||
|
download_item.hasUserGesture = download_item.hasUserGesture()
|
||||||
|
|
||||||
app.setApplicationMenu = (menu) ->
|
app.setApplicationMenu = (menu) ->
|
||||||
require('menu').setApplicationMenu menu
|
require('menu').setApplicationMenu menu
|
||||||
|
|
||||||
|
@ -51,5 +61,8 @@ app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-wi
|
||||||
sessionBindings._setWrapSession wrapSession
|
sessionBindings._setWrapSession wrapSession
|
||||||
process.once 'exit', sessionBindings._clearWrapSession
|
process.once 'exit', sessionBindings._clearWrapSession
|
||||||
|
|
||||||
|
downloadItemBindings._setWrapDownloadItem wrapDownloadItem
|
||||||
|
process.once 'exit', downloadItemBindings._clearWrapDownloadItem
|
||||||
|
|
||||||
# Only one App object pemitted.
|
# Only one App object pemitted.
|
||||||
module.exports = app
|
module.exports = app
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "atom/browser/atom_browser_main_parts.h"
|
#include "atom/browser/atom_browser_main_parts.h"
|
||||||
#include "atom/browser/atom_download_manager_delegate.h"
|
#include "atom/browser/atom_download_manager_delegate.h"
|
||||||
|
#include "atom/browser/atom_ssl_config_service.h"
|
||||||
#include "atom/browser/browser.h"
|
#include "atom/browser/browser.h"
|
||||||
#include "atom/browser/net/atom_url_request_job_factory.h"
|
#include "atom/browser/net/atom_url_request_job_factory.h"
|
||||||
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
#include "atom/browser/net/asar/asar_protocol_handler.h"
|
||||||
|
@ -156,6 +157,10 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() {
|
||||||
return guest_manager_.get();
|
return guest_manager_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() {
|
||||||
|
return new AtomSSLConfigService;
|
||||||
|
}
|
||||||
|
|
||||||
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
|
||||||
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
|
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
|
||||||
base::FilePath());
|
base::FilePath());
|
||||||
|
|
|
@ -27,6 +27,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
|
||||||
content::URLRequestInterceptorScopedVector* interceptors) override;
|
content::URLRequestInterceptorScopedVector* interceptors) override;
|
||||||
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
|
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
|
||||||
const base::FilePath& base_path) override;
|
const base::FilePath& base_path) override;
|
||||||
|
net::SSLConfigService* CreateSSLConfigService() override;
|
||||||
|
|
||||||
// content::BrowserContext:
|
// content::BrowserContext:
|
||||||
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
|
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/api/atom_api_download_item.h"
|
||||||
#include "atom/browser/atom_browser_context.h"
|
#include "atom/browser/atom_browser_context.h"
|
||||||
#include "atom/browser/native_window.h"
|
#include "atom/browser/native_window.h"
|
||||||
#include "atom/browser/ui/file_dialog.h"
|
#include "atom/browser/ui/file_dialog.h"
|
||||||
|
@ -73,18 +74,19 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated(
|
||||||
if (relay)
|
if (relay)
|
||||||
window = relay->window.get();
|
window = relay->window.get();
|
||||||
|
|
||||||
file_dialog::Filters filters;
|
|
||||||
base::FilePath path;
|
base::FilePath path;
|
||||||
if (!file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
|
if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path,
|
||||||
filters, &path)) {
|
file_dialog::Filters(), &path)) {
|
||||||
return;
|
// Remember the last selected download directory.
|
||||||
|
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||||
|
download_manager_->GetBrowserContext());
|
||||||
|
browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
||||||
|
path.DirName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remeber the last selected download directory.
|
// Running the DownloadTargetCallback with an empty FilePath signals that the
|
||||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
// download should be cancelled.
|
||||||
download_manager_->GetBrowserContext());
|
// If user cancels the file save dialog, run the callback with empty FilePath.
|
||||||
browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
|
||||||
path.DirName());
|
|
||||||
callback.Run(path,
|
callback.Run(path,
|
||||||
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
content::DownloadItem::TARGET_DISPOSITION_PROMPT,
|
||||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
|
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path);
|
||||||
|
@ -100,6 +102,25 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
|
||||||
const content::DownloadTargetCallback& callback) {
|
const content::DownloadTargetCallback& callback) {
|
||||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||||
|
|
||||||
|
if (!download->GetForcedFilePath().empty()) {
|
||||||
|
callback.Run(download->GetForcedFilePath(),
|
||||||
|
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||||
|
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||||
|
download->GetForcedFilePath());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
base::SupportsUserData::Data* save_path = download->GetUserData(
|
||||||
|
atom::api::DownloadItem::UserDataKey());
|
||||||
|
if (save_path) {
|
||||||
|
const base::FilePath& default_download_path =
|
||||||
|
static_cast<api::DownloadItem::SavePathData*>(save_path)->path();
|
||||||
|
callback.Run(default_download_path,
|
||||||
|
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
||||||
|
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
||||||
|
default_download_path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(
|
||||||
download_manager_->GetBrowserContext());
|
download_manager_->GetBrowserContext());
|
||||||
base::FilePath default_download_path = browser_context->prefs()->GetFilePath(
|
base::FilePath default_download_path = browser_context->prefs()->GetFilePath(
|
||||||
|
@ -110,14 +131,6 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
|
||||||
default_download_path = path.Append(FILE_PATH_LITERAL("Downloads"));
|
default_download_path = path.Append(FILE_PATH_LITERAL("Downloads"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!download->GetForcedFilePath().empty()) {
|
|
||||||
callback.Run(download->GetForcedFilePath(),
|
|
||||||
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
|
|
||||||
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
|
|
||||||
download->GetForcedFilePath());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateDownloadPathCallback download_path_callback =
|
CreateDownloadPathCallback download_path_callback =
|
||||||
base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
|
base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated,
|
||||||
weak_ptr_factory_.GetWeakPtr(),
|
weak_ptr_factory_.GetWeakPtr(),
|
||||||
|
|
47
atom/browser/atom_ssl_config_service.cc
Normal file
47
atom/browser/atom_ssl_config_service.cc
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "atom/browser/atom_ssl_config_service.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "base/command_line.h"
|
||||||
|
#include "atom/common/options_switches.h"
|
||||||
|
#include "content/public/browser/browser_thread.h"
|
||||||
|
#include "net/socket/ssl_client_socket.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint16 GetSSLProtocolVersion(const std::string& version_string) {
|
||||||
|
uint16 version = 0; // Invalid
|
||||||
|
if (version_string == "tls1")
|
||||||
|
version = net::SSL_PROTOCOL_VERSION_TLS1;
|
||||||
|
else if (version_string == "tls1.1")
|
||||||
|
version = net::SSL_PROTOCOL_VERSION_TLS1_1;
|
||||||
|
else if (version_string == "tls1.2")
|
||||||
|
version = net::SSL_PROTOCOL_VERSION_TLS1_2;
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
AtomSSLConfigService::AtomSSLConfigService() {
|
||||||
|
auto cmd_line = base::CommandLine::ForCurrentProcess();
|
||||||
|
if (cmd_line->HasSwitch(switches::kSSLVersionFallbackMin)) {
|
||||||
|
auto version_string =
|
||||||
|
cmd_line->GetSwitchValueASCII(switches::kSSLVersionFallbackMin);
|
||||||
|
config_.version_fallback_min = GetSSLProtocolVersion(version_string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AtomSSLConfigService::~AtomSSLConfigService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void AtomSSLConfigService::GetSSLConfig(net::SSLConfig* config) {
|
||||||
|
*config = config_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace atom
|
28
atom/browser/atom_ssl_config_service.h
Normal file
28
atom/browser/atom_ssl_config_service.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
// Copyright (c) 2015 GitHub, Inc.
|
||||||
|
// Use of this source code is governed by the MIT license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
||||||
|
#define ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
||||||
|
|
||||||
|
#include "net/ssl/ssl_config_service.h"
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
class AtomSSLConfigService : public net::SSLConfigService {
|
||||||
|
public:
|
||||||
|
AtomSSLConfigService();
|
||||||
|
~AtomSSLConfigService() override;
|
||||||
|
|
||||||
|
// net::SSLConfigService:
|
||||||
|
void GetSSLConfig(net::SSLConfig* config) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
net::SSLConfig config_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(AtomSSLConfigService);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
|
#endif // ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_
|
|
@ -13,8 +13,8 @@ app.on('window-all-closed', function() {
|
||||||
|
|
||||||
// Parse command line options.
|
// Parse command line options.
|
||||||
var argv = process.argv.slice(1);
|
var argv = process.argv.slice(1);
|
||||||
var option = { file: null, help: null, version: null, webdriver: null };
|
var option = { file: null, help: null, version: null, webdriver: null, modules: [] };
|
||||||
for (var i in argv) {
|
for (var i = 0; i < argv.length; i++) {
|
||||||
if (argv[i] == '--version' || argv[i] == '-v') {
|
if (argv[i] == '--version' || argv[i] == '-v') {
|
||||||
option.version = true;
|
option.version = true;
|
||||||
break;
|
break;
|
||||||
|
@ -23,6 +23,9 @@ for (var i in argv) {
|
||||||
break;
|
break;
|
||||||
} else if (argv[i] == '--test-type=webdriver') {
|
} else if (argv[i] == '--test-type=webdriver') {
|
||||||
option.webdriver = true;
|
option.webdriver = true;
|
||||||
|
} else if (argv[i] == '--require' || argv[i] == '-r') {
|
||||||
|
option.modules.push(argv[++i]);
|
||||||
|
continue;
|
||||||
} else if (argv[i][0] == '-') {
|
} else if (argv[i][0] == '-') {
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
|
@ -212,6 +215,10 @@ app.once('ready', function() {
|
||||||
Menu.setApplicationMenu(menu);
|
Menu.setApplicationMenu(menu);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (option.modules.length > 0) {
|
||||||
|
require('module')._preloadModules(option.modules);
|
||||||
|
}
|
||||||
|
|
||||||
// Start the specified app if there is one specified in command line, otherwise
|
// Start the specified app if there is one specified in command line, otherwise
|
||||||
// start the default app.
|
// start the default app.
|
||||||
if (option.file && !option.webdriver) {
|
if (option.file && !option.webdriver) {
|
||||||
|
@ -253,6 +260,7 @@ if (option.file && !option.webdriver) {
|
||||||
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
|
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
|
||||||
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
|
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
|
||||||
helpMessage += "Options:\n";
|
helpMessage += "Options:\n";
|
||||||
|
helpMessage += " -r, --require Module to preload (option can be repeated)";
|
||||||
helpMessage += " -h, --help Print this usage message.\n";
|
helpMessage += " -h, --help Print this usage message.\n";
|
||||||
helpMessage += " -v, --version Print the version.";
|
helpMessage += " -v, --version Print the version.";
|
||||||
console.log(helpMessage);
|
console.log(helpMessage);
|
||||||
|
|
|
@ -68,6 +68,7 @@ NativeWindow::NativeWindow(
|
||||||
const mate::Dictionary& options)
|
const mate::Dictionary& options)
|
||||||
: content::WebContentsObserver(inspectable_web_contents->GetWebContents()),
|
: content::WebContentsObserver(inspectable_web_contents->GetWebContents()),
|
||||||
has_frame_(true),
|
has_frame_(true),
|
||||||
|
force_using_draggable_region_(false),
|
||||||
transparent_(false),
|
transparent_(false),
|
||||||
enable_larger_than_screen_(false),
|
enable_larger_than_screen_(false),
|
||||||
is_closed_(false),
|
is_closed_(false),
|
||||||
|
@ -159,8 +160,13 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
||||||
// Then show it.
|
// Then show it.
|
||||||
bool show = true;
|
bool show = true;
|
||||||
options.Get(switches::kShow, &show);
|
options.Get(switches::kShow, &show);
|
||||||
if (show)
|
if (show) {
|
||||||
Show();
|
Show();
|
||||||
|
} else {
|
||||||
|
// When RenderView is created it sets to visible, this is to prevent
|
||||||
|
// breaking the visibility API.
|
||||||
|
web_contents()->WasHidden();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindow::SetSize(const gfx::Size& size) {
|
void NativeWindow::SetSize(const gfx::Size& size) {
|
||||||
|
@ -468,7 +474,7 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) {
|
||||||
void NativeWindow::UpdateDraggableRegions(
|
void NativeWindow::UpdateDraggableRegions(
|
||||||
const std::vector<DraggableRegion>& regions) {
|
const std::vector<DraggableRegion>& regions) {
|
||||||
// Draggable region is not supported for non-frameless window.
|
// Draggable region is not supported for non-frameless window.
|
||||||
if (has_frame_)
|
if (has_frame_ && !force_using_draggable_region_)
|
||||||
return;
|
return;
|
||||||
draggable_region_ = DraggableRegionsToSkRegion(regions);
|
draggable_region_ = DraggableRegionsToSkRegion(regions);
|
||||||
}
|
}
|
||||||
|
|
|
@ -219,6 +219,13 @@ class NativeWindow : public content::WebContentsObserver,
|
||||||
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
|
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
|
||||||
gfx::ImageSkia icon() const { return icon_; }
|
gfx::ImageSkia icon() const { return icon_; }
|
||||||
|
|
||||||
|
bool force_using_draggable_region() const {
|
||||||
|
return force_using_draggable_region_;
|
||||||
|
}
|
||||||
|
void set_force_using_draggable_region(bool force) {
|
||||||
|
force_using_draggable_region_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
void set_has_dialog_attached(bool has_dialog_attached) {
|
void set_has_dialog_attached(bool has_dialog_attached) {
|
||||||
has_dialog_attached_ = has_dialog_attached;
|
has_dialog_attached_ = has_dialog_attached;
|
||||||
}
|
}
|
||||||
|
@ -257,6 +264,9 @@ class NativeWindow : public content::WebContentsObserver,
|
||||||
// Whether window has standard frame.
|
// Whether window has standard frame.
|
||||||
bool has_frame_;
|
bool has_frame_;
|
||||||
|
|
||||||
|
// Force the window to be aware of draggable regions.
|
||||||
|
bool force_using_draggable_region_;
|
||||||
|
|
||||||
// Whether window is transparent.
|
// Whether window is transparent.
|
||||||
bool transparent_;
|
bool transparent_;
|
||||||
|
|
||||||
|
|
|
@ -351,21 +351,19 @@ NativeWindowMac::NativeWindowMac(
|
||||||
bool useStandardWindow = true;
|
bool useStandardWindow = true;
|
||||||
options.Get(switches::kStandardWindow, &useStandardWindow);
|
options.Get(switches::kStandardWindow, &useStandardWindow);
|
||||||
|
|
||||||
|
// New title bar styles are available in Yosemite or newer
|
||||||
|
std::string titleBarStyle;
|
||||||
|
if (base::mac::IsOSYosemiteOrLater())
|
||||||
|
options.Get(switches::kTitleBarStyle, &titleBarStyle);
|
||||||
|
|
||||||
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
|
NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask |
|
||||||
NSMiniaturizableWindowMask | NSResizableWindowMask;
|
NSMiniaturizableWindowMask | NSResizableWindowMask;
|
||||||
if (!useStandardWindow || transparent() || !has_frame()) {
|
if (!useStandardWindow || transparent() || !has_frame()) {
|
||||||
styleMask |= NSTexturedBackgroundWindowMask;
|
styleMask |= NSTexturedBackgroundWindowMask;
|
||||||
}
|
}
|
||||||
|
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
||||||
std::string titleBarStyle = "default";
|
styleMask |= NSFullSizeContentViewWindowMask;
|
||||||
options.Get(switches::kTitleBarStyle, &titleBarStyle);
|
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
|
||||||
|
|
||||||
if (base::mac::IsOSYosemiteOrLater()) {
|
|
||||||
// New title bar styles are available in Yosemite or newer
|
|
||||||
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
|
||||||
styleMask |= NSFullSizeContentViewWindowMask;
|
|
||||||
styleMask |= NSUnifiedTitleAndToolbarWindowMask;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window_.reset([[AtomNSWindow alloc]
|
window_.reset([[AtomNSWindow alloc]
|
||||||
|
@ -393,18 +391,18 @@ NativeWindowMac::NativeWindowMac(
|
||||||
// We will manage window's lifetime ourselves.
|
// We will manage window's lifetime ourselves.
|
||||||
[window_ setReleasedWhenClosed:NO];
|
[window_ setReleasedWhenClosed:NO];
|
||||||
|
|
||||||
// Configure title bar look on Yosemite or newer
|
// Hide the title bar.
|
||||||
if (base::mac::IsOSYosemiteOrLater()) {
|
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
||||||
if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) {
|
[window_ setTitlebarAppearsTransparent:YES];
|
||||||
[window_ setTitlebarAppearsTransparent:YES];
|
[window_ setTitleVisibility:NSWindowTitleHidden];
|
||||||
[window_ setTitleVisibility:NSWindowTitleHidden];
|
if (titleBarStyle == "hidden-inset") {
|
||||||
if (titleBarStyle == "hidden-inset") {
|
base::scoped_nsobject<NSToolbar> toolbar(
|
||||||
NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"];
|
[[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
|
||||||
toolbar.showsBaselineSeparator = NO;
|
[toolbar setShowsBaselineSeparator:NO];
|
||||||
[window_ setToolbar:toolbar];
|
[window_ setToolbar:toolbar];
|
||||||
[toolbar release];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
// We should be aware of draggable regions when using hidden titlebar.
|
||||||
|
set_force_using_draggable_region(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// On OS X the initial window size doesn't include window frame.
|
// On OS X the initial window size doesn't include window frame.
|
||||||
|
@ -436,6 +434,11 @@ NativeWindowMac::NativeWindowMac(
|
||||||
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||||
|
|
||||||
InstallView();
|
InstallView();
|
||||||
|
|
||||||
|
// Install the DraggableRegionView if it is forced to use draggable regions
|
||||||
|
// for normal window.
|
||||||
|
if (has_frame() && force_using_draggable_region())
|
||||||
|
InstallDraggableRegionView();
|
||||||
}
|
}
|
||||||
|
|
||||||
NativeWindowMac::~NativeWindowMac() {
|
NativeWindowMac::~NativeWindowMac() {
|
||||||
|
@ -467,6 +470,8 @@ bool NativeWindowMac::IsFocused() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::Show() {
|
void NativeWindowMac::Show() {
|
||||||
|
web_contents()->WasShown();
|
||||||
|
|
||||||
// This method is supposed to put focus on window, however if the app does not
|
// This method is supposed to put focus on window, however if the app does not
|
||||||
// have focus then "makeKeyAndOrderFront" will only show the window.
|
// have focus then "makeKeyAndOrderFront" will only show the window.
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
|
@ -475,11 +480,13 @@ void NativeWindowMac::Show() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::ShowInactive() {
|
void NativeWindowMac::ShowInactive() {
|
||||||
|
web_contents()->WasShown();
|
||||||
[window_ orderFrontRegardless];
|
[window_ orderFrontRegardless];
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::Hide() {
|
void NativeWindowMac::Hide() {
|
||||||
[window_ orderOut:nil];
|
[window_ orderOut:nil];
|
||||||
|
web_contents()->WasHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeWindowMac::IsVisible() {
|
bool NativeWindowMac::IsVisible() {
|
||||||
|
|
|
@ -338,15 +338,18 @@ bool NativeWindowViews::IsFocused() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowViews::Show() {
|
void NativeWindowViews::Show() {
|
||||||
|
web_contents()->WasShown();
|
||||||
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowViews::ShowInactive() {
|
void NativeWindowViews::ShowInactive() {
|
||||||
|
web_contents()->WasShown();
|
||||||
window_->ShowInactive();
|
window_->ShowInactive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowViews::Hide() {
|
void NativeWindowViews::Hide() {
|
||||||
window_->Hide();
|
window_->Hide();
|
||||||
|
web_contents()->WasHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NativeWindowViews::IsVisible() {
|
bool NativeWindowViews::IsVisible() {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>atom.icns</string>
|
<string>atom.icns</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>0.33.1</string>
|
<string>0.33.3</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.8.0</string>
|
<string>10.8.0</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
|
|
|
@ -56,8 +56,8 @@ END
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,33,1,0
|
FILEVERSION 0,33,3,0
|
||||||
PRODUCTVERSION 0,33,1,0
|
PRODUCTVERSION 0,33,3,0
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -74,12 +74,12 @@ BEGIN
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "GitHub, Inc."
|
VALUE "CompanyName", "GitHub, Inc."
|
||||||
VALUE "FileDescription", "Electron"
|
VALUE "FileDescription", "Electron"
|
||||||
VALUE "FileVersion", "0.33.1"
|
VALUE "FileVersion", "0.33.3"
|
||||||
VALUE "InternalName", "electron.exe"
|
VALUE "InternalName", "electron.exe"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||||
VALUE "OriginalFilename", "electron.exe"
|
VALUE "OriginalFilename", "electron.exe"
|
||||||
VALUE "ProductName", "Electron"
|
VALUE "ProductName", "Electron"
|
||||||
VALUE "ProductVersion", "0.33.1"
|
VALUE "ProductVersion", "0.33.3"
|
||||||
VALUE "SquirrelAwareVersion", "1"
|
VALUE "SquirrelAwareVersion", "1"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
|
|
||||||
#include "atom/browser/ui/win/notify_icon.h"
|
#include "atom/browser/ui/win/notify_icon.h"
|
||||||
|
|
||||||
#include <shobjidl.h>
|
|
||||||
|
|
||||||
#include "atom/browser/ui/win/notify_icon_host.h"
|
#include "atom/browser/ui/win/notify_icon_host.h"
|
||||||
#include "base/md5.h"
|
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/win/windows_version.h"
|
#include "base/win/windows_version.h"
|
||||||
|
@ -28,31 +25,7 @@ NotifyIcon::NotifyIcon(NotifyIconHost* host,
|
||||||
icon_id_(id),
|
icon_id_(id),
|
||||||
window_(window),
|
window_(window),
|
||||||
message_id_(message),
|
message_id_(message),
|
||||||
menu_model_(NULL),
|
menu_model_(NULL) {
|
||||||
has_tray_app_id_hash_(false) {
|
|
||||||
// NB: If we have an App Model ID, we should propagate that to the tray.
|
|
||||||
// Doing this prevents duplicate items from showing up in the notification
|
|
||||||
// preferences (i.e. "Always Show / Show notifications only / etc")
|
|
||||||
PWSTR explicit_app_id;
|
|
||||||
if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&explicit_app_id))) {
|
|
||||||
// GUIDs and MD5 hashes are the same length. So convenient!
|
|
||||||
base::MD5Sum(explicit_app_id,
|
|
||||||
sizeof(wchar_t) * wcslen(explicit_app_id),
|
|
||||||
reinterpret_cast<base::MD5Digest*>(&tray_app_id_hash_));
|
|
||||||
|
|
||||||
// Set the GUID to version 4 as described in RFC 4122, section 4.4.
|
|
||||||
// The format of GUID version 4 must be like
|
|
||||||
// xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where y is one of [8, 9, A, B].
|
|
||||||
tray_app_id_hash_.Data3 &= 0x0fff;
|
|
||||||
tray_app_id_hash_.Data3 |= 0x4000;
|
|
||||||
|
|
||||||
// Set y to one of [8, 9, A, B].
|
|
||||||
tray_app_id_hash_.Data4[0] = 1;
|
|
||||||
|
|
||||||
has_tray_app_id_hash_ = true;
|
|
||||||
CoTaskMemFree(explicit_app_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
NOTIFYICONDATA icon_data;
|
NOTIFYICONDATA icon_data;
|
||||||
InitIconData(&icon_data);
|
InitIconData(&icon_data);
|
||||||
icon_data.uFlags |= NIF_MESSAGE;
|
icon_data.uFlags |= NIF_MESSAGE;
|
||||||
|
@ -81,10 +54,6 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos,
|
||||||
icon_id.uID = icon_id_;
|
icon_id.uID = icon_id_;
|
||||||
icon_id.hWnd = window_;
|
icon_id.hWnd = window_;
|
||||||
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
|
icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER);
|
||||||
if (has_tray_app_id_hash_)
|
|
||||||
memcpy(reinterpret_cast<void*>(&icon_id.guidItem),
|
|
||||||
&tray_app_id_hash_,
|
|
||||||
sizeof(GUID));
|
|
||||||
|
|
||||||
RECT rect = { 0 };
|
RECT rect = { 0 };
|
||||||
Shell_NotifyIconGetRect(&icon_id, &rect);
|
Shell_NotifyIconGetRect(&icon_id, &rect);
|
||||||
|
@ -202,13 +171,6 @@ void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) {
|
||||||
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
icon_data->cbSize = sizeof(NOTIFYICONDATA);
|
||||||
icon_data->hWnd = window_;
|
icon_data->hWnd = window_;
|
||||||
icon_data->uID = icon_id_;
|
icon_data->uID = icon_id_;
|
||||||
|
|
||||||
if (has_tray_app_id_hash_) {
|
|
||||||
icon_data->uFlags |= NIF_GUID;
|
|
||||||
memcpy(reinterpret_cast<void*>(&icon_data->guidItem),
|
|
||||||
&tray_app_id_hash_,
|
|
||||||
sizeof(GUID));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -79,10 +79,6 @@ class NotifyIcon : public TrayIcon {
|
||||||
// The context menu.
|
// The context menu.
|
||||||
ui::SimpleMenuModel* menu_model_;
|
ui::SimpleMenuModel* menu_model_;
|
||||||
|
|
||||||
// A hash of the app model ID
|
|
||||||
GUID tray_app_id_hash_;
|
|
||||||
bool has_tray_app_id_hash_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(NotifyIcon);
|
DISALLOW_COPY_AND_ASSIGN(NotifyIcon);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,14 @@ bool FillFileInfoWithNode(Archive::FileInfo* info,
|
||||||
Archive::Archive(const base::FilePath& path)
|
Archive::Archive(const base::FilePath& path)
|
||||||
: path_(path),
|
: path_(path),
|
||||||
file_(path_, base::File::FLAG_OPEN | base::File::FLAG_READ),
|
file_(path_, base::File::FLAG_OPEN | base::File::FLAG_READ),
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
fd_(_open_osfhandle(
|
||||||
|
reinterpret_cast<intptr_t>(file_.GetPlatformFile()), 0)),
|
||||||
|
#elif defined(OS_POSIX)
|
||||||
|
fd_(file_.GetPlatformFile()),
|
||||||
|
#else
|
||||||
|
fd_(-1),
|
||||||
|
#endif
|
||||||
header_size_(0) {
|
header_size_(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,17 +279,7 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Archive::GetFD() const {
|
int Archive::GetFD() const {
|
||||||
if (!file_.IsValid())
|
return fd_;
|
||||||
return -1;
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
return
|
|
||||||
_open_osfhandle(reinterpret_cast<intptr_t>(file_.GetPlatformFile()), 0);
|
|
||||||
#elif defined(OS_POSIX)
|
|
||||||
return file_.GetPlatformFile();
|
|
||||||
#else
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace asar
|
} // namespace asar
|
||||||
|
|
|
@ -69,6 +69,7 @@ class Archive {
|
||||||
private:
|
private:
|
||||||
base::FilePath path_;
|
base::FilePath path_;
|
||||||
base::File file_;
|
base::File file_;
|
||||||
|
int fd_;
|
||||||
uint32 header_size_;
|
uint32 header_size_;
|
||||||
scoped_ptr<base::DictionaryValue> header_;
|
scoped_ptr<base::DictionaryValue> header_;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
#define ATOM_MAJOR_VERSION 0
|
#define ATOM_MAJOR_VERSION 0
|
||||||
#define ATOM_MINOR_VERSION 33
|
#define ATOM_MINOR_VERSION 33
|
||||||
#define ATOM_PATCH_VERSION 1
|
#define ATOM_PATCH_VERSION 3
|
||||||
|
|
||||||
#define ATOM_VERSION_IS_RELEASE 1
|
#define ATOM_VERSION_IS_RELEASE 1
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ REFERENCE_MODULE(atom_browser_app);
|
||||||
REFERENCE_MODULE(atom_browser_auto_updater);
|
REFERENCE_MODULE(atom_browser_auto_updater);
|
||||||
REFERENCE_MODULE(atom_browser_content_tracing);
|
REFERENCE_MODULE(atom_browser_content_tracing);
|
||||||
REFERENCE_MODULE(atom_browser_dialog);
|
REFERENCE_MODULE(atom_browser_dialog);
|
||||||
|
REFERENCE_MODULE(atom_browser_download_item);
|
||||||
REFERENCE_MODULE(atom_browser_menu);
|
REFERENCE_MODULE(atom_browser_menu);
|
||||||
REFERENCE_MODULE(atom_browser_power_monitor);
|
REFERENCE_MODULE(atom_browser_power_monitor);
|
||||||
REFERENCE_MODULE(atom_browser_power_save_blocker);
|
REFERENCE_MODULE(atom_browser_power_save_blocker);
|
||||||
|
|
|
@ -113,6 +113,10 @@ const char kDisableHttpCache[] = "disable-http-cache";
|
||||||
// Register schemes to standard.
|
// Register schemes to standard.
|
||||||
const char kRegisterStandardSchemes[] = "register-standard-schemes";
|
const char kRegisterStandardSchemes[] = "register-standard-schemes";
|
||||||
|
|
||||||
|
// The minimum SSL/TLS version ("tls1", "tls1.1", or "tls1.2") that
|
||||||
|
// TLS fallback will accept.
|
||||||
|
const char kSSLVersionFallbackMin[] = "ssl-version-fallback-min";
|
||||||
|
|
||||||
// The browser process app model ID
|
// The browser process app model ID
|
||||||
const char kAppUserModelId[] = "app-user-model-id";
|
const char kAppUserModelId[] = "app-user-model-id";
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,7 @@ extern const char kPageVisibility[];
|
||||||
|
|
||||||
extern const char kDisableHttpCache[];
|
extern const char kDisableHttpCache[];
|
||||||
extern const char kRegisterStandardSchemes[];
|
extern const char kRegisterStandardSchemes[];
|
||||||
|
extern const char kSSLVersionFallbackMin[];
|
||||||
|
|
||||||
extern const char kAppUserModelId[];
|
extern const char kAppUserModelId[];
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* [`<webview>` 태그](api/web-view-tag.md)
|
* [`<webview>` 태그](api/web-view-tag.md)
|
||||||
* [`window.open` 함수](api/window-open.md)
|
* [`window.open` 함수](api/window-open.md)
|
||||||
|
|
||||||
### 메인 프로세스를 위한 모듈들:
|
### 메인 프로세스에서 사용할 수 있는 모듈:
|
||||||
|
|
||||||
* [app (0% 번역됨)](api/app.md)
|
* [app (0% 번역됨)](api/app.md)
|
||||||
* [auto-updater](api/auto-updater.md)
|
* [auto-updater](api/auto-updater.md)
|
||||||
|
@ -44,13 +44,13 @@
|
||||||
* [web-contents (0% 번역됨)](api/web-contents.md)
|
* [web-contents (0% 번역됨)](api/web-contents.md)
|
||||||
* [tray](api/tray.md)
|
* [tray](api/tray.md)
|
||||||
|
|
||||||
### 랜더러 프로세스를 위한 모듈들 (웹 페이지):
|
### 랜더러 프로세스에서 사용할 수 있는 모듈 (웹 페이지):
|
||||||
|
|
||||||
* [ipc (renderer)](api/ipc-renderer.md)
|
* [ipc (renderer)](api/ipc-renderer.md)
|
||||||
* [remote](api/remote.md)
|
* [remote](api/remote.md)
|
||||||
* [web-frame](api/web-frame.md)
|
* [web-frame](api/web-frame.md)
|
||||||
|
|
||||||
### 두 프로세스에서 모두 사용 가능한 모듈들:
|
### 두 프로세스 모두 사용할 수 있는 모듈:
|
||||||
|
|
||||||
* [clipboard](api/clipboard.md)
|
* [clipboard](api/clipboard.md)
|
||||||
* [crash-reporter](api/crash-reporter.md)
|
* [crash-reporter](api/crash-reporter.md)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# 크롬 Command-Line 스위치 지원
|
# 크롬 Command-Line 스위치 지원
|
||||||
|
|
||||||
다음 Command-Line 스위치들은 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다.
|
크롬 Command-Line 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다.
|
||||||
[app][app]의 [ready][ready]이벤트가 작동하기 전에 [app.commandLine.appendSwitch][append-switch] API를 사용하면
|
[app][app]의 [ready][ready]이벤트가 작동하기 전에 [app.commandLine.appendSwitch][append-switch] API를 사용하면
|
||||||
어플리케이션 내부에서 스위치들을 추가할 수 있습니다:
|
어플리케이션 내부에서 스위치들을 추가할 수 있습니다:
|
||||||
|
|
||||||
|
@ -80,7 +80,11 @@ Pepper 플래시 플러그인의 버전을 설정합니다.
|
||||||
|
|
||||||
## --log-net-log=`path`
|
## --log-net-log=`path`
|
||||||
|
|
||||||
Net log 이벤트를 지정한 `path`에 로그로 기록합니다.
|
Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다.
|
||||||
|
|
||||||
|
## --ssl-version-fallback-min=`version`
|
||||||
|
|
||||||
|
Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2")
|
||||||
|
|
||||||
## --v=`log_level`
|
## --v=`log_level`
|
||||||
|
|
||||||
|
@ -93,7 +97,7 @@ Net log 이벤트를 지정한 `path`에 로그로 기록합니다.
|
||||||
`--v` 옵션에 전달된 값을 덮어쓰고 모듈당 최대 V-logging 레벨을 지정합니다.
|
`--v` 옵션에 전달된 값을 덮어쓰고 모듈당 최대 V-logging 레벨을 지정합니다.
|
||||||
예를 들어 `my_module=2,foo*=3`는 `my_module.*`, `foo*.*`와 같은 파일 이름 패턴을 가진 모든 소스 코드들의 로깅 레벨을 각각 2와 3으로 설정합니다.
|
예를 들어 `my_module=2,foo*=3`는 `my_module.*`, `foo*.*`와 같은 파일 이름 패턴을 가진 모든 소스 코드들의 로깅 레벨을 각각 2와 3으로 설정합니다.
|
||||||
|
|
||||||
슬래시(`/`), 백슬래시(`\`)를 포함하는 모든 패턴은 모듈뿐만 아니라 모든 경로명에 대해서도 테스트 됩니다.
|
또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 합니다.
|
||||||
예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다.
|
예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다.
|
||||||
|
|
||||||
모든 크로미움과 관련된 로그를 비활성화하고 어플리케이션의 로그만 활성화 하려면 다음과 같이 코드를 작성하면 됩니다:
|
모든 크로미움과 관련된 로그를 비활성화하고 어플리케이션의 로그만 활성화 하려면 다음과 같이 코드를 작성하면 됩니다:
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다.
|
`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다.
|
||||||
|
|
||||||
**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다.
|
**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다.
|
||||||
밑의 예제와 같이 `atomScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다.
|
밑의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다.
|
||||||
|
|
||||||
다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다:
|
다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다:
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ var BrowserWindow = require('browser-window');
|
||||||
var mainWindow;
|
var mainWindow;
|
||||||
|
|
||||||
app.on('ready', function() {
|
app.on('ready', function() {
|
||||||
var atomScreen = require('screen');
|
var electronScreen = require('screen');
|
||||||
var size = atomScreen.getPrimaryDisplay().workAreaSize;
|
var size = electronScreen.getPrimaryDisplay().workAreaSize;
|
||||||
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -32,8 +32,8 @@ var BrowserWindow = require('browser-window');
|
||||||
var mainWindow;
|
var mainWindow;
|
||||||
|
|
||||||
app.on('ready', function() {
|
app.on('ready', function() {
|
||||||
var atomScreen = require('screen');
|
var electronScreen = require('screen');
|
||||||
var displays = atomScreen.getAllDisplays();
|
var displays = electronScreen.getAllDisplays();
|
||||||
var externalDisplay = null;
|
var externalDisplay = null;
|
||||||
for (var i in displays) {
|
for (var i in displays) {
|
||||||
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
||||||
|
|
|
@ -17,11 +17,7 @@ var session = win.webContents.session
|
||||||
### Event: 'will-download'
|
### Event: 'will-download'
|
||||||
|
|
||||||
* `event` Event
|
* `event` Event
|
||||||
* `item` Object
|
* `item` [DownloadItem](download-item.md)
|
||||||
* `url` String
|
|
||||||
* `filename` String
|
|
||||||
* `mimeType` String
|
|
||||||
* `hasUserGesture` Boolean
|
|
||||||
* `webContents` [WebContents](web-contents.md)
|
* `webContents` [WebContents](web-contents.md)
|
||||||
|
|
||||||
Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다.
|
Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다.
|
||||||
|
@ -31,7 +27,7 @@ Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이
|
||||||
```javascript
|
```javascript
|
||||||
session.on('will-download', function(event, item, webContents) {
|
session.on('will-download', function(event, item, webContents) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
require('request')(item.url, function(data) {
|
require('request')(item.getUrl(), function(data) {
|
||||||
require('fs').writeFileSync('/somewhere', data);
|
require('fs').writeFileSync('/somewhere', data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -135,6 +135,14 @@
|
||||||
즉. 작동중인 랜더러 프로세스의 세션은 변경할 수 없습니다.
|
즉. 작동중인 랜더러 프로세스의 세션은 변경할 수 없습니다.
|
||||||
이후 이 값을 바꾸려고 시도하면 DOM 예외를 발생시킵니다.
|
이후 이 값을 바꾸려고 시도하면 DOM 예외를 발생시킵니다.
|
||||||
|
|
||||||
|
### `allowpopups`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<webview src="https://www.github.com/" allowpopups></webview>
|
||||||
|
```
|
||||||
|
|
||||||
|
"on"으로 지정하면 페이지에서 새로운 창을 열 수 있도록 허용합니다.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
`webview` 태그는 다음과 같은 메서드를 가지고 있습니다:
|
`webview` 태그는 다음과 같은 메서드를 가지고 있습니다:
|
||||||
|
@ -467,8 +475,8 @@ Returns:
|
||||||
|
|
||||||
* `url` String
|
* `url` String
|
||||||
* `frameName` String
|
* `frameName` String
|
||||||
* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`,
|
* `disposition` String - `default`, `foreground-tab`, `background-tab`, `new-window`, `other`를 사용할 수 있습니다.
|
||||||
`new-window` and `other`
|
* `options` Object - 새로운 `BrowserWindow`를 만들 때 사용되어야 하는 옵션.
|
||||||
|
|
||||||
페이지가 새로운 브라우저 창을 생성할 때 발생하는 이벤트입니다.
|
페이지가 새로운 브라우저 창을 생성할 때 발생하는 이벤트입니다.
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
프록시 객체는 브라우저의 웹 페이지 창과 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
|
프록시 객체는 브라우저의 웹 페이지 창과 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다.
|
||||||
창의 모든 컨트롤 권한을 가지려면 `BrowserWindow`를 직접 생성해서 사용해야 합니다.
|
창의 모든 컨트롤 권한을 가지려면 `BrowserWindow`를 직접 생성해서 사용해야 합니다.
|
||||||
|
|
||||||
|
새롭게 생성된 `BrowserWindow`는 기본적으로 부모 창의 옵션을 상속합니다. 이 옵션을 변경하려면 새 창을 열 때 `features` 인자를 지정해야 합니다.
|
||||||
|
|
||||||
### `window.open(url[, frameName][, features])`
|
### `window.open(url[, frameName][, features])`
|
||||||
|
|
||||||
* `url` String
|
* `url` String
|
||||||
|
@ -14,6 +16,8 @@
|
||||||
|
|
||||||
`BrowserWindowProxy` 클래스의 객체를 반환하는 새로운 윈도우를 생성합니다.
|
`BrowserWindowProxy` 클래스의 객체를 반환하는 새로운 윈도우를 생성합니다.
|
||||||
|
|
||||||
|
`features` 문자열은 표준 브라우저의 포맷을 따르고 있지만, 각 기능은 `BrowserWindow`의 옵션이어야 합니다.
|
||||||
|
|
||||||
### `window.opener.postMessage(message, targetOrigin)`
|
### `window.opener.postMessage(message, targetOrigin)`
|
||||||
|
|
||||||
* `message` String
|
* `message` String
|
||||||
|
|
|
@ -111,6 +111,7 @@ app.on('ready', function() {
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
<title>헬로 월드!</title>
|
<title>헬로 월드!</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -29,7 +29,20 @@ npm install --save-dev electron-rebuild
|
||||||
node ./node_modules/.bin/electron-rebuild
|
node ./node_modules/.bin/electron-rebuild
|
||||||
```
|
```
|
||||||
|
|
||||||
### node-gyp을 이용한 방법
|
### `npm`을 이용한 방법
|
||||||
|
|
||||||
|
또한 `npm`을 통해 설치할 수도 있습니다.
|
||||||
|
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export npm_config_disturl=https://atom.io/download/atom-shell
|
||||||
|
export npm_config_target=0.33.1
|
||||||
|
export npm_config_arch=x64
|
||||||
|
export npm_config_runtime=electron
|
||||||
|
HOME=~/.electron-gyp npm install module-name
|
||||||
|
```
|
||||||
|
|
||||||
|
### `node-gyp`를 이용한 방법
|
||||||
|
|
||||||
Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다:
|
Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다:
|
||||||
|
|
||||||
|
@ -40,15 +53,3 @@ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=ht
|
||||||
|
|
||||||
`HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다.
|
`HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다.
|
||||||
`--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다.
|
`--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다.
|
||||||
|
|
||||||
### npm을 이용한 방법
|
|
||||||
|
|
||||||
또한 `npm`을 통해 설치할 수도 있습니다.
|
|
||||||
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export npm_config_disturl=https://atom.io/download/atom-shell
|
|
||||||
export npm_config_target=0.29.1
|
|
||||||
export npm_config_arch=x64
|
|
||||||
HOME=~/.electron-gyp npm install module-name
|
|
||||||
```
|
|
||||||
|
|
|
@ -665,7 +665,7 @@ Same as `webContents.loadUrl(url[, options])`.
|
||||||
|
|
||||||
Same as `webContents.reload`.
|
Same as `webContents.reload`.
|
||||||
|
|
||||||
### `win.setMenu(menu)` _OS X_
|
### `win.setMenu(menu)` _Linux_ _Windows_
|
||||||
|
|
||||||
* `menu` Menu
|
* `menu` Menu
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,11 @@ Sets the `version` of the pepper flash plugin.
|
||||||
|
|
||||||
Enables net log events to be saved and writes them to `path`.
|
Enables net log events to be saved and writes them to `path`.
|
||||||
|
|
||||||
|
## --ssl-version-fallback-min=`version`
|
||||||
|
|
||||||
|
Set the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS
|
||||||
|
fallback will accept.
|
||||||
|
|
||||||
## --v=`log_level`
|
## --v=`log_level`
|
||||||
|
|
||||||
Gives the default maximal active V-logging level; 0 is the default. Normally
|
Gives the default maximal active V-logging level; 0 is the default. Normally
|
||||||
|
|
101
docs/api/download-item.md
Normal file
101
docs/api/download-item.md
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
# DownloadItem
|
||||||
|
|
||||||
|
`DownloadItem` is an EventEmitter represents a download item in Electron. It
|
||||||
|
is used in `will-download` event of `Session` module, and allows users to
|
||||||
|
control the download item.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// In the main process.
|
||||||
|
win.webContents.session.on('will-download', function(event, item, webContents) {
|
||||||
|
// Set the save path, making Electron not to prompt a save dialog.
|
||||||
|
item.setSavePath('/tmp/save.pdf');
|
||||||
|
console.log(item.getMimeType());
|
||||||
|
console.log(item.getFilename());
|
||||||
|
console.log(item.getTotalBytes());
|
||||||
|
item.on('updated', function() {
|
||||||
|
console.log('Received bytes: ' + item.getReceivedBytes());
|
||||||
|
});
|
||||||
|
item.on('done', function(e, state) {
|
||||||
|
if (state == "completed") {
|
||||||
|
console.log("Download successfully");
|
||||||
|
} else {
|
||||||
|
console.log("Download is cancelled or interrupted that can't be resumed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
### Event: 'updated'
|
||||||
|
|
||||||
|
Emits when the `downloadItem` gets updated.
|
||||||
|
|
||||||
|
### Event: 'done'
|
||||||
|
|
||||||
|
* `event` Event
|
||||||
|
* `state` String
|
||||||
|
* `completed` - The download completed successfully.
|
||||||
|
* `cancelled` - The download has been cancelled.
|
||||||
|
* `interrupted` - An error broke the connection with the file server.
|
||||||
|
|
||||||
|
Emits when the download is in a terminal state. This includes a completed
|
||||||
|
download, a cancelled download(via `downloadItem.cancel()`), and interrupted
|
||||||
|
download that can't be resumed.
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
The `downloadItem` object has the following methods:
|
||||||
|
|
||||||
|
### `downloadItem.setSavePath(path)`
|
||||||
|
|
||||||
|
* `path` String - Set the save file path of the download item.
|
||||||
|
|
||||||
|
The API is only available in session's `will-download` callback function.
|
||||||
|
If user doesn't set the save path via the API, Electron will use the original
|
||||||
|
routine to determine the save path(Usually prompts a save dialog).
|
||||||
|
|
||||||
|
### `downloadItem.pause()`
|
||||||
|
|
||||||
|
Pauses the download.
|
||||||
|
|
||||||
|
### `downloadItem.resume()`
|
||||||
|
|
||||||
|
Resumes the download that has been paused.
|
||||||
|
|
||||||
|
### `downloadItem.cancel()`
|
||||||
|
|
||||||
|
Cancels the download operation.
|
||||||
|
|
||||||
|
### `downloadItem.getUrl()`
|
||||||
|
|
||||||
|
Returns a `String` represents the origin url where the item is downloaded from.
|
||||||
|
|
||||||
|
### `downloadItem.getMimeType()`
|
||||||
|
|
||||||
|
Returns a `String` represents the mime type.
|
||||||
|
|
||||||
|
### `downloadItem.hasUserGesture()`
|
||||||
|
|
||||||
|
Returns a `Boolean` indicates whether the download has user gesture.
|
||||||
|
|
||||||
|
### `downloadItem.getFilename()`
|
||||||
|
|
||||||
|
Returns a `String` represents the file name of the download item.
|
||||||
|
|
||||||
|
**Note:** The file name is not always the same as the actual one saved in local
|
||||||
|
disk. If user changes the file name in a prompted download saving dialog, the
|
||||||
|
actual name of saved file will be different.
|
||||||
|
|
||||||
|
### `downloadItem.getTotalBytes()`
|
||||||
|
|
||||||
|
Returns a `Integer` represents the total size in bytes of the download item.
|
||||||
|
If the size is unknown, it returns 0.
|
||||||
|
|
||||||
|
### `downloadItem.getReceivedBytes()`
|
||||||
|
|
||||||
|
Returns a `Integer` represents the received bytes of the download item.
|
||||||
|
|
||||||
|
### `downloadItem.getContentDisposition()`
|
||||||
|
|
||||||
|
Returns a `String` represents the Content-Disposition field from the response
|
||||||
|
header.
|
|
@ -8,7 +8,7 @@ position, etc. You should not use this module until the `ready` event of the
|
||||||
|
|
||||||
**Note:** In the renderer / DevTools, `window.screen` is a reserved
|
**Note:** In the renderer / DevTools, `window.screen` is a reserved
|
||||||
DOM property, so writing `var screen = require('screen')` will not work. In our
|
DOM property, so writing `var screen = require('screen')` will not work. In our
|
||||||
examples below, we use `atomScreen` as the variable name instead.
|
examples below, we use `electronScreen` as the variable name instead.
|
||||||
|
|
||||||
An example of creating a window that fills the whole screen:
|
An example of creating a window that fills the whole screen:
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ var BrowserWindow = require('browser-window');
|
||||||
var mainWindow;
|
var mainWindow;
|
||||||
|
|
||||||
app.on('ready', function() {
|
app.on('ready', function() {
|
||||||
var atomScreen = require('screen');
|
var electronScreen = require('screen');
|
||||||
var size = atomScreen.getPrimaryDisplay().workAreaSize;
|
var size = electronScreen.getPrimaryDisplay().workAreaSize;
|
||||||
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
@ -34,8 +34,8 @@ var BrowserWindow = require('browser-window');
|
||||||
var mainWindow;
|
var mainWindow;
|
||||||
|
|
||||||
app.on('ready', function() {
|
app.on('ready', function() {
|
||||||
var atomScreen = require('screen');
|
var electronScreen = require('screen');
|
||||||
var displays = atomScreen.getAllDisplays();
|
var displays = electronScreen.getAllDisplays();
|
||||||
var externalDisplay = null;
|
var externalDisplay = null;
|
||||||
for (var i in displays) {
|
for (var i in displays) {
|
||||||
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
||||||
|
|
|
@ -18,11 +18,7 @@ var session = win.webContents.session
|
||||||
### Event: 'will-download'
|
### Event: 'will-download'
|
||||||
|
|
||||||
* `event` Event
|
* `event` Event
|
||||||
* `item` Object
|
* `item` [DownloadItem](download-item.md)
|
||||||
* `url` String
|
|
||||||
* `filename` String
|
|
||||||
* `mimeType` String
|
|
||||||
* `hasUserGesture` Boolean
|
|
||||||
* `webContents` [WebContents](web-contents.md)
|
* `webContents` [WebContents](web-contents.md)
|
||||||
|
|
||||||
Fired when Electron is about to download `item` in `webContents`.
|
Fired when Electron is about to download `item` in `webContents`.
|
||||||
|
@ -32,7 +28,7 @@ Calling `event.preventDefault()` will cancel the download.
|
||||||
```javascript
|
```javascript
|
||||||
session.on('will-download', function(event, item, webContents) {
|
session.on('will-download', function(event, item, webContents) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
require('request')(item.url, function(data) {
|
require('request')(item.getUrl(), function(data) {
|
||||||
require('fs').writeFileSync('/somewhere', data);
|
require('fs').writeFileSync('/somewhere', data);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -124,6 +124,7 @@ Finally the `index.html` is the web page you want to show:
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
<title>Hello World!</title>
|
<title>Hello World!</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -34,6 +34,19 @@ npm install --save-dev electron-rebuild
|
||||||
node ./node_modules/.bin/electron-rebuild
|
node ./node_modules/.bin/electron-rebuild
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### The npm Way
|
||||||
|
|
||||||
|
You can also use `npm` to install modules. The steps are exactly the same with
|
||||||
|
Node modules, except that you need to setup some environment variables:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export npm_config_disturl=https://atom.io/download/atom-shell
|
||||||
|
export npm_config_target=0.33.1
|
||||||
|
export npm_config_arch=x64
|
||||||
|
export npm_config_runtime=electron
|
||||||
|
HOME=~/.electron-gyp npm install module-name
|
||||||
|
```
|
||||||
|
|
||||||
### The node-gyp Way
|
### The node-gyp Way
|
||||||
|
|
||||||
To build Node modules with headers of Electron, you need to tell `node-gyp`
|
To build Node modules with headers of Electron, you need to tell `node-gyp`
|
||||||
|
@ -48,15 +61,3 @@ The `HOME=~/.electron-gyp` changes where to find development headers. The
|
||||||
`--target=0.29.1` is version of Electron. The `--dist-url=...` specifies
|
`--target=0.29.1` is version of Electron. The `--dist-url=...` specifies
|
||||||
where to download the headers. The `--arch=x64` says the module is built for
|
where to download the headers. The `--arch=x64` says the module is built for
|
||||||
64bit system.
|
64bit system.
|
||||||
|
|
||||||
### The npm Way
|
|
||||||
|
|
||||||
You can also use `npm` to install modules. The steps are exactly the same with
|
|
||||||
Node modules, except that you need to setup some environment variables:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
export npm_config_disturl=https://atom.io/download/atom-shell
|
|
||||||
export npm_config_target=0.29.1
|
|
||||||
export npm_config_arch=x64
|
|
||||||
HOME=~/.electron-gyp npm install module-name
|
|
||||||
```
|
|
||||||
|
|
|
@ -71,6 +71,8 @@
|
||||||
'atom/browser/api/atom_api_content_tracing.cc',
|
'atom/browser/api/atom_api_content_tracing.cc',
|
||||||
'atom/browser/api/atom_api_cookies.cc',
|
'atom/browser/api/atom_api_cookies.cc',
|
||||||
'atom/browser/api/atom_api_cookies.h',
|
'atom/browser/api/atom_api_cookies.h',
|
||||||
|
'atom/browser/api/atom_api_download_item.cc',
|
||||||
|
'atom/browser/api/atom_api_download_item.h',
|
||||||
'atom/browser/api/atom_api_dialog.cc',
|
'atom/browser/api/atom_api_dialog.cc',
|
||||||
'atom/browser/api/atom_api_global_shortcut.cc',
|
'atom/browser/api/atom_api_global_shortcut.cc',
|
||||||
'atom/browser/api/atom_api_global_shortcut.h',
|
'atom/browser/api/atom_api_global_shortcut.h',
|
||||||
|
@ -129,6 +131,8 @@
|
||||||
'atom/browser/atom_quota_permission_context.h',
|
'atom/browser/atom_quota_permission_context.h',
|
||||||
'atom/browser/atom_speech_recognition_manager_delegate.cc',
|
'atom/browser/atom_speech_recognition_manager_delegate.cc',
|
||||||
'atom/browser/atom_speech_recognition_manager_delegate.h',
|
'atom/browser/atom_speech_recognition_manager_delegate.h',
|
||||||
|
'atom/browser/atom_ssl_config_service.cc',
|
||||||
|
'atom/browser/atom_ssl_config_service.h',
|
||||||
'atom/browser/bridge_task_runner.cc',
|
'atom/browser/bridge_task_runner.cc',
|
||||||
'atom/browser/bridge_task_runner.h',
|
'atom/browser/bridge_task_runner.h',
|
||||||
'atom/browser/browser.cc',
|
'atom/browser/browser.cc',
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "electron",
|
"name": "electron",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"asar": "0.8.x",
|
"asar": "^0.8.0",
|
||||||
"coffee-script": "^1.9.2",
|
"coffee-script": "^1.9.2",
|
||||||
"coffeelint": "^1.9.4",
|
"coffeelint": "^1.9.4",
|
||||||
"request": "*",
|
"request": "*",
|
||||||
"runas": "3.x"
|
"runas": "^3.0.0"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import sys
|
||||||
|
|
||||||
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
|
BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \
|
||||||
'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent'
|
'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent'
|
||||||
LIBCHROMIUMCONTENT_COMMIT = '8482fe555913dea3bde8a74f754524e2cfb02bc5'
|
LIBCHROMIUMCONTENT_COMMIT = '04523758cda2a96d2454f9056fb1fb9a1c1f95f1'
|
||||||
|
|
||||||
PLATFORM = {
|
PLATFORM = {
|
||||||
'cygwin': 'win32',
|
'cygwin': 'win32',
|
||||||
|
|
|
@ -8,7 +8,7 @@ from lib.config import get_target_arch
|
||||||
from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download
|
from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download
|
||||||
|
|
||||||
|
|
||||||
VERSION = 'v0.7.0'
|
VERSION = 'v0.8.0'
|
||||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||||
FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \
|
FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \
|
||||||
'/download/' + VERSION
|
'/download/' + VERSION
|
||||||
|
|
|
@ -294,16 +294,6 @@ describe 'browser-window module', ->
|
||||||
w.show()
|
w.show()
|
||||||
w.minimize()
|
w.minimize()
|
||||||
|
|
||||||
describe 'will-navigate event', ->
|
|
||||||
@timeout 10000
|
|
||||||
it 'emits when user starts a navigation', (done) ->
|
|
||||||
url = "file://#{fixtures}/pages/will-navigate.html"
|
|
||||||
w.webContents.on 'will-navigate', (event, u) ->
|
|
||||||
event.preventDefault()
|
|
||||||
assert.equal u, url
|
|
||||||
done()
|
|
||||||
w.loadUrl url
|
|
||||||
|
|
||||||
xdescribe 'beginFrameSubscription method', ->
|
xdescribe 'beginFrameSubscription method', ->
|
||||||
it 'subscribes frame updates', (done) ->
|
it 'subscribes frame updates', (done) ->
|
||||||
w.loadUrl "file://#{fixtures}/api/blank.html"
|
w.loadUrl "file://#{fixtures}/api/blank.html"
|
||||||
|
|
|
@ -2,6 +2,7 @@ assert = require 'assert'
|
||||||
remote = require 'remote'
|
remote = require 'remote'
|
||||||
http = require 'http'
|
http = require 'http'
|
||||||
path = require 'path'
|
path = require 'path'
|
||||||
|
fs = require 'fs'
|
||||||
app = remote.require 'app'
|
app = remote.require 'app'
|
||||||
BrowserWindow = remote.require 'browser-window'
|
BrowserWindow = remote.require 'browser-window'
|
||||||
|
|
||||||
|
@ -72,3 +73,51 @@ describe 'session module', ->
|
||||||
quotas: ['persistent'],
|
quotas: ['persistent'],
|
||||||
w.webContents.session.clearStorageData options, ->
|
w.webContents.session.clearStorageData options, ->
|
||||||
w.webContents.send 'getcount'
|
w.webContents.send 'getcount'
|
||||||
|
|
||||||
|
describe 'DownloadItem', ->
|
||||||
|
# A 5 MB mock pdf.
|
||||||
|
mockPDF = new Buffer 1024 * 1024 * 5
|
||||||
|
contentDisposition = 'inline; filename="mock.pdf"'
|
||||||
|
ipc = require 'ipc'
|
||||||
|
downloadFilePath = path.join fixtures, 'mock.pdf'
|
||||||
|
downloadServer = http.createServer (req, res) ->
|
||||||
|
res.writeHead 200, {
|
||||||
|
'Content-Length': mockPDF.length,
|
||||||
|
'Content-Type': 'application/pdf',
|
||||||
|
'Content-Disposition': contentDisposition
|
||||||
|
}
|
||||||
|
res.end mockPDF
|
||||||
|
downloadServer.close()
|
||||||
|
|
||||||
|
it 'can download successfully', (done) ->
|
||||||
|
downloadServer.listen 0, '127.0.0.1', ->
|
||||||
|
{port} = downloadServer.address()
|
||||||
|
ipc.sendSync 'set-download-option', false
|
||||||
|
w.loadUrl "#{url}:#{port}"
|
||||||
|
ipc.once 'download-done', (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
|
||||||
|
done()
|
||||||
|
|
||||||
|
it 'can cancel download', (done) ->
|
||||||
|
downloadServer.listen 0, '127.0.0.1', ->
|
||||||
|
{port} = downloadServer.address()
|
||||||
|
ipc.sendSync 'set-download-option', true
|
||||||
|
w.loadUrl "#{url}:#{port}/"
|
||||||
|
ipc.once 'download-done', (state, url, mimeType, receivedBytes,
|
||||||
|
totalBytes, disposition, filename) ->
|
||||||
|
assert.equal state, 'cancelled'
|
||||||
|
assert.equal filename, 'mock.pdf'
|
||||||
|
assert.equal mimeType, 'application/pdf'
|
||||||
|
assert.equal receivedBytes, 0
|
||||||
|
assert.equal totalBytes, mockPDF.length
|
||||||
|
assert.equal disposition, contentDisposition
|
||||||
|
done()
|
||||||
|
|
|
@ -8,6 +8,10 @@ describe 'asar package', ->
|
||||||
|
|
||||||
describe 'node api', ->
|
describe 'node api', ->
|
||||||
describe 'fs.readFileSync', ->
|
describe 'fs.readFileSync', ->
|
||||||
|
it 'does not leak fd', ->
|
||||||
|
for i in [1..10000]
|
||||||
|
fs.readFileSync(path.join(process.resourcesPath, 'atom.asar', 'renderer', 'api', 'lib', 'ipc.js'))
|
||||||
|
|
||||||
it 'reads a normal file', ->
|
it 'reads a normal file', ->
|
||||||
file1 = path.join fixtures, 'asar', 'a.asar', 'file1'
|
file1 = path.join fixtures, 'asar', 'a.asar', 'file1'
|
||||||
assert.equal fs.readFileSync(file1).toString().trim(), 'file1'
|
assert.equal fs.readFileSync(file1).toString().trim(), 'file1'
|
||||||
|
|
|
@ -23,6 +23,23 @@ describe 'chromium feature', ->
|
||||||
{port} = server.address()
|
{port} = server.address()
|
||||||
$.get "http://127.0.0.1:#{port}"
|
$.get "http://127.0.0.1:#{port}"
|
||||||
|
|
||||||
|
describe 'document.hidden', ->
|
||||||
|
BrowserWindow = remote.require 'browser-window'
|
||||||
|
ipc = remote.require 'ipc'
|
||||||
|
url = "file://#{fixtures}/pages/document-hidden.html"
|
||||||
|
w = null
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
w?.destroy()
|
||||||
|
ipc.removeAllListeners 'hidden'
|
||||||
|
|
||||||
|
it 'is set correctly when window is not shown', (done) ->
|
||||||
|
ipc.once 'hidden', (event, hidden) ->
|
||||||
|
assert hidden
|
||||||
|
done()
|
||||||
|
w = new BrowserWindow(show:false)
|
||||||
|
w.loadUrl url
|
||||||
|
|
||||||
describe 'navigator.webkitGetUserMedia', ->
|
describe 'navigator.webkitGetUserMedia', ->
|
||||||
it 'calls its callbacks', (done) ->
|
it 'calls its callbacks', (done) ->
|
||||||
@timeout 5000
|
@timeout 5000
|
||||||
|
|
7
spec/fixtures/pages/document-hidden.html
vendored
Normal file
7
spec/fixtures/pages/document-hidden.html
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
require('ipc').send('hidden', document.hidden);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -22,6 +22,12 @@ describe 'third-party module', ->
|
||||||
assert.equal msg, 'ok'
|
assert.equal msg, 'ok'
|
||||||
done()
|
done()
|
||||||
|
|
||||||
|
describe 'ffi', ->
|
||||||
|
it 'does not crash', ->
|
||||||
|
ffi = require 'ffi'
|
||||||
|
libm = ffi.Library('libm', ceil: [ 'double', [ 'double' ] ])
|
||||||
|
assert.equal libm.ceil(1.5), 2
|
||||||
|
|
||||||
describe 'q', ->
|
describe 'q', ->
|
||||||
Q = require 'q'
|
Q = require 'q'
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,7 @@ describe 'node feature', ->
|
||||||
|
|
||||||
describe 'contexts', ->
|
describe 'contexts', ->
|
||||||
describe 'setTimeout in fs callback', ->
|
describe 'setTimeout in fs callback', ->
|
||||||
|
return if process.env.TRAVIS is 'true'
|
||||||
it 'does not crash', (done) ->
|
it 'does not crash', (done) ->
|
||||||
fs.readFile __filename, ->
|
fs.readFile __filename, ->
|
||||||
setTimeout done, 0
|
setTimeout done, 0
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"basic-auth": "^1.0.0",
|
"basic-auth": "^1.0.0",
|
||||||
|
"ffi": "2.0.0",
|
||||||
"formidable": "1.0.16",
|
"formidable": "1.0.16",
|
||||||
"graceful-fs": "3.0.5",
|
"graceful-fs": "3.0.5",
|
||||||
"mocha": "2.1.0",
|
"mocha": "2.1.0",
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var app = require('app');
|
var app = require('app');
|
||||||
var ipc = require('ipc');
|
var ipc = require('ipc');
|
||||||
var dialog = require('dialog');
|
var dialog = require('dialog');
|
||||||
|
var path = require('path');
|
||||||
var BrowserWindow = require('browser-window');
|
var BrowserWindow = require('browser-window');
|
||||||
|
|
||||||
var window = null;
|
var window = null;
|
||||||
|
@ -73,4 +74,27 @@ app.on('ready', function() {
|
||||||
});
|
});
|
||||||
if (chosen == 0) window.destroy();
|
if (chosen == 0) window.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// For session's download test, listen 'will-download' event in browser, and
|
||||||
|
// reply the result to renderer for verifying
|
||||||
|
var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf');
|
||||||
|
require('ipc').on('set-download-option', function(event, need_cancel) {
|
||||||
|
window.webContents.session.once('will-download',
|
||||||
|
function(e, item, webContents) {
|
||||||
|
item.setSavePath(downloadFilePath);
|
||||||
|
item.on('done', function(e, state) {
|
||||||
|
window.webContents.send('download-done',
|
||||||
|
state,
|
||||||
|
item.getUrl(),
|
||||||
|
item.getMimeType(),
|
||||||
|
item.getReceivedBytes(),
|
||||||
|
item.getTotalBytes(),
|
||||||
|
item.getContentDisposition(),
|
||||||
|
item.getFilename());
|
||||||
|
});
|
||||||
|
if (need_cancel)
|
||||||
|
item.cancel();
|
||||||
|
});
|
||||||
|
event.returnValue = "done";
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
2
vendor/brightray
vendored
2
vendor/brightray
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit 25f3a9d0a5b73ec170a65f4e2e4c9ad91e23fc8c
|
Subproject commit 8e443520e695674fd26585cfa24a0ec0b6140c27
|
2
vendor/node
vendored
2
vendor/node
vendored
|
@ -1 +1 @@
|
||||||
Subproject commit fa54694af4350bf1720ff47e97a07c7c09325ee2
|
Subproject commit ac25693ad1d4c248e69a89147fd3995c3bf6c946
|
Loading…
Reference in a new issue