diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 000000000000..a78e30d8620b --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,2 @@ +* Electron version: +* Operating system: diff --git a/README-ko.md b/README-ko.md index 664075dd4816..b9085828d468 100644 --- a/README-ko.md +++ b/README-ko.md @@ -57,6 +57,7 @@ API 레퍼런스가 있습니다. Electron을 빌드 하는 방법과 프로젝 - [중국어 번체](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) - [우크라이나어](https://github.com/atom/electron/tree/master/docs-translations/uk-UA) - [러시아어](https://github.com/atom/electron/tree/master/docs-translations/ru-RU) +- [프랑스어](https://github.com/atom/electron/tree/master/docs-translations/fr-FR) ## 시작하기 diff --git a/README.md b/README.md index a7306ddabbb6..0080585b54cd 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,7 @@ contains documents describing how to build and contribute to Electron. - [Traditional Chinese](https://github.com/atom/electron/tree/master/docs-translations/zh-TW) - [Ukrainian](https://github.com/atom/electron/tree/master/docs-translations/uk-UA) - [Russian](https://github.com/atom/electron/tree/master/docs-translations/ru-RU) +- [French](https://github.com/atom/electron/tree/master/docs-translations/fr-FR) ## Quick Start @@ -70,6 +71,7 @@ forums - [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack - [`electron-br`](https://electron-br.slack.com) *(Brazilian Portuguese)* - [`electron-kr`](http://www.meetup.com/electron-kr/) *(Korean)* +- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(Japanese)* Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron) for a community maintained list of useful example apps, tools and resources. diff --git a/atom.gyp b/atom.gyp index dbaf6db56298..68a30cc637f3 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.36.7', + 'version%': '0.36.8', }, 'includes': [ 'filenames.gypi', @@ -144,6 +144,7 @@ }, { 'copied_libraries': [ '<(libchromiumcontent_dir)/pdf.dll', + '<(libchromiumcontent_dir)/ffmpeg.dll', ], }], ], @@ -193,6 +194,7 @@ }, { 'copied_libraries': [ '<(PRODUCT_DIR)/lib/libnode.so', + '<(libchromiumcontent_dir)/libffmpeg.so', ], }], ], @@ -461,6 +463,7 @@ }, { 'copied_libraries': [ '<(PRODUCT_DIR)/libnode.dylib', + '<(libchromiumcontent_dir)/libffmpeg.dylib', ], }], ], diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 80e5b606ef8d..4935adbc75ad 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -218,7 +218,8 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::WebContents(v8::Isolate* isolate, const mate::Dictionary& options) - : request_id_(0) { + : embedder_(nullptr), + request_id_(0) { // Whether it is a guest WebContents. bool is_guest = false; options.Get("isGuest", &is_guest); @@ -273,10 +274,10 @@ WebContents::WebContents(v8::Isolate* isolate, guest_delegate_->Initialize(this); NativeWindow* owner_window = nullptr; - WebContents* embedder = nullptr; - if (options.Get("embedder", &embedder) && embedder) { + if (options.Get("embedder", &embedder_) && embedder_) { // New WebContents's owner_window is the embedder's owner_window. - auto relay = NativeWindowRelay::FromWebContents(embedder->web_contents()); + auto relay = + NativeWindowRelay::FromWebContents(embedder_->web_contents()); if (relay) owner_window = relay->window.get(); } @@ -296,6 +297,7 @@ WebContents::~WebContents() { // The WebContentsDestroyed will not be called automatically because we // unsubscribe from webContents before destroying it. So we have to manually // call it here to make sure "destroyed" event is emitted. + RenderViewDeleted(web_contents()->GetRenderViewHost()); WebContentsDestroyed(); } } @@ -485,17 +487,7 @@ void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) { } void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) { - int process_id = render_view_host->GetProcess()->GetID(); - Emit("render-view-deleted", process_id); - - // process.emit('ATOM_BROWSER_RELEASE_RENDER_VIEW', processId); - // Tell the rpc server that a render view has been deleted and we need to - // release all objects owned by it. - v8::Locker locker(isolate()); - v8::HandleScope handle_scope(isolate()); - node::Environment* env = node::Environment::GetCurrent(isolate()); - mate::EmitEvent(isolate(), env->process_object(), - "ATOM_BROWSER_RELEASE_RENDER_VIEW", process_id); + Emit("render-view-deleted", render_view_host->GetProcess()->GetID()); } void WebContents::RenderProcessGone(base::TerminationStatus status) { @@ -675,9 +667,6 @@ bool WebContents::OnMessageReceived(const IPC::Message& message) { // be destroyed on close, and WebContentsDestroyed would be called for it, so // we need to make sure the api::WebContents is also deleted. void WebContents::WebContentsDestroyed() { - // The RenderViewDeleted was not called when the WebContents is destroyed. - RenderViewDeleted(web_contents()->GetRenderViewHost()); - // This event is only for internal use, which is emitted when WebContents is // being destroyed. Emit("will-destroy"); @@ -710,6 +699,14 @@ bool WebContents::Equal(const WebContents* web_contents) const { } void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) { + if (!url.is_valid()) { + Emit("did-fail-load", + static_cast(net::ERR_INVALID_URL), + net::ErrorToShortString(net::ERR_INVALID_URL), + url.possibly_invalid_spec()); + return; + } + content::NavigationController::LoadURLParams params(url); GURL http_referrer; @@ -1120,6 +1117,12 @@ v8::Local WebContents::Session(v8::Isolate* isolate) { return v8::Local::New(isolate, session_); } +content::WebContents* WebContents::HostWebContents() { + if (!embedder_) + return nullptr; + return embedder_->web_contents(); +} + v8::Local WebContents::DevToolsWebContents(v8::Isolate* isolate) { if (devtools_web_contents_.IsEmpty()) return v8::Null(isolate); @@ -1203,6 +1206,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate, .SetMethod("addWorkSpace", &WebContents::AddWorkSpace) .SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace) .SetProperty("session", &WebContents::Session) + .SetProperty("hostWebContents", &WebContents::HostWebContents) .SetProperty("devToolsWebContents", &WebContents::DevToolsWebContents) .SetProperty("debugger", &WebContents::Debugger); } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 63c4a0177716..b4f29090dbd3 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -147,6 +147,7 @@ class WebContents : public mate::TrackableObject, // Properties. v8::Local Session(v8::Isolate* isolate); + content::WebContents* HostWebContents(); v8::Local DevToolsWebContents(v8::Isolate* isolate); v8::Local Debugger(v8::Isolate* isolate); @@ -287,6 +288,9 @@ class WebContents : public mate::TrackableObject, scoped_ptr guest_delegate_; + // The host webcontents that may contain this webcontents. + WebContents* embedder_; + // The type of current WebContents. Type type_; diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index bcf6ccc5a335..ea1d95b79ca0 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -109,7 +109,7 @@ void TranslateOldOptions(v8::Isolate* isolate, v8::Local options) { // Converts binary data to Buffer. v8::Local ToBuffer(v8::Isolate* isolate, void* val, int size) { - auto buffer = node::Buffer::New(isolate, static_cast(val), size); + auto buffer = node::Buffer::Copy(isolate, static_cast(val), size); if (buffer.IsEmpty()) return v8::Null(isolate); else diff --git a/atom/browser/api/frame_subscriber.cc b/atom/browser/api/frame_subscriber.cc index 5b7241486b72..b2b049ce8b74 100644 --- a/atom/browser/api/frame_subscriber.cc +++ b/atom/browser/api/frame_subscriber.cc @@ -16,7 +16,7 @@ namespace api { FrameSubscriber::FrameSubscriber(v8::Isolate* isolate, const gfx::Size& size, const FrameCaptureCallback& callback) - : isolate_(isolate), size_(size), callback_(callback) { + : isolate_(isolate), size_(size), callback_(callback), weak_factory_(this) { } bool FrameSubscriber::ShouldCaptureFrame( @@ -28,7 +28,7 @@ bool FrameSubscriber::ShouldCaptureFrame( media::PIXEL_FORMAT_YV12, size_, gfx::Rect(size_), size_, base::TimeDelta()); *callback = base::Bind(&FrameSubscriber::OnFrameDelivered, - base::Unretained(this), *storage); + weak_factory_.GetWeakPtr(), *storage); return true; } diff --git a/atom/browser/api/frame_subscriber.h b/atom/browser/api/frame_subscriber.h index f7748aa5790d..089c4922d797 100644 --- a/atom/browser/api/frame_subscriber.h +++ b/atom/browser/api/frame_subscriber.h @@ -6,6 +6,7 @@ #define ATOM_BROWSER_API_FRAME_SUBSCRIBER_H_ #include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "content/public/browser/render_widget_host_view_frame_subscriber.h" #include "ui/gfx/geometry/size.h" #include "v8/include/v8.h" @@ -35,6 +36,8 @@ class FrameSubscriber : public content::RenderWidgetHostViewFrameSubscriber { gfx::Size size_; FrameCaptureCallback callback_; + base::WeakPtrFactory weak_factory_; + DISALLOW_COPY_AND_ASSIGN(FrameSubscriber); }; diff --git a/atom/browser/api/lib/session.js b/atom/browser/api/lib/session.js index dc65264349fa..8662759192dd 100644 --- a/atom/browser/api/lib/session.js +++ b/atom/browser/api/lib/session.js @@ -1,6 +1,6 @@ const EventEmitter = require('events').EventEmitter; const bindings = process.atomBinding('session'); -const PERSIST_PERFIX = 'persist:'; +const PERSIST_PREFIX = 'persist:'; // Returns the Session from |partition| string. exports.fromPartition = function(partition) { @@ -10,8 +10,8 @@ exports.fromPartition = function(partition) { if (partition === '') { return exports.defaultSession; } - if (partition.startsWith(PERSIST_PERFIX)) { - return bindings.fromPartition(partition.substr(PERSIST_PERFIX.length), false); + if (partition.startsWith(PERSIST_PREFIX)) { + return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false); } else { return bindings.fromPartition(partition, true); } diff --git a/atom/browser/atom_resource_dispatcher_host_delegate.cc b/atom/browser/atom_resource_dispatcher_host_delegate.cc index aaba1f31045b..4d969786c19a 100644 --- a/atom/browser/atom_resource_dispatcher_host_delegate.cc +++ b/atom/browser/atom_resource_dispatcher_host_delegate.cc @@ -26,7 +26,8 @@ bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol( bool has_user_gesture) { GURL escaped_url(net::EscapeExternalHandlerValue(url.spec())); BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, - base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url)); + base::Bind( + base::IgnoreResult(platform_util::OpenExternal), escaped_url, true)); return true; } diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index 2ec765d0d691..ebcca2a5d9a5 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -9,13 +9,15 @@ app.on('window-all-closed', function() { app.quit(); }); -app.on('ready', function() { - mainWindow = new BrowserWindow({ - width: 800, - height: 600, - autoHideMenuBar: true, - useContentSize: true, +exports.load = function(appUrl) { + app.on('ready', function() { + mainWindow = new BrowserWindow({ + width: 800, + height: 600, + autoHideMenuBar: true, + useContentSize: true, + }); + mainWindow.loadURL(appUrl); + mainWindow.focus(); }); - mainWindow.loadURL('file://' + __dirname + '/index.html'); - mainWindow.focus(); -}); +}; diff --git a/atom/browser/default_app/index.html b/atom/browser/default_app/index.html index ec16a38bc423..80c347eff6dd 100644 --- a/atom/browser/default_app/index.html +++ b/atom/browser/default_app/index.html @@ -3,31 +3,39 @@ Electron @@ -78,40 +91,47 @@

-

- To run your app with Electron, execute the following command under your - Console (or Terminal): -

+
- +

+ To run your app with Electron, execute the following command in your + Console (or Terminal): +

-

- The path-to-your-app should be the path to your own Electron - app, you can read the - - guide in Electron's - - on how to write one. -

+ -

- Or you can just drag your app here to run it: -

+

+ The path-to-your-app should be the path to your own Electron + app. +

+ +

You can read the + + guide in Electron's + + to learn how to write one. +

+ +

+ Or you can just drag your app here to run it: +

+ +
+ Drag your app here to run it +
-
- Drag your app here to run it
+ + +``` + +## `require('electron').xxx` is undefined. + +Lors de l'utilisation des modules d'Electron, vous pouvez avoir une erreur : + +``` +> require('electron').webFrame.setZoomFactor(1.0); +Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined +``` + +Ceci se produit quand vous avez le [module npm `electron`][electron-module] +d'installé, soit en local ou en global, ce qui a pour effet d'écraser les +modules de base d'Electron. + +Vous vérifiez que vous utilisez les bons modules, vous pouvez afficher le +chemin du module `electron` : + +```javascript +console.log(require.resolve('electron')); +``` + +et vérifier si il est de la forme : + +``` +"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" +``` + +S'il est de la forme `node_modules/electron/index.js`, vous devez supprimer le +module npm `electron`, ou le renommer. + +```bash +npm uninstall electron +npm uninstall -g electron +``` + +Si vous utilisez le module de base mais que vous continuez d'avoir +l'erreur, ça vient probablement du fait que vous utilisez le module dans le +mauvais processus. Par exemple `electron.app` peut uniquement être utilisé +dans le processus principal, tandis que `electron.webFrame` est uniquement +disponible dans le processus d'affichage. + +[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management +[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx +[electron-module]: https://www.npmjs.com/package/electron diff --git a/docs-translations/fr-FR/styleguide.md b/docs-translations/fr-FR/styleguide.md new file mode 100644 index 000000000000..5fe781773c12 --- /dev/null +++ b/docs-translations/fr-FR/styleguide.md @@ -0,0 +1,101 @@ +# Règles de style pour la documentation d'Electron + +Choisissez la section appropriée : [lire la documentation d'Electron](#reading-electron-documentation) +ou [écrire de la documentation pour Electron](#writing-electron-documentation). + +## Ecrire de la documentation pour Electron + +La documentation d'Electron a été écrite en suivant les règles ci-dessous : + +- Maximum un titre `h1` par page. +- Utilisation de `bash` au lieu de `cmd` dans les blocs de code (à cause de la + coloration syntaxique). +- Les titres `h1` devraient reprendre le nom de l'objet (i.e. `browser-window` → + `BrowserWindow`). + - Cependant, les traits d'union sont acceptés pour les noms de fichier. +- Pas de titre directement après un autre, ajoutez au minimum une ligne de + description entre les deux. +- Les entêtes des méthodes sont entre accents graves (backquotes) `code`. +- Les entêtes des évènements sont entre des apostrophes 'quotation'. +- Les listes ne doivent pas dépasser 2 niveaux (à cause du formattage du + markdown). +- Ajouter des titres de section: Evènements, Méthodes de classe, et Méthodes + d'instance. +- Utiliser 'will' au lieu de 'would' lors de la description du retour. +- Les évènements et méthodes sont des titres `h3`. +- Les arguments optionnels sont notés `function (required[, optional])`. +- Les arguments optionnels sont indiqués quand appelés dans la liste. +- La longueur des lignes ne dépasse pas 80 caractères. +- Les méthodes spécifiques à une plateforme sont notées en italique. + - ```### `method(foo, bar)` _OS X_``` +- Préférer 'in the ___ process' au lieu de 'on' + +### Traductions de la Documentation + +Les traductions de la documentation d'Electron sont dans le dossier +`docs-translations`. + +Pour ajouter une nouvelle langue (ou commencer) : + +- Créer un sous-dossier avec comme nom le code langage. +- A l'intérieur de ce dossier, dupliquer le dossier `docs`, en gardant le même + nom de dossiers et de fichiers. +- Traduire les fichiers. +- Mettre à jour le `README.md` à l'intérieur du dossier de langue en mettant les + liens vers les fichiers traduits. +- Ajouter un lien vers le nouveau dossier de langue dans le [README](https://github.com/atom/electron#documentation-translations) + principal d'Electron. + +## Lire la documentation d'Electron + +Quelques indications pour comprendre la syntaxe de la documentation d'Electron. + +### Méthodes + +Un exemple de la documentation d'une [méthode](https://developer.mozilla.org/en-US/docs/Glossary/Method) +(Anglais) + +--- + +`methodName(required[, optional]))` + +* `require` String (**required**) +* `optional` Integer + +--- + +Le nom de la méthode est suivi des arguments de celle-ci. Les arguments +optionnels sont notés entre crochets, avec une virgule si ceux-ci suivent un +autre argument. + +En-dessous de la méthode, chaque argument est détaillé avec son type. +Celui-ci peut être un type générique : +[`String`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String), +[`Number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number), +[`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object), +[`Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) +ou un type personnalisé comme le [`webContent`](api/web-content.md) d'Electron. + +### Evènements + +Un exemple d'une documentation d'un [évènement](https://developer.mozilla.org/en-US/docs/Web/API/Event) +(Anglais) +--- + +Event: 'wake-up' + +Returns: + +* `time` String + +--- + +L'évènement est une chaine utilisée après un listener `.on`. Si il retourne une +valeur, elle est écrite en dessous ainsi que son type. Si vous voulez écouter et +répondre à l'évènement wake-up, ça donne quelque chose comme : + +```javascript +Alarm.on('wake-up', function(time) { + console.log(time) +}) +``` diff --git a/docs-translations/jp/api/ipc-renderer.md b/docs-translations/jp/api/ipc-renderer.md index 5854157363f4..edbd862ffaa6 100644 --- a/docs-translations/jp/api/ipc-renderer.md +++ b/docs-translations/jp/api/ipc-renderer.md @@ -52,7 +52,7 @@ * `channel` String - イベント名 * `arg` (optional) -`channel`経由でメインプロセスに非同期にイベントを送信し、任意の引数を送信できます。 +`channel`経由でメインプロセスに同期的にイベントを送信し、任意の引数を送信できます。 メインプロセスは`ipcMain`で`channel`を受信することでハンドルし、 `event.returnValue`を設定してリプライします。 diff --git a/docs-translations/jp/faq/electron-faq.md b/docs-translations/jp/faq/electron-faq.md index c8a652277174..eef30c013a3f 100644 --- a/docs-translations/jp/faq/electron-faq.md +++ b/docs-translations/jp/faq/electron-faq.md @@ -12,6 +12,27 @@ Node.js の新しいバージョンがリリースされたとき、私たちは 通常、Node.js の新しい機能は V8 のアップグレードによってもたらされますが、Electron は Chrome ブラウザーに搭載されている V8 を使用しているので、新しい Node.js に入ったばかりのピカピカに新しい JavaScript 機能は Electron ではたいてい既に導入されています。 +## ウェブページ間のデータを共有する方法は? + +ウェブページ(レンダラープロセス)間のデータを共有するために最も単純な方法は、ブラウザで、すでに提供されているHTML5 APIを使用することです。もっとも良い方法は、[Storage API][storage]、[`localStorage`][local-storage]、[`sessionStorage`][session-storage]、[IndexedDB][indexed-db]です。 + +```javascript +// In the main process. +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// In page 1. +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// In page 2. +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + ## 何分か経つと、アプリの Window/tray が消えてしまいます これは、Window/trayを格納するのに使用している変数がガベージコレクトされたときに発生します。 @@ -104,3 +125,7 @@ npm uninstall -g electron [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs-translations/jp/tutorial/desktop-environment-integration.md b/docs-translations/jp/tutorial/desktop-environment-integration.md index 0ef44b2f47c7..96bf76d73709 100644 --- a/docs-translations/jp/tutorial/desktop-environment-integration.md +++ b/docs-translations/jp/tutorial/desktop-environment-integration.md @@ -210,6 +210,23 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## タスクバーでアイコンをオーバーレイする (Windows) + +Windowsで、タスクバーボタンはアプリケーションステータスを表示するために小さなオーバーレイを使うことができます。MSDNから引用します。 + +> アイコン オーバーレイは、状況に応じた状態通知として機能し、通知領域に状態アイコンを個別に表示する必要性をなくして、情報をユーザーに伝えることを目的としています。たとえば、現在、通知領域に表示される Microsoft Office Outlook の新着メールの通知は、タスク バー ボタンのオーバーレイとして表示できるようになります。ここでも、開発サイクルの間に、アプリケーションに最適な方法を決定する必要があります。アイコン オーバーレイは、重要で長期にわたる状態や通知 (ネットワークの状態、メッセンジャーの状態、新着メールなど) を提供することを目的としています。ユーザーに対して、絶えず変化するオーバーレイやアニメーションを表示しないようにしてください。 + +__タスクバーボタンでのオーバーレイ:__ + +![Overlay on taskbar button](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +ウィンドウでオーバーレイアイコンを設定するために、[BrowserWindow.setOverlayIcon][setoverlayicon] APIを使用できます。 + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## Windowのファイル表示 (OS X) OS Xでは、ウィンドウがrepresented fileを設定でき、タイトルバー上にファイルのアイコンを表示でき、タイトル上でCommand-クリックまたはControl-クリックをすると、パスがポップアップ表示されます。 @@ -228,15 +245,16 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [notification-spec]: https://developer.gnome.org/notification-spec/ diff --git a/docs-translations/jp/tutorial/quick-start.md b/docs-translations/jp/tutorial/quick-start.md index bfb6e2a51f76..4f2e5c9a52ef 100644 --- a/docs-translations/jp/tutorial/quick-start.md +++ b/docs-translations/jp/tutorial/quick-start.md @@ -24,6 +24,8 @@ Electron はウェブページを表示させるために Chromium を使用し Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするために [ipc](../api/ipc-renderer.md) モジュールを提供しています。またそれと、RPC 形式の通信を行う [remote](../api/remote.md) モジュールもあります。 +Electron では、メインプロセスとレンダラープロセスとのコミュニケーションをするには幾つかのほうほうがあります。メッセージを送信する[`ipcRenderer`](../api/ipc-renderer.md)モジュールと[`ipcMain`](../api/ipc-main.md)モジュールのように、RPC 形式の通信を行う[remote](../api/remote.md)モジュールです。[ウェブページ間のデータを共有する方法][share-data]にFAQエントリーがあります。 + ## Electronアプリを作成する 一般的に Electron アプリの構成は次のようになります: @@ -169,3 +171,5 @@ $ cd electron-quick-start # Install dependencies and run the app $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages diff --git a/docs-translations/jp/tutorial/using-selenium-and-webdriver.md b/docs-translations/jp/tutorial/using-selenium-and-webdriver.md index 3202028ebf5f..a1fd0f21d7f9 100644 --- a/docs-translations/jp/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/jp/tutorial/using-selenium-and-webdriver.md @@ -41,7 +41,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // Here is the path to your Electron binary. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') diff --git a/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md b/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md index 5cee7f26dc66..55f9d039f611 100644 --- a/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md +++ b/docs-translations/jp/tutorial/using-widevine-cdm-plugin.md @@ -6,6 +6,8 @@ Electronで、Chromeブラウザーに同梱される Widevine CDMプラグイ Electronは、ライセンス的な理由でWidevine CDMプラグインは同梱されません。Widevine CDMプラグインを取得するために、最初に、使用するElectronビルドのChromバージョンとアーキテクチャを合わせた公式のChromeブラウザーをインストールする必要があります。 +__Note:__ Chromeブラウザの主要バージョンは、Electronが使用するChromeバージョンと同じでなければなりません。そうでなければ、プラグインは、`navigator.plugins`経由でロードされて表示されるにも関わらず動作しません。 + ### Windows & OS X Chromeブラウザーで、`chrome://components/`を開き、 `WidevineCdm` を探し、それが最新であることを確認し、`APP_DATA/Google/Chrome/WidevineCDM/VERSION/_platform_specific/PLATFORM_ARCH/`ディレクトリからすべてのプラグインバイナリを探します。 diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index ec4cb74c253a..048026e0d599 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -92,7 +92,7 @@ Returns: 이 이벤트를 처리할 땐 반드시 `event.preventDefault()`를 호출해야 합니다. -Windows에선 `process.argv`를 통해 파일 경로를 얻을 수 있습니다. +Windows에선 `process.argv` (메인 프로세스에서)를 통해 파일 경로를 얻을 수 있습니다. ### Event: 'open-url' _OS X_ @@ -164,7 +164,7 @@ Returns: 기본 동작을 방지하고 인증을 승인할 수 있습니다. ```javascript -session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { +app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { // Verification logic. event.preventDefault(); @@ -523,7 +523,7 @@ dock 아이콘을 표시합니다. ### `app.dock.setMenu(menu)` _OS X_ -* `menu` Menu +* `menu` [Menu](menu.md) 어플리케이션의 [dock menu][dock-menu]를 설정합니다. diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index f79b201d0a1d..8bc4a1545fc4 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -451,7 +451,6 @@ var win = new BrowserWindow({ width: 800, height: 600 }); * `aspectRatio` 유지하려 하는 컨텐츠 뷰 일부의 종횡비 * `extraSize` Object (optional) - 종횡비를 유지하는 동안 포함되지 않을 엑스트라 크기. - 사용 가능한 속성: * `width` Integer * `height` Integer @@ -469,7 +468,7 @@ var win = new BrowserWindow({ width: 800, height: 600 }); ### `win.setBounds(options[, animate])` -* `options` Object, properties: +* `options` Object * `x` Integer * `y` Integer @@ -719,8 +718,7 @@ Windows 메시지 훅을 등록합니다. `callback`은 WndProc에서 메시지 ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional) - 캡쳐할 페이지의 영역. - 사용할 수 있는 속성은 다음과 같습니다: +* `rect` Object (optional) - 캡쳐할 페이지의 영역 * `x` Integer * `y` Integer * `width` Integer @@ -773,7 +771,7 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고 아이콘입니다. `null`로 지정하면 빈 오버레이가 사용됩니다 * `description` String - 접근성 설정에 의한 스크린 리더에 제공될 설명입니다 -현재 작업표시줄 아이콘에 16px 크기의 오버레이를 지정합니다. 보통 이 기능은 +현재 작업표시줄 아이콘에 16 x 16 픽셀 크기의 오버레이를 지정합니다. 보통 이 기능은 어플리케이션의 여러 상태를 사용자에게 소극적으로 알리기 위한 방법으로 사용됩니다. ### `win.setHasShadow(hasShadow)` _OS X_ @@ -790,34 +788,34 @@ Linux 플랫폼에선 Unity 데스크톱 환경만 지원합니다. 그리고 ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` - `button` 객체의 배열 - -`button` 객체는 다음과 같은 속성을 가지고 있습니다: - -* `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. -* `tooltip` String (optional) - 버튼의 툴팁 텍스트. -* `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 - 사용됩니다. 이 속성은 다음 문자열들을 포함할 수 있습니다: - * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. - * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 - 동작에 응답하지 않는 비활성화 상태로 표시됩니다. - * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 - 종료됩니다. - * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. - * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. - * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 - 눌려지지 않은 상태를 유지합니다. 이 값은 버튼을 알림의 용도로 사용하기 위해 - 만들어졌습니다. -* `click` - Function +* `buttons` - Array 윈도우 작업표시줄 버튼 레이아웃의 미리보기 이미지 영역에 미리보기 툴바와 버튼 세트를 -지정합니다. 반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. +추가합니다. 반환되는 `Boolean` 값은 미리보기 툴바가 성공적으로 추가됬는지를 알려줍니다. 미리보기 이미지 영역의 제한된 크기로 인해 미리보기 툴바에 추가될 수 있는 최대 버튼의 개수는 7개이며 이 이상 추가될 수 없습니다. 플랫폼의 제약으로 인해 미리보기 툴바는 한 번 설정되면 삭제할 수 없습니다. 하지만 이 API에 빈 배열을 전달하여 버튼들을 제거할 수 있습니다. +`buttons`는 `Button` 객체의 배열입니다: + +* `Button` 객체 + * `icon` [NativeImage](native-image.md) - 미리보기 툴바에 보여질 아이콘. + * `tooltip` String (optional) - 버튼의 툴팁 텍스트. + * `flags` Array (optional) - 버튼의 특정 동작 및 상태 제어. 기본적으로 `enabled`이 + 사용됩니다. 이 속성은 다음 문자열들을 포함할 수 있습니다: + * `enabled` - 사용자가 사용할 수 있도록 버튼이 활성화 됩니다. + * `disabled` - 버튼이 비활성화 됩니다. 버튼은 표시되지만 시각적인 상태는 사용자의 + 동작에 응답하지 않는 비활성화 상태로 표시됩니다. + * `dismissonclick` - 버튼이 클릭되면 작업표시줄 버튼의 미리보기(flyout)가 즉시 + 종료됩니다. + * `nobackground` - 버튼의 테두리를 표시하지 않습니다. 이미지에만 사용할 수 있습니다. + * `hidden` - 버튼을 사용자에게 표시되지 않도록 숨깁니다. + * `noninteractive` - 버튼은 활성화되어 있지만 반응이 제거되며 버튼을 눌러도 + 눌려지지 않은 상태를 유지합니다. 이 값은 버튼을 알림의 용도로 사용하기 위해 + 만들어졌습니다. + ### `win.showDefinitionForSelection()` _OS X_ 페이지의 선택된 단어에 대한 사전 검색 결과 팝업을 표시합니다. diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 2a0c98da2c09..df6475ad611b 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -62,6 +62,19 @@ console.log(clipboard.readText('selection')); 클립보드에 `image`를 씁니다. +### `clipboard.readRtf([type])` + +* `type` String (optional) + +클립보드로부터 RTF 형식으로 컨텐츠를 읽어옵니다. + +### `clipboard.writeRtf(text[, type])` + +* `text` String +* `type` String (optional) + +클립보드에 `text`를 RTF 형식으로 씁니다. + ### `clipboard.clear([type])` * `type` String (optional) diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index 0b7daba14dd0..81713760a856 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -22,19 +22,15 @@ crashReporter.start({ ### `crashReporter.start(options)` -* `options` Object, properties: - -* `productName` String, 기본값: Electron -* `companyName` String (**필수항목**) -* `submitURL` String, (**필수항목**) - * 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다. -* `autoSubmit` Boolean, 기본값: true - * true로 지정할 경우 유저의 승인 없이 자동으로 오류를 보고합니다. -* `ignoreSystemCrashHandler` Boolean, 기본값: false -* `extra` Object - * 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다. - * 문자열로 된 속성만 정상적으로 보내집니다. - * 중첩 객체는 지원되지 않습니다. (Nested objects are not supported) +* `options` Object + * `companyName` String + * `submitURL` String - 크래시 리포트는 POST 방식으로 이 URL로 전송됩니다. + * `productName` String (optional) - 기본값은 `Electron` 입니다. + * `autoSubmit` Boolean - 유저의 승인 없이 자동으로 오류를 보고합니다. 기본값은 + `true` 입니다. + * `ignoreSystemCrashHandler` Boolean - 기본값은 `false` 입니다. + * `extra` Object - 크래시 리포트 시 같이 보낼 추가 정보를 지정하는 객체입니다. + 문자열로 된 속성만 정상적으로 보내집니다. 중첩된 객체는 지원되지 않습니다. 다른 crashReporter API를 사용하기 전에 이 메서드를 먼저 호출해야 합니다. diff --git a/docs-translations/ko-KR/api/ipc-main.md b/docs-translations/ko-KR/api/ipc-main.md index 3ae519d294b6..30b10247f9dc 100644 --- a/docs-translations/ko-KR/api/ipc-main.md +++ b/docs-translations/ko-KR/api/ipc-main.md @@ -8,8 +8,7 @@ ## 메시지 전송 물론 메시지를 받는 것 말고도 메인 프로세스에서 랜더러 프로세스로 보내는 것도 가능합니다. -자세한 내용은 [webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-)를 -참고하세요. +자세한 내용은 [webContents.send][web-contents-send]를 참고하세요. * 메시지를 전송할 때 이벤트 이름은 `channel`이 됩니다. * 메시지에 동기로 응답할 땐 반드시 `event.returnValue`를 설정해야 합니다. @@ -46,34 +45,40 @@ ipcRenderer.send('asynchronous-message', 'ping'); `ipcMain`은 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -### `ipcMain.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - 이벤트 이름 -* `callback` Function +* `channel` String +* `listener` Function -이벤트가 발생하면 `event` 객체와 임의 메시지와 함께 `callback`이 호출됩니다. +`channel`에 대해 이벤트를 리스닝합니다. 새로운 메시지가 도착하면 `listener`가 +`listener(event, args...)` 형식으로 호출됩니다. -### `ipcMain.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - 이벤트의 이름 -* `callback` Function - `ipcMain.on(channel, callback)`에서 사용한 함수의 레퍼런스 +* `channel` String +* `listener` Function + +이벤트에 대해 한 번만 작동하는 `listener` 함수를 등록합니다. 이 `listener`는 등록된 +후 `channel`에 보내지는 메시지에 한해 호출됩니다. 호출된 이후엔 리스너가 삭제됩니다. + +### `ipcMain.removeListener(channel, listener)` + +* `channel` String +* `listener` Function 메시지 수신을 완료한 후, 더 이상의 콜백이 필요하지 않을 때 또는 몇 가지 이유로 채널의 메시지 전송을 멈출수 없을 때, 이 함수를 통해 지정한 채널에 대한 콜백을 삭제할 수 있습니다. +지정한 `channel`에 대한 리스너를 저장하는 배열에서 지정한 `listener`를 삭제합니다. + ### `ipcMain.removeAllListeners(channel)` -* `channel` String - 이벤트의 이름 +* `channel` String (optional) -이 ipc 채널에 등록된 *모든* 핸들러들을 삭제합니다. +이 ipc 채널에 등록된 모든 핸들러들을 삭제하거나 지정한 `channel`을 삭제합니다. -### `ipcMain.once(channel, callback)` - -`ipcMain.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. -`callback`이 한 번 호출된 이후 활성화되지 않습니다. - -## IPC Event +## Event 객체 `callback`에서 전달된 `event` 객체는 다음과 같은 메서드와 속성을 가지고 있습니다: @@ -85,5 +90,6 @@ ipcRenderer.send('asynchronous-message', 'ping'); 메시지를 보낸 `webContents` 객체를 반환합니다. `event.sender.send` 메서드를 통해 비동기로 메시지를 전달할 수 있습니다. 자세한 내용은 -[webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-)를 -참고하세요. +[webContents.send][web-contents-send]를 참고하세요. + +[web-contents-send]: web-contents.md#webcontentssendchannel-arg1-arg2- diff --git a/docs-translations/ko-KR/api/ipc-renderer.md b/docs-translations/ko-KR/api/ipc-renderer.md index aba632430b52..0d43b157d165 100644 --- a/docs-translations/ko-KR/api/ipc-renderer.md +++ b/docs-translations/ko-KR/api/ipc-renderer.md @@ -10,32 +10,38 @@ `ipcRenderer`는 다음과 같은 이벤트 리스닝 메서드를 가지고 있습니다: -### `ipcRenderer.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - 이벤트 이름 -* `callback` Function +* `channel` String +* `listener` Function -이벤트가 일어나면 `event` 객체와 임의의 인자와 함께 `callback` 함수가 호출됩니다. +`channel`에 대해 이벤트를 리스닝합니다. 새로운 메시지가 도착하면 `listener`가 +`listener(event, args...)` 형식으로 호출됩니다. -### `ipcMain.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - 이벤트의 이름 -* `callback` Function - `ipcMain.on(channel, callback)`에서 사용한 함수의 레퍼런스 +* `channel` String +* `listener` Function + +이벤트에 대해 한 번만 작동하는 `listener` 함수를 등록합니다. 이 `listener`는 등록된 +후 `channel`에 보내지는 메시지에 한해 호출됩니다. 호출된 이후엔 리스너가 삭제됩니다. + +### `ipcMain.removeListener(channel, listener)` + +* `channel` String +* `listener` Function 메시지 수신을 완료한 후, 더 이상의 콜백이 필요하지 않을 때 또는 몇 가지 이유로 채널의 메시지 전송을 멈출수 없을 때, 이 함수를 통해 지정한 채널에 대한 콜백을 삭제할 수 있습니다. +지정한 `channel`에 대한 리스너를 저장하는 배열에서 지정한 `listener`를 삭제합니다. + ### `ipcMain.removeAllListeners(channel)` -* `channel` String - 이벤트의 이름 +* `channel` String (optional) -이 ipc 채널에 등록된 *모든* 핸들러들을 삭제합니다. - -### `ipcMain.once(channel, callback)` - -`ipcMain.on()` 대신 이 함수를 사용할 경우 핸들러가 단 한 번만 호출됩니다. -`callback`이 한 번 호출된 이후 활성화되지 않습니다. +이 ipc 채널에 등록된 모든 핸들러들을 삭제하거나 지정한 `channel`을 삭제합니다. ## 메시지 보내기 @@ -43,23 +49,26 @@ ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `channel`을 통해 메인 프로세스에 비동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 -인자를 사용할 수도 있습니다. 메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 +인수를 사용할 수도 있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 +프로토타입 체인은 포함되지 않게 됩니다. + +메인 프로세스는 `ipcMain` 모듈의 `channel` 이벤트를 통해 이벤트를 리스닝 할 수 있습니다. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `channel`을 통해 메인 프로세스에 동기 메시지를 보냅니다. 그리고 필요에 따라 임의의 -인자를 사용할 수도 있습니다. 메인 프로세스는 `ipc`를 통해 `channel` 이벤트를 리스닝 -할 수 있습니다. +인자를 사용할 수도 있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 +프로토타입 체인은 포함되지 않게 됩니다. -메인 프로세스에선 `ipcMain` 모듈의 `channel` 이벤트를 통해 받은 +메인 프로세스는 `ipcMain` 모듈을 통해 `channel` 이벤트를 리스닝 할 수 있고, `event.returnValue`로 회신 할 수 있습니다. __참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일시 중단시킵니다. 사용 목적이 @@ -67,7 +76,7 @@ __참고:__ 동기 메서드는 모든 랜더러 프로세스의 작업을 일 ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` -* `channel` String - 이벤트 이름 +* `channel` String * `arg` (optional) `ipcRenderer.send`와 비슷하지만 이벤트를 메인 프로세스 대신 호스트 페이지내의 diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 59eceb05a7a3..5bb4867eda0e 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -59,7 +59,8 @@ var ses = session.fromPartition('persist:name'); Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다. -`event.preventDefault()` 메서드를 호출하면 다운로드를 취소합니다. +`event.preventDefault()` 메서드를 호출하면 다운로드를 취소하고, 프로세스의 다음 +틱부터 `item`을 사용할 수 없게 됩니다. ```javascript session.defaultSession.on('will-download', function(event, item, webContents) { @@ -293,26 +294,32 @@ myWindow.webContents.session.setCertificateVerifyProc(function(hostname, cert, c * `handler` Function * `webContents` Object - [WebContents](web-contents.md) 권한을 요청. * `permission` String - 'media', 'geolocation', 'notifications', - 'midiSysex'의 나열. + 'midiSysex', 'pointerLock', 'fullscreen'의 나열. * `callback` Function - 권한 허용 및 거부. `session`의 권한 요청에 응답을 하는데 사용하는 핸들러를 설정합니다. -`callback('granted')`를 호출하면 권한 제공을 허용하고 `callback('denied')`를 +`callback(true)`를 호출하면 권한 제공을 허용하고 `callback(false)`를 호출하면 권한 제공을 거부합니다. ```javascript session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) { if (webContents.getURL() === host) { if (permission == "notifications") { - callback(); // 거부됨. + callback(false); // 거부됨. return; } } - callback('granted'); + callback(true); }); ``` +#### `ses.clearHostResolverCache([callback])` + +* `callback` Function (optional) - 작업이 완료되면 호출됩니다. + +호스트 리소버(resolver) 캐시를 지웁니다. + #### `ses.webRequest` `webRequest` API는 생명주기의 다양한 단계에 맞춰 요청 컨텐츠를 가로채거나 변경할 수 diff --git a/docs-translations/ko-KR/api/shell.md b/docs-translations/ko-KR/api/shell.md index 4183d3b2502d..c4831092f3cf 100644 --- a/docs-translations/ko-KR/api/shell.md +++ b/docs-translations/ko-KR/api/shell.md @@ -25,12 +25,16 @@ shell.openExternal('https://github.com'); 지정한 파일을 데스크톱 기본 프로그램으로 엽니다. -### `shell.openExternal(url)` +### `shell.openExternal(url[, options])` * `url` String +* `options` Object (optional) _OS X_ + * `activate` Boolean - `true`로 설정하면 어플리케이션을 바로 활성화 상태로 + 실행합니다. 기본값은 `true`입니다. 제공된 외부 프로토콜 URL을 기반으로 데스크톱의 기본 프로그램으로 엽니다. (예를 들어 -mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) +mailto: URL은 유저의 기본 이메일 에이전트로 URL을 엽니다.) 어플리케이션이 해당 URL을 +열 수 있을 때 `true`를 반환합니다. 아니라면 `false`를 반환합니다. 역주: 폴더는 'file:\\\\C:\\'와 같이 지정하여 열 수 있습니다. (Windows의 경우) diff --git a/docs-translations/ko-KR/api/tray.md b/docs-translations/ko-KR/api/tray.md index e182f6471e7a..d82b0a9d7e40 100644 --- a/docs-translations/ko-KR/api/tray.md +++ b/docs-translations/ko-KR/api/tray.md @@ -32,6 +32,13 @@ __플랫폼별 한계:__ 트레이 아이콘이 작동하도록 만들 수 있습니다. * 앱 알림 표시기는 컨텍스트 메뉴를 가지고 있을 때만 보입니다. * Linux에서 앱 표시기가 사용될 경우, `click` 이벤트는 무시됩니다. +* Linux에서 각각 개별 `MenuItem`의 변경을 적용하려면 `setContextMenu`를 다시 + 호출해야 합니다. 예를 들면: + +```javascript +contextMenu.items[2].checked = false; +appIcon.setContextMenu(contextMenu); +``` 이러한 이유로 Tray API가 모든 플랫폼에서 똑같이 작동하게 하고 싶다면 `click` 이벤트에 의존해선 안되며 언제나 컨텍스트 메뉴를 포함해야 합니다. diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 3f9a7daaaa76..6e41f31155ce 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -255,8 +255,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - 더 많은 응답이 따르는 경우를 표시합니다. - * `matches` Integer (Optional) - 일치하는 개수. - * `selectionArea` Object (Optional) - 첫 일치 부위의 좌표. + * `matches` Integer (optional) - 일치하는 개수. + * `selectionArea` Object (optional) - 첫 일치 부위의 좌표. [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) 요청의 결과를 사용할 수 있을 때 발생하는 이벤트입니다. @@ -307,7 +307,7 @@ Returns: ### `webContents.loadURL(url[, options])` * `url` URL -* `options` Object (optional), 속성들: +* `options` Object (optional) * `httpReferrer` String - HTTP 레퍼러 url. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. @@ -493,7 +493,7 @@ CSS 코드를 현재 웹 페이지에 삽입합니다. ### `webContents.findInPage(text[, options])` * `text` String - 찾을 컨텐츠, 반드시 공백이 아니여야 합니다. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - 앞에서부터 검색할지 뒤에서부터 검색할지 여부입니다. 기본값은 `true`입니다. * `findNext` Boolean - 작업을 계속 처리할지 첫 요청만 처리할지 여부입니다. 기본값은 @@ -546,11 +546,10 @@ ServiceWorker가 존재하면 모두 등록을 해제하고 JS Promise가 만족 ### `webContents.print([options])` -`options` Object (optional), properties: - -* `silent` Boolean - 사용자에게 프린트 설정을 묻지 않습니다. 기본값을 `false`입니다. -* `printBackground` Boolean - 웹 페이지의 배경 색과 이미지를 출력합니다. 기본값은 - `false`입니다. +`options` Object (optional) + * `silent` Boolean - 사용자에게 프린트 설정을 묻지 않습니다. 기본값을 `false`입니다. + * `printBackground` Boolean - 웹 페이지의 배경 색과 이미지를 출력합니다. 기본값은 + `false`입니다. 윈도우의 웹 페이지를 프린트합니다. `silent`가 `false`로 지정되어있을 땐, Electron이 시스템의 기본 프린터와 기본 프린터 설정을 가져옵니다. @@ -565,32 +564,23 @@ print기능을 사용하지 않는 경우 전체 바이너리 크기를 줄이 ### `webContents.printToPDF(options, callback)` -`options` Object, properties: - -* `marginsType` Integer - 사용할 마진의 종류를 지정합니다. - * 0 - default - * 1 - none - * 2 - minimum -* `pageSize` String - 생성되는 PDF의 페이지 크기를 지정합니다. - * `A5` - * `A4` - * `A3` - * `Legal` - * `Letter` - * `Tabloid` -* `printBackground` Boolean - CSS 배경을 프린트할지 여부를 정합니다. -* `printSelectionOnly` Boolean - 선택된 영역만 프린트할지 여부를 정합니다. -* `landscape` Boolean - landscape을 위해선 `true`를, portrait를 위해선 `false`를 - 사용합니다. - -`callback` Function - `function(error, data) {}` - -* `error` Error -* `data` Buffer - PDF 파일 내용. +* `options` Object + * `marginsType` Integer - 사용할 마진의 종류를 지정합니다. 0 부터 2 사이 값을 사용할 + 수 있고 각각 기본 마진, 마진 없음, 최소 마진입니다. + * `pageSize` String - 생성되는 PDF의 페이지 크기를 지정합니다. 값은 `A3`, `A4`, + `A5`, `Legal`, `Letter` 와 `Tabloid`가 사용될 수 있습니다. + * `printBackground` Boolean - CSS 배경을 프린트할지 여부를 정합니다. + * `printSelectionOnly` Boolean - 선택된 영역만 프린트할지 여부를 정합니다. + * `landscape` Boolean - landscape을 위해선 `true`를, portrait를 위해선 `false`를 + 사용합니다. +* `callback` Function - `function(error, data) {}` Chromium의 미리보기 프린팅 커스텀 설정을 이용하여 윈도우의 웹 페이지를 PDF로 프린트합니다. +`callback`은 작업이 완료되면 `callback(error, data)` 형식으로 호출됩니다. `data`는 +생성된 PDF 데이터를 담고있는 `Buffer`입니다. + 기본으로 비어있는 `options`은 다음과 같이 여겨지게 됩니다: ```javascript @@ -643,7 +633,7 @@ mainWindow.webContents.on('devtools-opened', function() { ### `webContents.openDevTools([options])` -* `options` Object (optional). Properties: +* `options` Object (optional) * `detach` Boolean - 새 창에서 개발자 도구를 엽니다. 개발자 도구를 엽니다. @@ -681,8 +671,11 @@ mainWindow.webContents.on('devtools-opened', function() { * `arg` (optional) `channel`을 통하여 렌더러 프로세스에 비동기 메시지를 보냅니다. 임의의 인수를 보낼수도 -있습니다. 렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리슨하여 메시지를 -처리할 수 있습니다. +있습니다. 인수들은 내부적으로 JSON 포맷으로 직렬화 되며, 이후 함수와 프로토타입 체인은 +포함되지 않게 됩니다. + +렌더러 프로세스는 `ipcRenderer` 모듈을 통하여 `channel`를 리스닝하여 메시지를 처리할 +수 있습니다. 메인 프로세스에서 렌더러 프로세스로 메시지를 보내는 예시 입니다: diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index bd07c883e061..30da9f253b45 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -178,7 +178,7 @@ webview.addEventListener("dom-ready", function() { ### `.loadURL(url[, options])` * `url` URL -* `options` Object (optional), 속성들: +* `options` Object (optional) * `httpReferrer` String - HTTP 레퍼러 url. * `userAgent` String - 요청을 시작한 유저 에이전트. * `extraHeaders` String - "\n"로 구분된 Extra 헤더들. @@ -370,7 +370,7 @@ Service worker에 대한 개발자 도구를 엽니다. ### `webContents.findInPage(text[, options])` * `text` String - 찾을 컨텐츠, 반드시 공백이 아니여야 합니다. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - 앞에서부터 검색할지 뒤에서부터 검색할지 여부입니다. 기본값은 `true`입니다. * `findNext` Boolean - 작업을 계속 처리할지 첫 요청만 처리할지 여부입니다. 기본값은 @@ -557,8 +557,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - 더 많은 응답이 따르는 경우를 표시합니다. - * `matches` Integer (Optional) - 일치하는 개수. - * `selectionArea` Object (Optional) - 첫 일치 부위의 좌표. + * `matches` Integer (optional) - 일치하는 개수. + * `selectionArea` Object (optional) - 첫 일치 부위의 좌표. [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) 요청의 결과를 사용할 수 있을 때 발생하는 이벤트입니다. diff --git a/docs-translations/ko-KR/faq/electron-faq.md b/docs-translations/ko-KR/faq/electron-faq.md index 0978dc00539b..ea9953fcd4cd 100644 --- a/docs-translations/ko-KR/faq/electron-faq.md +++ b/docs-translations/ko-KR/faq/electron-faq.md @@ -18,6 +18,34 @@ Node.js의 새로운 기능은 보통 V8 업그레이드에서 가져옵니다. 브라우저에 탑재된 V8을 사용하고 있습니다. 눈부신 새로운 Node.js 버전의 자바스크립트 기능은 보통 이미 Electron에 있습니다. +## 어떻게 웹 페이지 간에 데이터를 공유할 수 있나요? + +두 웹페이지 간에 (랜더러 프로세스) 데이터를 공유하려면 간단히 이미 모든 브라우저에서 +사용할 수 있는 HTML5 API들을 사용하면 됩니다. 가장 좋은 후보는 +[Storage API][storage], [`localStorage`][local-storage], +[`sessionStorage`][session-storage], 그리고 [IndexedDB][indexed-db]가 있습니다. + +또는 Electron에서만 사용할 수 있는 IPC 시스템을 사용하여 메인 프로세스의 global +변수에 데이터를 저장한 후 다음과 같이 랜더러 프로세스에서 `remote` 모듈을 사용하여 +접근할 수 있습니다: + +```javascript +// 메인 프로세스에서 +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// 첫 번째 페이지에서 +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// 두 번째 페이지에서 +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + ## 제작한 어플리케이션의 윈도우/트레이가 몇 분 후에나 나타납니다. 이러한 문제가 발생하는 이유는 보통 윈도우/트레이를 담은 변수에 가비지 컬렉션이 작동해서 @@ -119,3 +147,7 @@ npm uninstall -g electron [memory-management]: https://developer.mozilla.org/ko/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs-translations/ko-KR/tutorial/application-distribution.md b/docs-translations/ko-KR/tutorial/application-distribution.md index 635337574152..7072d7c4d952 100644 --- a/docs-translations/ko-KR/tutorial/application-distribution.md +++ b/docs-translations/ko-KR/tutorial/application-distribution.md @@ -59,9 +59,8 @@ electron/resources/ ### Windows -`electron.exe`을 원하는 이름으로 변경할 수 있습니다. -그리고 [rcedit](https://github.com/atom/rcedit) -를 사용하여 아이콘을 변경할 수 있습니다. +[rcedit](https://github.com/atom/rcedit)를 통해 `electron.exe`을 원하는 이름으로 +변경할 수 있고, 또한 아이콘과 기타 정보도 변경할 수 있습니다. ### OS X diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index 91fc59a8f2ef..38830b91e82d 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -263,6 +263,33 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## 작업 표시줄의 아이콘 오버레이 (Windows) + +Windows에선 작업 표시줄 버튼에 어플리케이션의 상태를 표시하는 작은 오버레이를 사용할 +수 있습니다. MSDN에서 인용하자면 (영문): + +> Icon overlays serve as a contextual notification of status, and are intended +> to negate the need for a separate notification area status icon to communicate +> that information to the user. For instance, the new mail status in Microsoft +> Outlook, currently shown in the notification area, can now be indicated +> through an overlay on the taskbar button. Again, you must decide during your +> development cycle which method is best for your application. Overlay icons are +> intended to supply important, long-standing status or notifications such as +> network status, messenger status, or new mail. The user should not be +> presented with constantly changing overlays or animations. + +__작업 표시줄 버튼 위의 오버레이:__ + +![작업 표시줄 버튼 위의 오버레이](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +윈도우에 오버레이 아이콘을 설정하려면 [BrowserWindow.setOverlayIcon][setoverlayicon] +API를 사용할 수 있습니다: + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## 대표 파일 제시 (OS X) OS X는 창에서 대표 파일을 설정할 수 있습니다. 타이틀바에서 파일 아이콘이 있고, 사용자가 @@ -283,13 +310,16 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons -[trayballoon]: ../api/tray.md#traydisplayballoonoptions-windows +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 +[tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows +[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx +[notification-spec]: https://developer.gnome.org/notification-spec/ diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 708a48080ff4..82d359e0de5f 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -12,7 +12,7 @@ Electron은 웹 페이지의 GUI를 사용합니다. 쉽게 말해 Electron은 ### 메인 프로세스 -Electron은 실행될 때 __메인 프로세스__로 불리는 `package.json`의 `main` 스크립트를 +Electron은 실행될 때 __메인 프로세스__ 로 불리는 `package.json`의 `main` 스크립트를 호출합니다. 이 스크립트는 메인 프로세스에서 작동합니다. GUI 컴포넌트를 조작하거나 웹 페이지 창을 생성할 수 있습니다. @@ -43,6 +43,7 @@ API를 사용하여 low-level 수준으로 운영체제와 상호작용할 수 Electron에는 메인 프로세스와 랜더러 프로세스 사이에 통신을 할 수 있도록 [ipc](../api/ipc-renderer.md) 모듈을 제공하고 있습니다. 또는 [remote](../api/remote.md) 모듈을 사용하여 RPC 스타일로 통신할 수도 있습니다. +또한 FAQ에서 [다양한 객체를 공유하는 방법](share-data)도 소개하고 있습니다. ## 첫번째 Electron 앱 만들기 @@ -211,3 +212,5 @@ $ cd electron-quick-start # 어플리케이션의 종속성 모듈을 설치한 후 실행합니다 $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#어떻게-웹-페이지-간에-데이터를-공유할-수-있나요 diff --git a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md index d0684e0cfe10..6cc5472bb12c 100644 --- a/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md +++ b/docs-translations/ko-KR/tutorial/using-selenium-and-webdriver.md @@ -48,7 +48,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // 여기에 사용중인 Electron 바이너리의 경로를 지정하세요. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') diff --git a/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md b/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md index d729c0efc08b..b9fec886769d 100644 --- a/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md +++ b/docs-translations/ko-KR/tutorial/using-widevine-cdm-plugin.md @@ -8,6 +8,10 @@ Electron은 라이센스상의 문제로 Widevine CDM 플러그인을 직접 제 따라서 플러그인을 얻으려면 먼저 사용할 Electron 빌드의 아키텍쳐와 버전에 맞춰 공식 Chrome 브라우저를 설치해야 합니다. +__참고:__ Chrome 브라우저의 메이저 버전은 Electron에서 사용하는 Chrome 버전과 +같습니다, 만약 그렇지 않다면 `navigator.plugins`가 로드됐더라도 정상적으로 작동하지 +않습니다. + ### Windows & OS X Chrome 브라우저에서 `chrome://components/`를 열고 `WidevineCdm`을 찾은 후 확실히 diff --git a/docs-translations/pt-BR/api/window-open.md b/docs-translations/pt-BR/api/window-open.md new file mode 100644 index 000000000000..eb2b31cd0e4e --- /dev/null +++ b/docs-translations/pt-BR/api/window-open.md @@ -0,0 +1,67 @@ +# The `window.open` function + +Qunado `window.open` é chamado para criar uma nova janela de uma pagina web uma nova instância de `BrowserWindow` será criado para a `url` e um proxy será devolvido para o `windows.open`, para permitir que a página tenha limitado controle sobre ele. + +O proxy tem funcionalidade limitada padrão implementada para ser compatível com as páginas web tradicionais. +Para controle total da nova janela você deveria criar um `BrowserWindow` diretamente + + +The newly created `BrowserWindow` will inherit parent window's options by +default, to override inherited options you can set them in the `features` +string. + +O recém-criado `BrowserWindow` herdará as opções da janela pai por padrão, para substituir as opções herdadas você pode definilos no `features`(string). +### `window.open(url[, frameName][, features])` + +* `url` String +* `frameName` String (opcional) +* `features` String (opcional) + +Cria uma nova janela e retorna uma instância da classe `BrowserWindowProxy'. + +A string `features` segue o formato padrão do browser, mas cada recurso (feature) tem que ser um campo de opções do `BrowserWindow`. + +### `window.opener.postMessage(message, targetOrigin)` + +* `message` String +* `targetOrigin` String + +Envia uma mensagem para a janela pai com a origem especificada ou `*` preferência de origem não especificada. +Sends a message to the parent window with the specified origin or `*` +origin preference. + +## Class: BrowserWindowProxy + +O objeto `BrowserWindowProxy` é retornado de `window.open` e fornece uma funcionalidade limitada para a janela filha. + +### `BrowserWindowProxy.blur()` + +Remove o foco da janela filha. + +### `BrowserWindowProxy.close()` + +Forçadamente fecha a janela filha sem chamar o evento de descarregamento. + +### `BrowserWindowProxy.closed` + +Define como true após a janela filha ficar fechada. + +### `BrowserWindowProxy.eval(code)` + +* `code` String + +Avalia o código na jánela filha. + +### `BrowserWindowProxy.focus()` + +Concentra-se a janela filha (traz a janela para frente) +### `BrowserWindowProxy.postMessage(message, targetOrigin)` + +* `message` String +* `targetOrigin` String + +Sends a message to the child window with the specified origin or `*` for no +origin preference. + +In addition to these methods, the child window implements `window.opener` object +with no properties and a single method. diff --git a/docs-translations/ru-RU/README.md b/docs-translations/ru-RU/README.md index 07e50028df94..4e7ed443468a 100644 --- a/docs-translations/ru-RU/README.md +++ b/docs-translations/ru-RU/README.md @@ -1,6 +1,6 @@ Пожалуйста, убедитесь, что вы используете документацию, которые соответствует вашей версии Electron. Номер версии должен быть частью адреса страницы. Если это не так, вы -возможно,используете документицию ветки разработки, которая может содержать изменения api, +возможно, используете документацию ветки разработки, которая может содержать изменения api, которые не совместимы с вашей версией Electron. Если это так, Вы можете переключиться на другую версию документации в списке [доступные версии](http://electron.atom.io/docs/) на atom.io, или diff --git a/docs-translations/zh-CN/README.md b/docs-translations/zh-CN/README.md index 5c4303a0a6f8..d7a8442ad4a3 100644 --- a/docs-translations/zh-CN/README.md +++ b/docs-translations/zh-CN/README.md @@ -1,13 +1,19 @@ +## 常见问题 + ++ [Electron 常见问题](faq/electron-faq.md) + ## 向导 * [支持平台](tutorial/supported-platforms.md) -* [应用部署](tutorial/application-distribution.md) -* [应用打包](tutorial/application-packaging.md) -* [使用原生模块](tutorial/using-native-node-modules.md) +* [分发应用](tutorial/application-distribution.md) +* [提交应用到 Mac App Store](tutorial/mac-app-store-submission-guide.md) +* [打包应用](tutorial/application-packaging.md) +* [使用 Node 原生模块](tutorial/using-native-node-modules.md) * [主进程调试](tutorial/debugging-main-process.md) * [使用 Selenium 和 WebDriver](tutorial/using-selenium-and-webdriver.md) -* [调试工具扩展](tutorial/devtools-extension.md) -* [使用 PepperFlash 插件](tutorial/using-pepper-flash-plugin.md) +* [使用开发人员工具扩展](tutorial/devtools-extension.md) +* [使用 Pepper Flash 插件](tutorial/using-pepper-flash-plugin.md) +* [使用 Widevine CDM 插件](tutorial/using-widevine-cdm-plugin.md) ## 教程 @@ -19,53 +25,55 @@ * [简介](api/synopsis.md) * [进程对象](api/process.md) -* [支持的Chrome命令行开关](api/chrome-command-line-switches.md) +* [支持的 Chrome 命令行开关](api/chrome-command-line-switches.md) +* [环境变量](api/environment-variables.md) -定制的DOM元素: +自定义的 DOM 元素: -* [`File`对象](api/file-object.md) -* [``标签](api/web-view-tag.md) -* [`window.open`函数](api/window-open.md) +* [`File` 对象](api/file-object.md) +* [`` 标签](api/web-view-tag.md) +* [`window.open` 函数](api/window-open.md) -主进程可用的模块: +在主进程内可用的模块: * [app](api/app.md) -* [auto-updater](api/auto-updater.md) -* [browser-window](api/browser-window.md) -* [content-tracing](api/content-tracing.md) +* [autoUpdater](api/auto-updater.md) +* [BrowserWindow](api/browser-window.md) +* [contentTracing](api/content-tracing.md) * [dialog](api/dialog.md) -* [global-shortcut](api/global-shortcut.md) -* [ipc (main process)](api/ipc-main-process.md) -* [menu](api/menu.md) -* [menu-item](api/menu-item.md) -* [power-monitor](api/power-monitor.md) -* [power-save-blocker](api/power-save-blocker.md) +* [globalShortcut](api/global-shortcut.md) +* [ipcMain](api/ipc-main.md) +* [Menu](api/menu.md) +* [MenuItem](api/menu-item.md) +* [powerMonitor](api/power-monitor.md) +* [powerSaveBlocker](api/power-save-blocker.md) * [protocol](api/protocol.md) * [session](api/session.md) * [webContents](api/web-contents.md) -* [tray](api/tray.md) +* [Tray](api/tray.md) -渲染进程(网页)可用的模块: +在渲染进程(网页)内可用的模块: -* [ipc (renderer)](api/ipc-renderer.md) +* [desktopCapturer](api/desktop-capturer.md) +* [ipcRenderer](api/ipc-renderer.md) * [remote](api/remote.md) -* [web-frame](api/web-frame.md) +* [webFrame](api/web-frame.md) -两种进程都可用的模块: +在两种进程中都可用的模块: * [clipboard](api/clipboard.md) -* [crash-reporter](api/crash-reporter.md) -* [native-image](api/native-image.md) +* [crashReporter](api/crash-reporter.md) +* [nativeImage](api/native-image.md) * [screen](api/screen.md) * [shell](api/shell.md) ## 开发 -* [编码规范](development/coding-style.md) +* [代码规范](development/coding-style.md) * [源码目录结构](development/source-code-directory-structure.md) -* [与 NW.js (原名 node-webkit) 在技术上的差异](development/atom-shell-vs-node-webkit.md) -* [构建系统概况](development/build-system-overview.md) -* [构建步骤 (Mac)](development/build-instructions-mac.md) -* [构建步骤 (Windows)](development/build-instructions-windows.md) -* [构建步骤 (Linux)](development/build-instructions-linux.md) -* [在调试中使用 SymbolServer](development/setting-up-symbol-server.md) +* [与 NW.js(原 node-webkit)在技术上的差异](development/atom-shell-vs-node-webkit.md) +* [构建系统概览](development/build-system-overview.md) +* [构建步骤(Mac)](development/build-instructions-mac.md) +* [构建步骤(Windows)](development/build-instructions-windows.md) +* [构建步骤(Linux)](development/build-instructions-linux.md) +* [在调试中使用 Symbol Server](development/setting-up-symbol-server.md) diff --git a/docs-translations/zh-CN/api/accelerator.md b/docs-translations/zh-CN/api/accelerator.md index 8858d18e856e..06e7397c849a 100644 --- a/docs-translations/zh-CN/api/accelerator.md +++ b/docs-translations/zh-CN/api/accelerator.md @@ -1,46 +1,43 @@ # Accelerator -An accelerator is a string that represents a keyboard shortcut. It can contain -multiple modifiers and key codes, combined by the `+` character. +一个 `Accelerator` 是一个表示某个快捷键组合的字符串。它包含了用 `+` 连接的若干个按键。 -Examples: +例如: * `Command+A` * `Ctrl+Shift+Z` -## Platform notice +## 运行平台相关的提示 -On Linux and Windows, the `Command` key does not have any effect so -use `CommandOrControl` which represents `Command` on OS X and `Control` on -Linux and Windows to define some accelerators. +在 Linux 和 Windows 上,`Command` 键并不存在,因此我们通常用 `CommandOrControl` 来表示“在 OS X 下为 `Command` 键,但在 +Linux 和 Windows 下为 `Control` 键。 -The `Super` key is mapped to the `Windows` key on Windows and Linux and -`Cmd` on OS X. +`Super` 键是指 Linux 和 Windows 上的 `Windows` 键,但是在 OS X 下为 `Command` 键。 -## Available modifiers +## 可用的功能按键 -* `Command` (or `Cmd` for short) -* `Control` (or `Ctrl` for short) -* `CommandOrControl` (or `CmdOrCtrl` for short) +* `Command`(缩写为 `Cmd`) +* `Control`(缩写为 `Ctrl`) +* `CommandOrControl`(缩写为 `CmdOrCtrl`) * `Alt` * `Shift` * `Super` -## Available key codes +## 可用的普通按键 -* `0` to `9` -* `A` to `Z` -* `F1` to `F24` -* Punctuations like `~`, `!`, `@`, `#`, `$`, etc. +* `0` 到 `9` +* `A` 到 `Z` +* `F1` 到 `F24` +* 类似与 `~`、`!`、`@`、`#`、`$` 的标点符号。 * `Plus` * `Space` * `Backspace` * `Delete` * `Insert` -* `Return` (or `Enter` as alias) -* `Up`, `Down`, `Left` and `Right` -* `Home` and `End` -* `PageUp` and `PageDown` -* `Escape` (or `Esc` for short) -* `VolumeUp`, `VolumeDown` and `VolumeMute` -* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause` +* `Return`(和 `Enter` 等同) +* `Up`、`Down`、`Left` 和 `Right` +* `Home` 和 `End` +* `PageUp` 和 `PageDown` +* `Escape`(缩写为 `Esc`) +* `VolumeUp`、`VolumeDown` 和 `VolumeMute` +* `MediaNextTrack`、`MediaPreviousTrack`、`MediaStop` 和 `MediaPlayPause` diff --git a/docs-translations/zh-CN/api/app.md b/docs-translations/zh-CN/api/app.md index 448a5a373e91..dd8d6bcfdf65 100644 --- a/docs-translations/zh-CN/api/app.md +++ b/docs-translations/zh-CN/api/app.md @@ -11,11 +11,11 @@ app.on('window-all-closed', function() { }); ``` -## 事件 +## 事件列表 `app` 对象会触发以下的事件: -### 事件: 'will-finish-launching' +### 事件:'will-finish-launching' 当应用程序完成基础的启动的时候被触发。在 Windows 和 Linux 中, `will-finish-launching` 事件与 `ready` 事件是相同的; 在 OS X 中, @@ -24,11 +24,11 @@ app.on('window-all-closed', function() { 在大多数的情况下,你应该只在 `ready` 事件处理器中完成所有的业务。 -### 事件: 'ready' +### 事件:'ready' 当 Electron 完成初始化时被触发。 -### 事件: 'window-all-closed' +### 事件:'window-all-closed' 当所有的窗口都被关闭时触发。 @@ -36,20 +36,20 @@ app.on('window-all-closed', function() { 或者开发者调用了 `app.quit()` ,Electron 将会先尝试关闭所有的窗口再触发 `will-quit` 事件, 在这种情况下 `window-all-closed` 不会被触发。 -### 事件: 'before-quit' +### 事件:'before-quit' 返回: -* `event` 事件 +* `event` Event 在应用程序开始关闭它的窗口的时候被触发。 调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。 -### 事件: 'will-quit' +### 事件:'will-quit' 返回: -* `event` 事件 +* `event` Event 当所有的窗口已经被关闭,应用即将退出时被触发。 调用 `event.preventDefault()` 将会阻止终止应用程序的默认行为。 @@ -57,20 +57,20 @@ app.on('window-all-closed', function() { 你可以在 `window-all-closed` 事件的描述中看到 `will-quit` 事件 和 `window-all-closed` 事件的区别。 -### 事件: 'quit' +### 事件:'quit' 返回: -* `event` 事件 -* `exitCode` 整数 +* `event` Event +* `exitCode` Integer 当应用程序正在退出时触发。 -### 事件: 'open-file' _OS X_ +### 事件:'open-file' _OS X_ 返回: -* `event` 事件 -* `path` 字符串 +* `event` Event +* `path` String 当用户想要在应用中打开一个文件时触发。`open-file` 事件常常在应用已经打开并且系统想要再次使用应用打开文件时被触发。 `open-file` 也会在一个文件被拖入 dock 且应用还没有运行的时候被触发。 @@ -78,73 +78,74 @@ app.on('window-all-closed', function() { 如果你想处理这个事件,你应该调用 `event.preventDefault()` 。 在 Windows系统中, 你需要通过解析 process.argv 来获取文件路径。 -### 事件: 'open-url' _OS X_ + +### 事件:'open-url' _OS X_ 返回: -* `event` 事件 -* `url` 字符串 +* `event` Event +* `url` String 当用户想要在应用中打开一个url的时候被触发。URL格式必须要提前标识才能被你的应用打开。 如果你想处理这个事件,你应该调用 `event.preventDefault()` 。 -### 事件: 'activate' _OS X_ +### 事件:'activate' _OS X_ 返回: -* `event` 事件 -* `hasVisibleWindows` 布尔值 +* `event` Event +* `hasVisibleWindows` Boolean 当应用被激活时触发,常用于点击应用的 dock 图标的时候。 -### 事件: 'browser-window-blur' +### 事件:'browser-window-blur' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 失去焦点的时候触发。 +当一个 [BrowserWindow](browser-window.md) 失去焦点的时候触发。 -### 事件: 'browser-window-focus' +### 事件:'browser-window-focus' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 获得焦点的时候触发。 +当一个 [BrowserWindow](browser-window.md) 获得焦点的时候触发。 -### 事件: 'browser-window-created' +### 事件:'browser-window-created' 返回: -* `event` 事件 -* `window` 浏览器窗口 +* `event` Event +* `window` BrowserWindow -当一个 [浏览器窗口](browser-window.md) 被创建的时候触发。 +当一个 [BrowserWindow](browser-window.md) 被创建的时候触发。 -### 事件: 'certificate-error' +### 事件:'certificate-error' 返回: -* `event` 事件 -* `webContents` [web组件](web-contents.md) -* `url` 字符串 -* `certificateList` 对象 - * `data` PEM 编码数据 - * `issuerName` 发行者的公有名称 -* `callback` 函数 +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` String - URL 地址 +* `error` String - 错误码 +* `certificate` Object + * `data` Buffer - PEM 编码数据 + * `issuerName` String - 发行者的公有名称 +* `callback` Function -Emitted when failed to verify the `certificate` for `url`, to trust the -certificate you should prevent the default behavior with -`event.preventDefault()` and call `callback(true)`. +当对 `url` 验证 `certificate` 证书失败的时候触发,如果需要信任这个证书,你需要阻止默认行为 `event.preventDefault()` 并且 +调用 `callback(true)`。 ```javascript session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { - // Verification logic. + // 验证逻辑。 event.preventDefault(); callback(true); } else { @@ -153,37 +154,37 @@ session.on('certificate-error', function(event, webContents, url, error, certifi }); ``` -### 事件: 'select-client-certificate' +### 事件:'select-client-certificate' 返回: -* `event` 事件 -* `webContents` [web组件](web-contents.md) -* `url` 字符串 -* `certificateList` 对象 - * `data` PEM 编码数据 - * `issuerName` 发行者的公有名称 -* `callback` 函数 +* `event` Event +* `webContents` [WebContents](web-contents.md) +* `url` String - URL 地址 +* `certificateList` [Object] + * `data` Buffer - PEM 编码数据 + * `issuerName` String - 发行者的公有名称 +* `callback` Function 当一个客户端认证被请求的时候被触发。 -The `url` corresponds to the navigation entry requesting the client certificate -and `callback` needs to be called with an entry filtered from the list. -Using `event.preventDefault()` prevents the application from using the first -certificate from the store. +`url` 指的是请求客户端认证的网页地址,调用 `callback` 时需要传入一个证书列表中的证书。 + +需要通过调用 `event.preventDefault()` 来防止应用自动使用第一个证书进行验证。如下所示: + ```javascript app.on('select-certificate', function(event, host, url, list, callback) { event.preventDefault(); callback(list[0]); }) ``` -### Event: 'login' +### 事件: 'login' -Returns: +返回: * `event` Event -* `webContents` [Web组件](web-contents.md) +* `webContents` [WebContents](web-contents.md) * `request` Object * `method` String * `url` URL @@ -196,11 +197,10 @@ Returns: * `realm` String * `callback` Function -当 `webContents` 要做验证时被触发。 +当 `webContents` 要做进行一次 HTTP 登陆验证时被触发。 -The default behavior is to cancel all authentications, to override this you -should prevent the default behavior with `event.preventDefault()` and call -`callback(username, password)` with the credentials. +默认情况下,Electron 会取消所有的验证行为,如果需要重写这个行为,你需要用 `event.preventDefault()` 来阻止默认行为,并且 +用 `callback(username, password)` 来进行验证。 ```javascript app.on('login', function(event, webContents, request, authInfo, callback) { @@ -208,22 +208,22 @@ app.on('login', function(event, webContents, request, authInfo, callback) { callback('username', 'secret'); }) ``` -### 事件: 'gpu-process-crashed' +### 事件:'gpu-process-crashed' -当GPU进程崩溃时触发。 +当 GPU 进程崩溃时触发。 -## 方法 +## 方法列表 `app` 对象拥有以下的方法: -**提示:** 有的方法只能用于特定的操作系统。 +**请注意** 有的方法只能用于特定的操作系统。 ### `app.quit()` -试图关掉所有的窗口。`before-quit` 事件将会被最先触发。如果所有的窗口都被成功关闭了, +试图关掉所有的窗口。`before-quit` 事件将会最先被触发。如果所有的窗口都被成功关闭了, `will-quit` 事件将会被触发,默认下应用将会被关闭。 -这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。会存在一个窗口被 `beforeunload` 事件处理器返回 `false` 取消退出的可能性。 +这个方法保证了所有的 `beforeunload` 和 `unload` 事件处理器被正确执行。假如一个窗口的 `beforeunload` 事件处理器返回 `false`,那么整个应用可能会取消退出。 ### `app.hide()` _OS X_ @@ -241,30 +241,29 @@ app.on('login', function(event, webContents, request, authInfo, callback) { 所有的窗口会被立刻关闭,不会询问用户。`before-quit` 和 `will-quit` 这2个事件不会被触发 - ### `app.getAppPath()` 返回当前应用所在的文件路径。 ### `app.getPath(name)` -* `name` 字符串 +* `name` String 返回一个与 `name` 参数相关的特殊文件夹或文件路径。当失败时抛出一个 `Error` 。 你可以通过名称请求以下的路径: -* `home` 用户的 home 文件夹。 -* `appData` 所有用户的应用数据文件夹,默认对应: +* `home` 用户的 home 文件夹(主目录) +* `appData` 当前用户的应用数据文件夹,默认对应: * `%APPDATA%` Windows 中 * `$XDG_CONFIG_HOME` or `~/.config` Linux 中 * `~/Library/Application Support` OS X 中 -* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称。 -* `temp` 临时文件夹。 +* `userData` 储存你应用程序设置文件的文件夹,默认是 `appData` 文件夹附加应用的名称 +* `temp` 临时文件夹 * `exe` 当前的可执行文件 -* `module` `libchromiumcontent` 库. -* `desktop` 当前用户的桌面文件夹。 -* `documents` "我的文件夹"的路径. +* `module` `libchromiumcontent` 库 +* `desktop` 当前用户的桌面文件夹 +* `documents` 用户文档目录的路径 * `downloads` 用户下载目录的路径. * `music` 用户音乐目录的路径. * `pictures` 用户图片目录的路径. @@ -272,14 +271,14 @@ app.on('login', function(event, webContents, request, authInfo, callback) { ### `app.setPath(name, path)` -* `name` 字符串 -* `path` 字符串 +* `name` String +* `path` String -重写 `path` 参数到一个特别的文件夹或者是一个和 `name` 参数有关系的文件。 +重写某个 `name` 的路径为 `path`,`path` 可以是一个文件夹或者一个文件,这个和 `name` 的类型有关。 如果这个路径指向的文件夹不存在,这个文件夹将会被这个方法创建。 -如果错误则抛出 `Error` 。 +如果错误则会抛出 `Error`。 -你只可以指向 `app.getPath` 中定义过 `name` 的路径。 +`name` 参数只能使用 `app.getPath` 中定义过 `name`。 默认情况下,网页的 cookie 和缓存都会储存在 `userData` 文件夹。 如果你想要改变这个位置,你需要在 `app` 模块中的 `ready` 事件被触发之前重写 `userData` 的路径。 @@ -293,22 +292,20 @@ app.on('login', function(event, webContents, request, authInfo, callback) { 返回当前应用程序的 `package.json` 文件中的名称。 -通常 `name` 字段是一个短的小写字符串,其命名规则按照 npm 中的模块命名规则。你应该单独列举一个 -`productName` 字段,用于表示你的应用程序的完整名称,这个名称将会被 Electron 优先采用。 +由于 npm 的命名规则,通常 `name` 字段是一个短的小写字符串。但是应用名的完整名称通常是首字母大写的,你应该单独使用一个 +`productName` 字段,用于表示你的应用程序的完整名称。Electron 会优先使用这个字段作为应用名。 ### `app.getLocale()` -返回当前应用程序的语言种类。 - - +返回当前应用程序的语言。 ### `app.addRecentDocument(path)` _OS X_ _Windows_ -* `path` 字符串 +* `path` String -为最近访问的文档列表中添加 `path` 。 +在最近访问的文档列表中添加 `path`。 -这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过dock 菜单进行访问。 +这个列表由操作系统进行管理。在 Windows 中您可以通过任务条进行访问,在 OS X 中你可以通过 dock 菜单进行访问。 ### `app.clearRecentDocuments()` _OS X_ _Windows_ @@ -316,66 +313,55 @@ app.on('login', function(event, webContents, request, authInfo, callback) { ### `app.setUserTasks(tasks)` _Windows_ -* `tasks` 由 `Task` 对象构成的数组 +* `tasks` [Task] - 一个由 Task 对象构成的数组 将 `tasks` 添加到 Windows 中 JumpList 功能的 [Tasks][tasks] 分类中。 `tasks` 中的 `Task` 对象格式如下: -`Task` 对象 -* `program` 字符串 - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。 -* `arguments` 字符串 - 当 `program` 执行时的命令行参数。 -* `title` 字符串 - JumpList 中显示的标题。 -* `description` 字符串 - 对这个任务的描述。 -* `iconPath` 字符串 - JumpList 中显示的 icon 的绝对路径,可以是一个任意包含一个icon的资源文件。你通常可以通过指明 `process.execPath` 来显示程序中的icon。 -* `iconIndex` 整数 - icon文件中的icon目录。如果一个icon文件包括了两个或多个icon,就需要设置这个值以确定icon。如果一个文件仅包含一个icon,那么这个值为0。 +`Task` Object +* `program` String - 执行程序的路径,通常你应该说明当前程序的路径为 `process.execPath` 字段。 +* `arguments` String - 当 `program` 执行时的命令行参数。 +* `title` String - JumpList 中显示的标题。 +* `description` String - 对这个任务的描述。 +* `iconPath` String - JumpList 中显示的图标的绝对路径,可以是一个任意包含一个图标的资源文件。通常来说,你可以通过指明 `process.execPath` 来显示程序中的图标。 +* `iconIndex` Integer - 图标文件中的采用的图标位置。如果一个图标文件包括了多个图标,就需要设置这个值以确定使用的是哪一个图标。 +如果这个图标文件中只包含一个图标,那么这个值为 0。 ### `app.allowNTLMCredentialsForAllDomains(allow)` * `allow` Boolean -Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate -authentication - normally, Electron will only send NTLM/Kerberos credentials for -URLs that fall under "Local Intranet" sites (i.e. are in the same domain as you). -However, this detection often fails when corporate networks are badly configured, -so this lets you co-opt this behavior and enable it for all URLs. +动态设置是否总是为 HTTP NTLM 或 Negotiate 认证发送证书。通常来说,Electron 只会对本地网络(比如和你处在一个域中的计算机)发 +送 NTLM / Kerberos 证书。但是假如网络设置得不太好,可能这个自动探测会失效,所以你可以通过这个接口自定义 Electron 对所有 URL +的行为。 + ### `app.makeSingleInstance(callback)` * `callback` Function -This method makes your application a Single Instance Application - instead of -allowing multiple instances of your app to run, this will ensure that only a -single instance of your app is running, and other instances signal this -instance and exit. +这个方法可以让你的应用在同一时刻最多只会有一个实例,否则你的应用可以被运行多次并产生多个实例。你可以利用这个接口保证只有一个实例正 +常运行,其余的实例全部会被终止并退出。 -`callback` will be called with `callback(argv, workingDirectory)` when a second -instance has been executed. `argv` is an Array of the second instance's command -line arguments, and `workingDirectory` is its current working directory. Usually -applications respond to this by making their primary window focused and -non-minimized. +如果多个实例同时运行,那么第一个被运行的实例中 `callback` 会以 `callback(argv, workingDirectory)` 的形式被调用。其余的实例 +会被终止。 +`argv` 是一个包含了这个实例的命令行参数列表的数组,`workingDirectory` 是这个实例目前的运行目录。通常来说,我们会用通过将应用在 +主屏幕上激活,并且取消最小化,来提醒用户这个应用已经被打开了。 -The `callback` is guaranteed to be executed after the `ready` event of `app` -gets emitted. +在 `app` 的 `ready` 事件后,`callback` 才有可能被调用。 -This method returns `false` if your process is the primary instance of the -application and your app should continue loading. And returns `true` if your -process has sent its parameters to another instance, and you should immediately -quit. +如果当前实例为第一个实例,那么在这个方法将会返回 `false` 来保证它继续运行。否则将会返回 `true` 来让它立刻退出。 -On OS X the system enforces single instance automatically when users try to open -a second instance of your app in Finder, and the `open-file` and `open-url` -events will be emitted for that. However when users start your app in command -line the system's single instance machanism will be bypassed and you have to -use this method to ensure single instance. +在 OS X 中,如果用户通过 Finder、`open-file` 或者 `open-url` 打开应用,系统会强制确保只有一个实例在运行。但是如果用户是通过 +命令行打开,这个系统机制会被忽略,所以你仍然需要靠这个方法来保证应用为单实例运行的。 -An example of activating the window of primary instance when a second instance -starts: +下面是一个简单的例子。我们可以通过这个例子了解如何确保应用为单实例运行状态。 ```js var myWindow = null; var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) { - // Someone tried to run a second instance, we should focus our window. + // 当另一个实例运行的时候,这里将会被调用,我们需要激活应用的窗口 if (myWindow) { if (myWindow.isMinimized()) myWindow.restore(); myWindow.focus(); @@ -383,104 +369,109 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) return true; }); +// 这个实例是多余的实例,需要退出 if (shouldQuit) { app.quit(); return; } -// Create myWindow, load the rest of the app, etc... +// 创建窗口、继续加载应用、应用逻辑等…… app.on('ready', function() { }); + ``` ### `app.setAppUserModelId(id)` _Windows_ * `id` String -改变 [Application User Model ID][app-user-model-id] 的 `id`. +改变当前应用的 [Application User Model ID][app-user-model-id] 为 `id`. ### `app.isAeroGlassEnabled()` _Windows_ -This method returns `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx) -(Aero Glass) is enabled, and `false` otherwise. You can use it to determine if -you should create a transparent window or not (transparent windows won't work -correctly when DWM composition is disabled). +如果 [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx)(Aero Glass) 启用 +了,那么这个方法会返回 `true`,否则是 `false`。你可以用这个方法来决定是否要开启透明窗口特效,因为如果用户没开启 DWM,那么透明窗 +口特效是无效的。 -Usage example: +举个例子: ```js let browserOptions = {width: 1000, height: 800}; -// Make the window transparent only if the platform supports it. +// 只有平台支持的时候才使用透明窗口 if (process.platform !== 'win32' || app.isAeroGlassEnabled()) { browserOptions.transparent = true; browserOptions.frame = false; } -// Create the window. +// 创建窗口 win = new BrowserWindow(browserOptions); -// Navigate. +// 转到某个网页 if (browserOptions.transparent) { win.loadURL('file://' + __dirname + '/index.html'); } else { - // No transparency, so we load a fallback that uses basic styles. + // 没有透明特效,我们应该用某个只包含基本样式的替代解决方案。 win.loadURL('file://' + __dirname + '/fallback.html'); } ``` ### `app.commandLine.appendSwitch(switch[, value])` -通过可选的参数 `value` 给 Chromium 命令行中添加一个开关。 -Append a switch (with optional `value`) to Chromium's command line. +通过可选的参数 `value` 给 Chromium 中添加一个命令行开关。 -**贴士:** 这不会影响 `process.argv` ,这个方法主要被开发者用于控制一些低层级的 Chromium 行为。 +**注意** 这个方法不会影响 `process.argv`,我们通常用这个方法控制一些底层 Chromium 行为。 ### `app.commandLine.appendArgument(value)` -给 Chromium 命令行中加入一个参数。这个参数是当前正在被引用的。 +给 Chromium 中直接添加一个命令行参数,这个参数 `value` 的引号和格式必须正确。 -**贴士:** 这不会影响 `process.argv`。 +**注意** 这个方法不会影响 `process.argv`。 ### `app.dock.bounce([type])` _OS X_ -* `type` 字符串 (可选的) - 可以是 `critical` 或 `informational`。默认下是 `informational` +* `type` String - 可选参数,可以是 `critical` 或 `informational`。默认为 `informational`。 -当输入 `critical` 时,dock 中的 icon 将会开始弹跳直到应用被激活或者这个请求被取消。 +当传入的是 `critical` 时,dock 中的应用将会开始弹跳,直到这个应用被激活或者这个请求被取消。 -当输入 `informational` 时,dock 中的 icon 只会弹跳一秒钟。 -然而,这个请求仍然会激活,直到应用被激活或者请求被取消。 +当传入的是 `informational` 时,dock 中的图标只会弹跳一秒钟。但是,这个请求仍然会激活,直到应用被激活或者请求被取消。 -返回一个表示这个请求的 ID。 +这个方法返回的返回值表示这个请求的 ID。 ### `app.dock.cancelBounce(id)` _OS X_ -* `id` 整数 +* `id` Integer 取消这个 `id` 对应的请求。 ### `app.dock.setBadge(text)` _OS X_ -* `text` 字符串 +* `text` String -设置 dock 中显示的字符。 +设置应用在 dock 中显示的字符串。 ### `app.dock.getBadge()` _OS X_ -返回 dock 中显示的字符。 +返回应用在 dock 中显示的字符串。 ### `app.dock.hide()` _OS X_ -隐藏 dock 中的 icon。 +隐藏应用在 dock 中的图标。 ### `app.dock.show()` _OS X_ -显示 dock 中的 icon。 +显示应用在 dock 中的图标。 ### `app.dock.setMenu(menu)` _OS X_ -* `menu` 菜单 +* `menu` [Menu](menu.md) 设置应用的 [dock 菜单][dock-menu]. +### `app.dock.setIcon(image)` _OS X_ + +* `image` [NativeImage](native-image.md) + +设置应用在 dock 中显示的图标。 + [dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103 [tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx diff --git a/docs-translations/zh-CN/api/auto-updater.md b/docs-translations/zh-CN/api/auto-updater.md new file mode 100644 index 000000000000..f027fbc6e503 --- /dev/null +++ b/docs-translations/zh-CN/api/auto-updater.md @@ -0,0 +1,88 @@ +# autoUpdater + +这个模块提供了一个到 `Squirrel` 自动更新框架的接口。 + +## 平台相关的提示 + +虽然 `autoUpdater` 模块提供了一套各平台通用的接口,但是在每个平台间依然会有一些微小的差异。 + +### OS X + +在 OS X 上,`autoUpdater` 模块依靠的是内置的 [Squirrel.Mac][squirrel-mac],这意味着你不需要依靠其他的设置就能使用。关于 +更新服务器的配置,你可以通过阅读 [Server Support][server-support] 这篇文章来了解。 + +### Windows + +在 Windows 上,你必须使用安装程序将你的应用装到用户的计算机上,所以比较推荐的方法是用 [grunt-electron-installer][installer] 这个模块来自动生成一个 Windows 安装向导。 + +Squirrel 自动生成的安装向导会生成一个带 [Application User Model ID][app-user-model-id] 的快捷方式。 +Application User Model ID 的格式是 `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, 比如 +像 `com.squirrel.slack.Slack` 和 `com.squirrel.code.Code` 这样的。你应该在自己的应用中使用 `app.setAppUserModelId` 方法设置相同的 API,不然 Windows 将不能正确地把你的应用固定在任务栏上。 + +服务器端的配置和 OS X 也是不一样的,你可以阅读 [Squirrel.Windows][squirrel-windows] 这个文档来获得详细信息。 + +### Linux + +Linux 下没有任何的自动更新支持,所以我们推荐用各个 Linux 发行版的包管理器来分发你的应用。 + +## 事件列表 + +`autoUpdater` 对象会触发以下的事件: + +### 事件:'error' + +返回: + +* `error` Error + +当更新发生错误的时候触发。 + +### 事件:'checking-for-update' + +当开始检查更新的时候触发。 + +### 事件:'update-available' + +当发现一个可用更新的时候触发,更新包下载会自动开始。 + +### 事件:'update-not-available' + +当没有可用更新的时候触发。 + +### 事件:'update-downloaded' + +返回: + +* `event` Event +* `releaseNotes` String - 新版本更新公告 +* `releaseName` String - 新的版本号 +* `releaseDate` Date - 新版本发布的日期 +* `updateURL` String - 更新地址 + +在更新下载完成的时候触发。 + +在 Windows 上只有 `releaseName` 是有效的。 + +## 方法列表 + +`autoUpdater` 对象有以下的方法: + +### `autoUpdater.setFeedURL(url)` + +* `url` String + +设置检查更新的 `url`,并且初始化自动更新。这个 `url` 一旦设置就无法更改。 + +### `autoUpdater.checkForUpdates()` + +向服务端查询现在是否有可用的更新。在调用这个方法之前,必须要先调用 `setFeedURL`。 + +### `autoUpdater.quitAndInstall()` + +在下载完成后,重启当前的应用并且安装更新。这个方法应该仅在 `update-downloaded` 事件触发后被调用。 + +[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac +[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support +[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows +[installer]: https://github.com/atom/grunt-electron-installer +[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx diff --git a/docs-translations/zh-CN/api/file-object.md b/docs-translations/zh-CN/api/file-object.md new file mode 100644 index 000000000000..ef320b36994e --- /dev/null +++ b/docs-translations/zh-CN/api/file-object.md @@ -0,0 +1,29 @@ +# `File`对象 + +为了让用户能够通过HTML5的file API直接操作本地文件,DOM的File接口提供了对本地文件的抽象。Electron在File接口中增加了一个path属性,它是文件在系统中的真实路径。 + +--- + +获取拖动到APP中文件的真实路径的例子: + +``` +
+ Drag your file here +
+ + +``` diff --git a/docs-translations/zh-CN/api/remote.md b/docs-translations/zh-CN/api/remote.md new file mode 100644 index 000000000000..a686abf2f618 --- /dev/null +++ b/docs-translations/zh-CN/api/remote.md @@ -0,0 +1,137 @@ +# remote + +`remote` 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。 + +Electron中, 与GUI相关的模块(如 `dialog`, `menu` 等)只存在于主进程,而不在渲染进程中 +。为了能从渲染进程中使用它们,需要用`ipc`模块来给主进程发送进程间消息。使用 `remote` +模块,可以调用主进程对象的方法,而无需显式地发送进程间消息,这类似于 Java 的 [RMI][rmi]。 +下面是从渲染进程创建一个浏览器窗口的例子: + +```javascript +const remote = require('electron').remote; +const BrowserWindow = remote.BrowserWindow; + +var win = new BrowserWindow({ width: 800, height: 600 }); +win.loadURL('https://github.com'); +``` + +**注意:** 反向操作(从主进程访问渲染进程),可以使用[webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture). + +## 远程对象 + +`remote`模块返回的每个对象(包括函数)都代表了主进程中的一个对象(我们称之为远程对象或者远程函数)。 +当调用远程对象的方法、执行远程函数或者使用远程构造器(函数)创建新对象时,其实就是在发送同步的进程间消息。 + +在上面的例子中, `BrowserWindow` 和 `win` 都是远程对象,然而 +`new BrowserWindow` 并没有在渲染进程中创建 `BrowserWindow` 对象。 +而是在主进程中创建了 `BrowserWindow` 对象,并在渲染进程中返回了对应的远程对象,即 +`win` 对象。 + +请注意只有 [可枚举属性](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) 才能通过 remote 进行访问. + +## 远程对象的生命周期 + +Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。 +当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。 + +如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露, +所以你必须小心不要泄露了远程对象。If the remote object is leaked in the renderer process (e.g. stored in a map but +never freed), the corresponding object in the main process will also be leaked, +so you should be very careful not to leak remote objects. + +不过,主要的值类型如字符串和数字,是传递的副本。 + +## 给主进程传递回调函数 + +在主进程中的代码可以从渲染进程——`remote`模块——中接受回调函数,但是使用这个功能的时候必须非常非常小心。Code in the main process can accept callbacks from the renderer - for instance +the `remote` module - but you should be extremely careful when using this +feature. + +首先,为了避免死锁,传递给主进程的回调函数会进行异步调用。所以不能期望主进程来获得传递过去的回调函数的返回值。First, in order to avoid deadlocks, the callbacks passed to the main process +are called asynchronously. You should not expect the main process to +get the return value of the passed callbacks. + +比如,你不能主进程中给`Array.map`传递来自渲染进程的函数。 + +```javascript +// 主进程 mapNumbers.js +exports.withRendererCallback = function(mapper) { + return [1,2,3].map(mapper); +} + +exports.withLocalCallback = function() { + return exports.mapNumbers(function(x) { + return x + 1; + }); +} +``` + +```javascript +// 渲染进程 +var mapNumbers = require("remote").require("./mapNumbers"); + +var withRendererCb = mapNumbers.withRendererCallback(function(x) { + return x + 1; +}) + +var withLocalCb = mapNumbers.withLocalCallback() + +console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4] +``` + +如你所见,渲染器回调函数的同步返回值没有按预期产生,与主进程中的一模一样的回调函数的返回值不同。 + +其次,传递给主进程的函数会持续到主进程对他们进行垃圾回收。 + +例如,下面的代码第一眼看上去毫无问题。给远程对象的`close`事件绑定了一个回调函数: + +```javascript +remote.getCurrentWindow().on('close', function() { + // blabla... +}); +``` + +但记住主进程会一直保持对这个回调函数的引用,除非明确的卸载它。如果不卸载,每次重新载入窗口都会再次绑定,这样每次重启就会泄露一个回调函数。 + +更严重的是,由于前面安装了回调函数的上下文已经被释放,所以当主进程的 `close` 事件触发的时候,会抛出异常。 + +为了避免这个问题,要确保对传递给主进程的渲染器的回调函数进行清理。可以清理事件处理器,或者明确告诉主进行取消来自已经退出的渲染器进程中的回调函数。 + +## 访问主进程中的内置模块 + +在主进程中的内置模块已经被添加为`remote`模块中的属性,所以可以直接像使用`electron`模块一样直接使用它们。 + +```javascript +const app = remote.app; +``` + +## 方法 + +`remote` 模块有以下方法: + +### `remote.require(module)` + +* `module` String + +返回在主进程中执行 `require(module)` 所返回的对象。 + +### `remote.getCurrentWindow()` + +返回该网页所属的 [`BrowserWindow`](browser-window.md) 对象。 + +### `remote.getCurrentWebContents()` + +返回该网页的 [`WebContents`](web-contents.md) 对象 + +### `remote.getGlobal(name)` + +* `name` String + +返回在主进程中名为 `name` 的全局变量(即 `global[name]`) 。 + +### `remote.process` + +返回主进程中的 `process` 对象。等同于 +`remote.getGlobal('process')` 但是有缓存。 + +[rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation diff --git a/docs-translations/zh-CN/faq/electron-faq.md b/docs-translations/zh-CN/faq/electron-faq.md new file mode 100644 index 000000000000..3431c6018ab2 --- /dev/null +++ b/docs-translations/zh-CN/faq/electron-faq.md @@ -0,0 +1,139 @@ +# Electron 常见问题 + +## Electron 会在什么时候升级到最新版本的 Chrome? + +通常来说,在稳定版的 Chrome 发布后两周内,我们会更新 Electron 内的 Chrome 版本。 + +我们只会使用 stable 版本的 Chrome。但如果在 beta 或 dev 版本中有一个重要的更新,我们会把补丁应用到现版本的 Chrome 上。 + +## Electron 会在什么时候升级到最新版本的 Node.js? + +我们通常会在最新版的 Node.js 发布后一个月左右将 Electron 更新到这个版本的 Node.js。我们通过这种方式来避免新版本的 Node.js +带来的 bug(这种 bug 太常见了)。 + +Node.js 的新特性通常是由新版本的 V8 带来的。由于 Electron 使用的是 Chrome 浏览器中附带的 V8 引擎,所以 Electron 内往往已经 +有了部分新版本 Node.js 才有的崭新特性。 + +## 如何在两个网页间共享数据? + +在两个网页(渲染进程)间共享数据最简单的方法是使用浏览器中已经实现的 HTML5 API,比较好的方案是用 [Storage API][storage], +[`localStorage`][local-storage],[`sessionStorage`][session-storage] 或者 [IndexedDB][indexed-db]。 + +你还可以用 Electron 内的 IPC 机制实现。将数据存在主进程的某个全局变量中,然后在多个渲染进程中使用 `remote` 模块来访问它。 + +```javascript +// 在主进程中 +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// 在第一个页面中 +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// 在第二个页面中 +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + +## 为什么应用的窗口、托盘在一段时间后不见了? + +这通常是因为用来存放窗口、托盘的变量被垃圾收集了。 + +你可以参考以下两篇文章来了解为什么会遇到这个问题。 + +* [内存管理][memory-management] +* [变量作用域][variable-scope] + +如果你只是要一个快速的修复方案,你可以用下面的方式改变变量的作用域,防止这个变量被垃圾收集。 + +从 + +```javascript +app.on('ready', function() { + var tray = new Tray('/path/to/icon.png'); +}) +``` + +改为 + +```javascript +var tray = null; +app.on('ready', function() { + tray = new Tray('/path/to/icon.png'); +}) +``` + +## 在 Electron 中,我为什么不能用 jQuery、RequireJS、Meteor、AngularJS? + +因为 Electron 在运行环境中引入了 Node.js,所以在 DOM 中有一些额外的变量,比如 `module`、`exports` 和 `require`。这导致 +了许多库不能正常运行,因为它们也需要将同名的变量加入运行环境中。 + +我们可以通过禁用 Node.js 来解决这个问题,用如下的方式: + +```javascript +// 在主进程中 +var mainWindow = new BrowserWindow({ + webPreferences: { + nodeIntegration: false + } +}); +``` + +假如你依然需要使用 Node.js 和 Electron 提供的 API,你需要在引入那些库之前将这些变量重命名,比如: + +```html + + + + +``` + +## 为什么 `require('electron').xxx` 的结果是 undefined? + +在使用 Electron 的提供的模块时,你可能会遇到和以下类似的错误: + +``` +> require('electron').webFrame.setZoomFactor(1.0); +Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined +``` + +这是因为你在项目中或者在全局中安装了[npm 上获取的 `electron` 模块][electron-module],它把 Electron 的内置模块覆写了。 + +你可以通过以下方式输出 `electron` 模块的路径来确认你是否使用了正确的模块。 + +```javascript +console.log(require.resolve('electron')); +``` + +确认以下它是不是像下面这样的: + +``` +"/path/to/Electron.app/Contents/Resources/atom.asar/renderer/api/lib/exports/electron.js" +``` + +假如输出的路径类似于 `node_modules/electron/index.js`,那么你需要移除或者重命名 npm 上的 `electron` 模块。 + +```bash +npm uninstall electron +npm uninstall -g electron +``` + +如果你依然遇到了这个问题,你可能需要检查一下拼写或者是否在错误的进程中调用了这个模块。比如, +`require('electron').app` 只能在主进程中使用, 然而 `require('electron').webFrame` 只能在渲染进程中使用。 + +[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management +[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx +[electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs-translations/zh-CN/tutorial/debugging-main-process.md b/docs-translations/zh-CN/tutorial/debugging-main-process.md index 48f3579394e7..f971a40892fc 100644 --- a/docs-translations/zh-CN/tutorial/debugging-main-process.md +++ b/docs-translations/zh-CN/tutorial/debugging-main-process.md @@ -18,16 +18,31 @@ ## 使用 node-inspector 来调试 -__备注:__ Electron 使用 node v0.11.13 版本,目前对 node-inspector支持的不是特别好, +__备注:__ Electron 目前对 node-inspector支持的不是特别好, 如果你通过 node-inspector 的 console 来检查 `process` 对象,主进程就会崩溃。 -### 1. 开始 [node-inspector][node-inspector] 服务 +### 1. 确认你已经安装了 [node-gyp 所需工具](https://github.com/nodejs/node-gyp#installation) + +### 2. 安装 [node-inspector][node-inspector] ```bash -$ node-inspector +$ npm install node-inspector ``` -### 2. 打开 Electron 的调试模式 +### 3. 安装 `node-pre-gyp` 的一个修订版 + +```bash +$ npm install git+https://git@github.com/enlight/node-pre-gyp.git#detect-electron-runtime-in-find +``` + +### 4. 为 Electron 重新编译 `node-inspector` `v8` 模块(将 target 参数修改为你的 Electron 的版本号) + +```bash +$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-debug/ --dist-url=https://atom.io/download/atom-shell reinstall +$ node_modules/.bin/node-pre-gyp --target=0.36.2 --runtime=electron --fallback-to-build --directory node_modules/v8-profiler/ --dist-url=https://atom.io/download/atom-shell reinstall +``` + +### 5. 打开 Electron 的调试模式 你也可以用调试参数来运行 Electron : @@ -41,7 +56,13 @@ $ electron --debug=5858 your/app $ electron --debug-brk=5858 your/app ``` -### 3. 加载调试器界面 +### 6. 使用 Electron 开启 [node-inspector][node-inspector] 服务 + +```bash +$ ELECTRON_RUN_AS_NODE=true path/to/electron.exe node_modules/node-inspector/bin/inspector.js +``` + +### 7. 加载调试器界面 在 Chrome 中打开 http://127.0.0.1:8080/debug?ws=127.0.0.1:8080&port=5858 diff --git a/docs-translations/zh-CN/tutorial/quick-start.md b/docs-translations/zh-CN/tutorial/quick-start.md index 5e9c752d1d45..c4d668417e4c 100644 --- a/docs-translations/zh-CN/tutorial/quick-start.md +++ b/docs-translations/zh-CN/tutorial/quick-start.md @@ -127,7 +127,7 @@ $ ./Electron.app/Contents/MacOS/Electron your-app/ 在你完成了你的应用后,你可以按照[应用部署][4]指导发布一个版本,并且以已经打包好的形式运行应用。 - [1]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/ipc-renderer.md + [1]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/ipc-main-process.md [2]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/api/remote.md [3]: https://github.com/atom/electron/releases [4]: https://github.com/atom/electron/blob/master/docs-translations/zh-CN/tutorial/application-distribution.md diff --git a/docs/api/app.md b/docs/api/app.md index adba230b0e2b..bdf0a8a55870 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -156,7 +156,7 @@ certificate you should prevent the default behavior with `event.preventDefault()` and call `callback(true)`. ```javascript -session.on('certificate-error', function(event, webContents, url, error, certificate, callback) { +app.on('certificate-error', function(event, webContents, url, error, certificate, callback) { if (url == "https://github.com") { // Verification logic. event.preventDefault(); @@ -246,7 +246,7 @@ returning `false` in the `beforeunload` event handler. ### `app.hide()` _OS X_ -Hides all application windows without minimising them. +Hides all application windows without minimizing them. ### `app.show()` _OS X_ @@ -398,7 +398,7 @@ quit. On OS X the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the `open-file` and `open-url` events will be emitted for that. However when users start your app in command -line the system's single instance machanism will be bypassed and you have to +line the system's single instance mechanism will be bypassed and you have to use this method to ensure single instance. An example of activating the window of primary instance when a second instance @@ -413,7 +413,6 @@ var shouldQuit = app.makeSingleInstance(function(commandLine, workingDirectory) if (myWindow.isMinimized()) myWindow.restore(); myWindow.focus(); } - return true; }); if (shouldQuit) { @@ -516,7 +515,7 @@ Shows the dock icon. ### `app.dock.setMenu(menu)` _OS X_ -* `menu` Menu +* `menu` [Menu](menu.md) Sets the application's [dock menu][dock-menu]. diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 7cf684a39539..2800ac38a049 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -58,7 +58,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `alwaysOnTop` Boolean - Whether the window should always stay on top of other windows. Default is `false`. * `fullscreen` Boolean - Whether the window should show in fullscreen. When - explicity set to `false` the fullscreen button will be hidden or disabled + explicitly set to `false` the fullscreen button will be hidden or disabled on OS X, or the maximize button will be disabled on Windows. Default is `false`. * `fullscreenable` Boolean - Whether the maximize/zoom button on OS X should @@ -458,7 +458,7 @@ Returns a boolean, whether the window is in fullscreen mode. * `aspectRatio` The aspect ratio we want to maintain for some portion of the content view. * `extraSize` Object (optional) - The extra size not to be included while -maintaining the aspect ratio. Properties: +maintaining the aspect ratio. * `width` Integer * `height` Integer @@ -478,13 +478,11 @@ height areas you have within the overall content view. ### `win.setBounds(options[, animate])` -* `options` Object, properties: - +* `options` Object * `x` Integer * `y` Integer * `width` Integer * `height` Integer - * `animate` Boolean (optional) _OS X_ Resizes and moves the window to `width`, `height`, `x`, `y`. @@ -717,7 +715,7 @@ Returns the pathname of the file the window represents. * `edited` Boolean Specifies whether the window’s document has been edited, and the icon in title -bar will become grey when set to `true`. +bar will become gray when set to `true`. ### `win.isDocumentEdited()` _OS X_ @@ -729,7 +727,7 @@ Whether the window's document has been edited. ### `win.capturePage([rect, ]callback)` -* `rect` Object (optional)- The area of page to be captured, properties: +* `rect` Object (optional) - The area of page to be captured * `x` Integer * `y` Integer * `width` Integer @@ -802,27 +800,7 @@ Returns whether the window has a shadow. On Windows and Linux always returns ### `win.setThumbarButtons(buttons)` _Windows 7+_ -`buttons` Array of `button` Objects: - -`button` Object, properties: - -* `icon` [NativeImage](native-image.md) - The icon showing in thumbnail - toolbar. -* `tooltip` String (optional) - The text of the button's tooltip. -* `flags` Array (optional) - Control specific states and behaviors - of the button. By default, it uses `enabled`. It can include following - Strings: - * `enabled` - The button is active and available to the user. - * `disabled` - The button is disabled. It is present, but has a visual - state indicating it will not respond to user action. - * `dismissonclick` - When the button is clicked, the taskbar button's - flyout closes immediately. - * `nobackground` - Do not draw a button border, use only the image. - * `hidden` - The button is not shown to the user. - * `noninteractive` - The button is enabled but not interactive; no - pressed button state is drawn. This value is intended for instances - where the button is used in a notification. -* `click` - Function +* `buttons` Array Add a thumbnail toolbar with a specified set of buttons to the thumbnail image of a window in a taskbar button layout. Returns a `Boolean` object indicates @@ -833,6 +811,29 @@ the limited room. Once you setup the thumbnail toolbar, the toolbar cannot be removed due to the platform's limitation. But you can call the API with an empty array to clean the buttons. +The `buttons` is an array of `Button` objects: + +* `Button` Object + * `icon` [NativeImage](native-image.md) - The icon showing in thumbnail + toolbar. + * `click` Function + * `tooltip` String (optional) - The text of the button's tooltip. + * `flags` Array (optional) - Control specific states and behaviors of the + button. By default, it is `['enabled']`. + +The `flags` is an array that can include following `String`s: + +* `enabled` - The button is active and available to the user. +* `disabled` - The button is disabled. It is present, but has a visual state + indicating it will not respond to user action. +* `dismissonclick` - When the button is clicked, the thumbnail window closes + immediately. +* `nobackground` - Do not draw a button border, use only the image. +* `hidden` - The button is not shown to the user. +* `noninteractive` - The button is enabled but not interactive; no pressed + button state is drawn. This value is intended for instances where the button + is used in a notification. + ### `win.showDefinitionForSelection()` _OS X_ Shows pop-up dictionary that searches the selected word on the page. diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index dcb9fa398a90..7f95a1af26d2 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -67,7 +67,6 @@ Writes `image` to the clipboard. Returns the content in the clipboard as RTF. - ### `clipboard.writeRtf(text[, type])` * `text` String diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index aae5306523ae..0b83c2759c67 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -155,7 +155,7 @@ called. * `eventName` String * `callback` Function -`callback` will will be called every time the given event occurs on any +`callback` will be called every time the given event occurs on any process. ### `contentTracing.cancelWatchEvent()` diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 1b0928263566..98465dffc971 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -22,19 +22,16 @@ The `crash-reporter` module has the following methods: ### `crashReporter.start(options)` -`options` Object, properties: - -* `productName` String, default: Electron. -* `companyName` String (**required**) -* `submitURL` String, (**required**) - * URL that crash reports will be sent to as POST. -* `autoSubmit` Boolean, default: `true`. - * Send the crash report without user interaction. -* `ignoreSystemCrashHandler` Boolean, default: `false`. -* `extra` Object - * An object you can define that will be sent along with the report. - * Only string properties are sent correctly. - * Nested objects are not supported. +* `options` Object + * `companyName` String + * `submitURL` String - URL that crash reports will be sent to as POST. + * `productName` String (optional) - Default is `Electron`. + * `autoSubmit` Boolean - Send the crash report without user interaction. + Default is `true`. + * `ignoreSystemCrashHandler` Boolean - Default is `false`. + * `extra` Object - An object you can define that will be sent along with the + report. Only string properties are sent correctly, Nested objects are not + supported. You are required to call this method before using other `crashReporter` APIs. diff --git a/docs/api/ipc-main.md b/docs/api/ipc-main.md index 337d86be217b..84fbcfd5a72f 100644 --- a/docs/api/ipc-main.md +++ b/docs/api/ipc-main.md @@ -9,7 +9,7 @@ module. ## Sending Messages It is also possible to send messages from the main process to the renderer -process, see [webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-) for more information. +process, see [webContents.send][web-contents-send] for more information. * When sending a message, the event name is the `channel`. * To reply a synchronous message, you need to set `event.returnValue`. @@ -48,37 +48,37 @@ ipcRenderer.send('asynchronous-message', 'ping'); The `ipcMain` module has the following method to listen for events: -### `ipcMain.on(channel, callback)` +### `ipcMain.on(channel, listener)` -* `channel` String - The event name. -* `callback` Function +* `channel` String +* `listener` Function -When the event occurs the `callback` is called with an `event` object and -arbitrary arguments. +Listens to `channel`, when a new message arrives `listener` would be called with +`listener(event, args...)`. -### `ipcMain.removeListener(channel, callback)` +### `ipcMain.once(channel, listener)` -* `channel` String - The event name. -* `callback` Function - The reference to the same function that you used for - `ipcMain.on(channel, callback)` +* `channel` String +* `listener` Function -Once done listening for messages, if you no longer want to activate this -callback and for whatever reason can't merely stop sending messages on the -channel, this function will remove the callback handler for the specified -channel. +Adds a one time `listener` function for the event. This `listener` is invoked +only the next time a message is sent to `channel`, after which it is removed. -### `ipcMain.removeAllListeners(channel)` +### `ipcMain.removeListener(channel, listener)` -* `channel` String - The event name. +* `channel` String +* `listener` Function -This removes *all* handlers to this ipc channel. +Removes the specified `listener` from the listener array for the specified +`channel`. -### `ipcMain.once(channel, callback)` +### `ipcMain.removeAllListeners([channel])` -Use this in place of `ipcMain.on()` to fire handlers meant to occur only once, -as in, they won't be activated after one call of `callback` +* `channel` String (optional) -## IPC Event +Removes all listeners, or those of the specified `channel`. + +## Event object The `event` object passed to the `callback` has the following methods: @@ -90,4 +90,6 @@ Set this to the value to be returned in a synchronous message. Returns the `webContents` that sent the message, you can call `event.sender.send` to reply to the asynchronous message, see -[webContents.send](web-contents.md#webcontentssendchannel-arg1-arg2-) for more information. +[webContents.send][web-contents-send] for more information. + +[web-contents-send]: web-contents.md#webcontentssendchannel-arg1-arg2- diff --git a/docs/api/ipc-renderer.md b/docs/api/ipc-renderer.md index 96936632563e..f17843702b57 100644 --- a/docs/api/ipc-renderer.md +++ b/docs/api/ipc-renderer.md @@ -12,35 +12,35 @@ See [ipcMain](ipc-main.md) for code examples. The `ipcRenderer` module has the following method to listen for events: -### `ipcRenderer.on(channel, callback)` +### `ipcRenderer.on(channel, listener)` -* `channel` String - The event name. -* `callback` Function +* `channel` String +* `listener` Function -When the event occurs the `callback` is called with an `event` object and -arbitrary arguments. +Listens to `channel`, when a new message arrives `listener` would be called with +`listener(event, args...)`. -### `ipcRenderer.removeListener(channel, callback)` +### `ipcRenderer.once(channel, listener)` -* `channel` String - The event name. -* `callback` Function - The reference to the same function that you used for - `ipcRenderer.on(channel, callback)` +* `channel` String +* `listener` Function -Once done listening for messages, if you no longer want to activate this -callback and for whatever reason can't merely stop sending messages on the -channel, this function will remove the callback handler for the specified -channel. +Adds a one time `listener` function for the event. This `listener` is invoked +only the next time a message is sent to `channel`, after which it is removed. -### `ipcRenderer.removeAllListeners(channel)` +### `ipcRenderer.removeListener(channel, listener)` -* `channel` String - The event name. +* `channel` String +* `listener` Function -This removes *all* handlers to this ipc channel. +Removes the specified `listener` from the listener array for the specified +`channel`. -### `ipcRenderer.once(channel, callback)` +### `ipcRenderer.removeAllListeners([channel])` -Use this in place of `ipcRenderer.on()` to fire handlers meant to occur only once, -as in, they won't be activated after one call of `callback` +* `channel` String (optional) + +Removes all listeners, or those of the specified `channel`. ## Sending Messages @@ -48,30 +48,33 @@ The `ipcRenderer` module has the following methods for sending messages: ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) -Send an event to the main process asynchronously via a `channel`, you can also -send arbitrary arguments. The main process handles it by listening for the -`channel` event with `ipcMain`. +Send a message to the main process asynchronously via `channel`, you can also +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. + +The main process handles it by listening for `channel` with `ipcMain` module. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) -Send an event to the main process synchronously via a `channel`, you can also -send arbitrary arguments. +Send a message to the main process synchronously via `channel`, you can also +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. -The main process handles it by listening for the `channel` event with -`ipcMain` and replies by setting `event.returnValue`. +The main process handles it by listening for `channel` with `ipcMain` module, +and replies by setting `event.returnValue`. __Note:__ Sending a synchronous message will block the whole renderer process, unless you know what you are doing you should never use it. ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` -* `channel` String - The event name. +* `channel` String * `arg` (optional) Like `ipcRenderer.send` but the event will be sent to the `` element in diff --git a/docs/api/shell.md b/docs/api/shell.md index e6678a955364..823dc481bb07 100644 --- a/docs/api/shell.md +++ b/docs/api/shell.md @@ -26,12 +26,16 @@ Show the given file in a file manager. If possible, select the file. Open the given file in the desktop's default manner. -### `shell.openExternal(url)` +### `shell.openExternal(url[, options])` * `url` String +* `options` Object (optional) _OS X_ + * `activate` Boolean - `true` to bring the opened application to the + foreground. The default is `true`. Open the given external protocol URL in the desktop's default manner. (For -example, mailto: URLs in the user's default mail agent.) +example, mailto: URLs in the user's default mail agent.) Returns true if an +application was available to open the URL, false otherwise. ### `shell.moveItemToTrash(fullPath)` diff --git a/docs/api/tray.md b/docs/api/tray.md index 08a43638be14..22ab9aea5b79 100644 --- a/docs/api/tray.md +++ b/docs/api/tray.md @@ -32,6 +32,13 @@ __Platform limitations:__ install `libappindicator1` to make the tray icon work. * App indicator will only be shown when it has a context menu. * When app indicator is used on Linux, the `click` event is ignored. +* On Linux in order for changes made to individual `MenuItem`s to take effect, + you have to call `setContextMenu` again. For example: + +```javascript +contextMenu.items[2].checked = false; +appIcon.setContextMenu(contextMenu); +``` If you want to keep exact same behaviors on all platforms, you should not rely on the `click` event and always attach a context menu to the tray icon. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index afdd08c4d005..dde701d7f488 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -259,8 +259,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - Indicates if more responses are to follow. - * `matches` Integer (Optional) - Number of Matches. - * `selectionArea` Object (Optional) - Coordinates of first match region. + * `matches` Integer (optional) - Number of Matches. + * `selectionArea` Object (optional) - Coordinates of first match region. Emitted when a result is available for [`webContents.findInPage`](web-contents.md#webcontentsfindinpage) request. @@ -310,7 +310,7 @@ The `webContents` object has the following instance methods: ### `webContents.loadURL(url[, options])` * `url` URL -* `options` Object (optional), properties: +* `options` Object (optional) * `httpReferrer` String - A HTTP Referrer url. * `userAgent` String - A user agent originating the request. * `extraHeaders` String - Extra headers separated by "\n" @@ -503,7 +503,7 @@ Inserts `text` to the focused element. ### `webContents.findInPage(text[, options])` * `text` String - Content to be searched, must not be empty. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - Whether to search forward or backward, defaults to `true`. * `findNext` Boolean - Whether the operation is first request or a follow up, defaults to `false`. @@ -556,11 +556,10 @@ when the JS promise is rejected. ### `webContents.print([options])` -`options` Object (optional), properties: - -* `silent` Boolean - Don't ask user for print settings, defaults to `false` -* `printBackground` Boolean - Also prints the background color and image of - the web page, defaults to `false`. +* `options` Object (optional) + * `silent` Boolean - Don't ask user for print settings. Default is `false`. + * `printBackground` Boolean - Also prints the background color and image of + the web page. Default is `false`. Prints window's web page. When `silent` is set to `false`, Electron will pick up system's default printer and default settings for printing. @@ -574,31 +573,22 @@ size. ### `webContents.printToPDF(options, callback)` -`options` Object, properties: - -* `marginsType` Integer - Specify the type of margins to use - * 0 - default - * 1 - none - * 2 - minimum -* `pageSize` String - Specify page size of the generated PDF. - * `A5` - * `A4` - * `A3` - * `Legal` - * `Letter` - * `Tabloid` -* `printBackground` Boolean - Whether to print CSS backgrounds. -* `printSelectionOnly` Boolean - Whether to print selection only. -* `landscape` Boolean - `true` for landscape, `false` for portrait. - -`callback` Function - `function(error, data) {}` - -* `error` Error -* `data` Buffer - PDF file content. +* `options` Object + * `marginsType` Integer - Specifies the type of margins to use. Uses 0 for + default margin, 1 for no margin, and 2 for minimum margin. + * `pageSize` String - Specify page size of the generated PDF. Can be `A3`, + `A4`, `A5`, `Legal`, `Letter` and `Tabloid`. + * `printBackground` Boolean - Whether to print CSS backgrounds. + * `printSelectionOnly` Boolean - Whether to print selection only. + * `landscape` Boolean - `true` for landscape, `false` for portrait. +* `callback` Function Prints window's web page as PDF with Chromium's preview printing custom settings. +The `callback` will be called with `callback(error, data)` on completion. The +`data` is a `Buffer` that contains the generated PDF data. + By default, an empty `options` will be regarded as: ```javascript @@ -651,7 +641,7 @@ Removes the specified path from DevTools workspace. ### `webContents.openDevTools([options])` -* `options` Object (optional). Properties: +* `options` Object (optional) * `detach` Boolean - opens DevTools in a new window Opens the devtools. @@ -693,8 +683,11 @@ Opens the developer tools for the service worker context. * `arg` (optional) Send an asynchronous message to renderer process via `channel`, you can also -send arbitrary arguments. The renderer process can handle the message by -listening to the `channel` event with the `ipcRenderer` module. +send arbitrary arguments. Arguments will be serialized in JSON internally and +hence no functions or prototype chain will be included. + +The renderer process can handle the message by listening to `channel` with the +`ipcRenderer` module. An example of sending messages from the main process to the renderer process: @@ -849,6 +842,10 @@ win.webContents.on('did-finish-load', function() { Returns the [session](session.md) object used by this webContents. +### `webContents.hostWebContents` + +Returns the `WebContents` that might own this `WebContents`. + ### `webContents.devToolsWebContents` Get the `WebContents` of DevTools for this `WebContents`. diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index c410287553ac..4a0697ad843d 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -184,7 +184,7 @@ webview.addEventListener("dom-ready", function() { ### `.loadURL(url[, options])` * `url` URL -* `options` Object (optional), properties: +* `options` Object (optional) * `httpReferrer` String - A HTTP Referrer url. * `userAgent` String - A user agent originating the request. * `extraHeaders` String - Extra headers separated by "\n" @@ -382,7 +382,7 @@ Inserts `text` to the focused element. ### `.findInPage(text[, options])` * `text` String - Content to be searched, must not be empty. -* `options` Object (Optional) +* `options` Object (optional) * `forward` Boolean - Whether to search forward or backward, defaults to `true`. * `findNext` Boolean - Whether the operation is first request or a follow up, defaults to `false`. @@ -438,6 +438,10 @@ Sends an input `event` to the page. See [webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent) for detailed description of `event` object. +### `.getWebContents()` + +Returns the [WebContents](web-contents.md) associated with this `webview`. + ## DOM events The following DOM events are available to the `webview` tag: @@ -522,7 +526,7 @@ Returns: * `explicitSet` Boolean Fired when page title is set during navigation. `explicitSet` is false when -title is synthesised from file url. +title is synthesized from file url. ### Event: 'page-favicon-updated' @@ -567,8 +571,8 @@ Returns: * `result` Object * `requestId` Integer * `finalUpdate` Boolean - Indicates if more responses are to follow. - * `matches` Integer (Optional) - Number of Matches. - * `selectionArea` Object (Optional) - Coordinates of first match region. + * `matches` Integer (optional) - Number of Matches. + * `selectionArea` Object (optional) - Coordinates of first match region. Fired when a result is available for [`webview.findInPage`](web-view-tag.md#webviewtagfindinpage) request. diff --git a/docs/faq/electron-faq.md b/docs/faq/electron-faq.md index 643bde7409b2..a58d31107b6d 100644 --- a/docs/faq/electron-faq.md +++ b/docs/faq/electron-faq.md @@ -18,6 +18,34 @@ New features of Node.js are usually brought by V8 upgrades, since Electron is using the V8 shipped by Chrome browser, the shiny new JavaScript feature of a new Node.js version is usually already in Electron. +## How to share data between web pages? + +To share data between web pages (the renderer processes) the simplest way is to +use HTML5 APIs which are already available in browsers. Good candidates are +[Storage API][storage], [`localStorage`][local-storage], +[`sessionStorage`][session-storage], and [IndexedDB][indexed-db]. + +Or you can use the IPC system, which are specific to Electron, to store objects +in the main process as a global variable, and then to access them from the +renderers through the `remote` module: + +```javascript +// In the main process. +global.sharedObject = { + someProperty: 'default value' +}; +``` + +```javascript +// In page 1. +require('remote').getGlobal('sharedObject').someProperty = 'new value'; +``` + +```javascript +// In page 2. +console.log(require('remote').getGlobal('sharedObject').someProperty); +``` + ## My app's window/tray disappeared after a few minutes. This happens when the variable which is used to store the window/tray gets @@ -120,3 +148,7 @@ is only available in renderer processes. [memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management [variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx [electron-module]: https://www.npmjs.com/package/electron +[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage +[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage +[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage +[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API diff --git a/docs/tutorial/desktop-environment-integration.md b/docs/tutorial/desktop-environment-integration.md index 7d7eb44ecb6e..a72d68b3cf30 100644 --- a/docs/tutorial/desktop-environment-integration.md +++ b/docs/tutorial/desktop-environment-integration.md @@ -271,6 +271,33 @@ var window = new BrowserWindow({...}); window.setProgressBar(0.5); ``` +## Icon Overlays in Taskbar (Windows) + +On Windows a taskbar button can use a small overlay to display application +status, as quoted from MSDN: + +> Icon overlays serve as a contextual notification of status, and are intended +> to negate the need for a separate notification area status icon to communicate +> that information to the user. For instance, the new mail status in Microsoft +> Outlook, currently shown in the notification area, can now be indicated +> through an overlay on the taskbar button. Again, you must decide during your +> development cycle which method is best for your application. Overlay icons are +> intended to supply important, long-standing status or notifications such as +> network status, messenger status, or new mail. The user should not be +> presented with constantly changing overlays or animations. + +__Overlay on taskbar button:__ + +![Overlay on taskbar button](https://i-msdn.sec.s-msft.com/dynimg/IC420441.png) + +To set the overlay icon for a window, you can use the +[BrowserWindow.setOverlayIcon][setoverlayicon] API: + +```javascript +var window = new BrowserWindow({...}); +window.setOverlayIcon('path/to/overlay.png', 'Description for overlay'); +``` + ## Represented File of Window (OS X) On OS X a window can set its represented file, so the file's icon can show in @@ -294,15 +321,16 @@ window.setRepresentedFilename('/etc/passwd'); window.setDocumentEdited(true); ``` -[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath -[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments -[setusertaskstasks]: ../api/app.md#appsetusertaskstasks -[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress -[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename -[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited +[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-os-x-windows +[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-os-x-windows +[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows +[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress +[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows-7 +[setrepresentedfilename]: ../api/browser-window.md#winsetrepresentedfilenamefilename-os-x +[setdocumentedited]: ../api/browser-window.md#winsetdocumenteditededited-os-x [app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx [unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher -[setthumbarbuttons]: ../api/browser-window.md#browserwindowsetthumbarbuttonsbuttons +[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows-7 [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [notification-spec]: https://developer.gnome.org/notification-spec/ diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index ebf907e070f2..684c72c6669e 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -34,8 +34,8 @@ The main process creates web pages by creating `BrowserWindow` instances. Each is also terminated. The main process manages all web pages and their corresponding renderer -processes. Each renderer process is isolated and only cares -about the web page running in it. +processes. Each renderer process is isolated and only cares about the web page +running in it. In web pages, calling native GUI related APIs is not allowed because managing native GUI resources in web pages is very dangerous and it is easy to leak @@ -43,9 +43,11 @@ resources. If you want to perform GUI operations in a web page, the renderer process of the web page must communicate with the main process to request that the main process perform those operations. -In Electron, we have provided the [ipc](../api/ipc-renderer.md) module for -communication between the main process and renderer process. There is also a -[remote](../api/remote.md) module for RPC style communication. +In Electron, we have several ways to communicate between the main process and +renderer processes. Like [`ipcRenderer`](../api/ipc-renderer.md) and +[`ipcMain`](../api/ipc-main.md) modules for sending messages, and the +[remote](../api/remote.md) module for RPC style communication. There is also +an FAQ entry on [how to share data between web pages][share-data]. ## Write your First Electron App @@ -205,3 +207,5 @@ $ cd electron-quick-start # Install dependencies and run the app $ npm install && npm start ``` + +[share-data]: ../faq/electron-faq.md#how-to-share-data-between-web-pages diff --git a/docs/tutorial/using-selenium-and-webdriver.md b/docs/tutorial/using-selenium-and-webdriver.md index 035dabdfe79f..2d296548dd9c 100644 --- a/docs/tutorial/using-selenium-and-webdriver.md +++ b/docs/tutorial/using-selenium-and-webdriver.md @@ -49,7 +49,7 @@ var driver = new webdriver.Builder() .withCapabilities({ chromeOptions: { // Here is the path to your Electron binary. - binary: '/Path-to-Your-App.app/Contents/MacOS/Atom', + binary: '/Path-to-Your-App.app/Contents/MacOS/Electron', } }) .forBrowser('electron') diff --git a/docs/tutorial/using-widevine-cdm-plugin.md b/docs/tutorial/using-widevine-cdm-plugin.md index 340dad343c8a..630c18ab8e5f 100644 --- a/docs/tutorial/using-widevine-cdm-plugin.md +++ b/docs/tutorial/using-widevine-cdm-plugin.md @@ -8,6 +8,10 @@ Electron doesn't ship with the Widevine CDM plugin for license reasons, to get it, you need to install the official Chrome browser first, which should match the architecture and Chrome version of the Electron build you use. +__Note:__ The major version of Chrome browser has to be the same with the Chrome +version used by Electron, otherwise the plugin will not work even though +`navigator.plugins` would show it has been loaded. + ### Windows & OS X Open `chrome://components/` in Chrome browser, find `WidevineCdm` and make diff --git a/filenames.gypi b/filenames.gypi index a5369570cade..abb114532106 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -41,6 +41,7 @@ 'atom/common/api/lib/clipboard.js', 'atom/common/api/lib/crash-reporter.js', 'atom/common/api/lib/deprecate.js', + 'atom/common/api/lib/deprecations.js', 'atom/common/api/lib/exports/electron.js', 'atom/common/api/lib/native-image.js', 'atom/common/api/lib/shell.js', diff --git a/package.json b/package.json index 6d8120871991..e6d399fb3be4 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "name": "electron", - "version": "0.36.7", + "version": "0.36.8", "devDependencies": { - "asar": "^0.9.0", - "eslint": "^1.10.3", + "asar": "^0.10.0", + "eslint": "^2.1.0", "request": "*" }, "optionalDependencies": { diff --git a/script/create-dist.py b/script/create-dist.py index a619e04d3ea0..32d8f52aff37 100755 --- a/script/create-dist.py +++ b/script/create-dist.py @@ -38,6 +38,7 @@ TARGET_BINARIES = { 'libGLESv2.dll', 'msvcp120.dll', 'msvcr120.dll', + 'ffmpeg.dll', 'node.dll', 'pdf.dll', 'content_resources_200_percent.pak', @@ -51,6 +52,7 @@ TARGET_BINARIES = { PROJECT_NAME, # 'electron' 'content_shell.pak', 'icudtl.dat', + 'libffmpeg.so', 'libnode.so', 'natives_blob.bin', 'snapshot_blob.bin', @@ -97,6 +99,7 @@ def main(): create_dist_zip() create_chrome_binary_zip('chromedriver', get_chromedriver_version()) create_chrome_binary_zip('mksnapshot', ATOM_SHELL_VERSION) + create_ffmpeg_zip() create_symbols_zip() @@ -203,6 +206,24 @@ def create_chrome_binary_zip(binary, version): make_zip(zip_file, files, []) +def create_ffmpeg_zip(): + dist_name = 'ffmpeg-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name) + + if PLATFORM == 'darwin': + ffmpeg_name = 'libffmpeg.dylib' + elif PLATFORM == 'linux': + ffmpeg_name = 'libffmpeg.so' + elif PLATFORM == 'win32': + ffmpeg_name = 'ffmpeg.dll' + + shutil.copy2(os.path.join(CHROMIUM_DIR, '..', 'ffmpeg', ffmpeg_name), + DIST_DIR) + with scoped_cwd(DIST_DIR): + make_zip(zip_file, [ffmpeg_name, 'LICENSE', 'LICENSES.chromium.html'], []) + + def create_symbols_zip(): dist_name = '{0}-{1}-{2}-{3}-symbols.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, diff --git a/script/eslint.py b/script/eslint.py index 8fa2c3a7e3a7..7b912e0e1d6c 100755 --- a/script/eslint.py +++ b/script/eslint.py @@ -4,6 +4,7 @@ import glob import os import sys +from lib.config import PLATFORM from lib.util import execute @@ -13,6 +14,10 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) def main(): os.chdir(SOURCE_ROOT) + # Skip eslint on our Windows build machine for now. + if PLATFORM == 'win32' and os.getenv('JANKY_SHA1'): + return + eslint = os.path.join(SOURCE_ROOT, 'node_modules', '.bin', 'eslint') if sys.platform in ['win32', 'cygwin']: eslint += '.cmd' diff --git a/script/lib/config.py b/script/lib/config.py index 279fa7340a96..e3404918ce4e 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'https://s3.amazonaws.com/github-janky-artifacts/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = 'ad63d8ba890bcaad2f1b7e6de148b7992f4d3af7' +LIBCHROMIUMCONTENT_COMMIT = '599c8941e1884e155218ec1013cba9fc5c7c7072' PLATFORM = { 'cygwin': 'win32', diff --git a/script/upload.py b/script/upload.py index 3245d9caaa76..d23bc554c3cc 100755 --- a/script/upload.py +++ b/script/upload.py @@ -35,9 +35,6 @@ DSYM_NAME = '{0}-{1}-{2}-{3}-dsym.zip'.format(PROJECT_NAME, ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) -MKSNAPSHOT_NAME = 'mksnapshot-{0}-{1}-{2}.zip'.format(ATOM_SHELL_VERSION, - get_platform_key(), - get_target_arch()) def main(): @@ -89,12 +86,19 @@ def main(): if PLATFORM == 'darwin': upload_atom_shell(github, release, os.path.join(DIST_DIR, DSYM_NAME)) + # Upload free version of ffmpeg. + ffmpeg = 'ffmpeg-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + upload_atom_shell(github, release, os.path.join(DIST_DIR, ffmpeg)) + # Upload chromedriver and mksnapshot for minor version update. if parse_version(args.version)[2] == '0': chromedriver = 'chromedriver-{0}-{1}-{2}.zip'.format( get_chromedriver_version(), get_platform_key(), get_target_arch()) upload_atom_shell(github, release, os.path.join(DIST_DIR, chromedriver)) - upload_atom_shell(github, release, os.path.join(DIST_DIR, MKSNAPSHOT_NAME)) + mksnapshot = 'mksnapshot-{0}-{1}-{2}.zip'.format( + ATOM_SHELL_VERSION, get_platform_key(), get_target_arch()) + upload_atom_shell(github, release, os.path.join(DIST_DIR, mksnapshot)) if PLATFORM == 'win32' and not tag_exists: # Upload node headers. diff --git a/spec/api-app-spec.js b/spec/api-app-spec.js index 0019ec59d5f0..cbf8223401ce 100644 --- a/spec/api-app-spec.js +++ b/spec/api-app-spec.js @@ -1,14 +1,10 @@ -var BrowserWindow, ChildProcess, app, assert, path, ref, remote; +const assert = require('assert'); +const ChildProcess = require('child_process'); +const path = require('path'); +const remote = require('electron').remote; -assert = require('assert'); - -ChildProcess = require('child_process'); - -path = require('path'); - -remote = require('electron').remote; - -ref = remote.require('electron'), app = ref.app, BrowserWindow = ref.BrowserWindow; +const app = remote.require('electron').app; +const BrowserWindow = remote.require('electron').BrowserWindow; describe('electron module', function() { it ('can prevent exposing internal modules to require', function(done) { @@ -27,100 +23,109 @@ describe('electron module', function() { describe('app module', function() { describe('app.getVersion()', function() { - return it('returns the version field of package.json', function() { - return assert.equal(app.getVersion(), '0.1.0'); + it('returns the version field of package.json', function() { + assert.equal(app.getVersion(), '0.1.0'); }); }); + describe('app.setVersion(version)', function() { - return it('overrides the version', function() { + it('overrides the version', function() { assert.equal(app.getVersion(), '0.1.0'); app.setVersion('test-version'); assert.equal(app.getVersion(), 'test-version'); - return app.setVersion('0.1.0'); + app.setVersion('0.1.0'); }); }); + describe('app.getName()', function() { - return it('returns the name field of package.json', function() { - return assert.equal(app.getName(), 'Electron Test'); + it('returns the name field of package.json', function() { + assert.equal(app.getName(), 'Electron Test'); }); }); + describe('app.setName(name)', function() { - return it('overrides the name', function() { + it('overrides the name', function() { assert.equal(app.getName(), 'Electron Test'); app.setName('test-name'); assert.equal(app.getName(), 'test-name'); - return app.setName('Electron Test'); + app.setName('Electron Test'); }); }); + describe('app.getLocale()', function() { - return it('should not be empty', function() { - return assert.notEqual(app.getLocale(), ''); + it('should not be empty', function() { + assert.notEqual(app.getLocale(), ''); }); }); + describe('app.exit(exitCode)', function() { - var appProcess; - appProcess = null; + var appProcess = null; + afterEach(function() { - return appProcess != null ? appProcess.kill() : void 0; + appProcess != null ? appProcess.kill() : void 0; }); - return it('emits a process exit event with the code', function(done) { - var appPath, electronPath, output; - appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); - electronPath = remote.getGlobal('process').execPath; + + it('emits a process exit event with the code', function(done) { + var appPath = path.join(__dirname, 'fixtures', 'api', 'quit-app'); + var electronPath = remote.getGlobal('process').execPath; + var output = ''; appProcess = ChildProcess.spawn(electronPath, [appPath]); - output = ''; appProcess.stdout.on('data', function(data) { - return output += data; + output += data; }); - return appProcess.on('close', function(code) { + appProcess.on('close', function(code) { if (process.platform !== 'win32') { assert.notEqual(output.indexOf('Exit event with code: 123'), -1); } assert.equal(code, 123); - return done(); + done(); }); }); }); - return describe('BrowserWindow events', function() { - var w; - w = null; + + describe('BrowserWindow events', function() { + var w = null; + afterEach(function() { if (w != null) { w.destroy(); } - return w = null; + w = null; }); + it('should emit browser-window-focus event when window is focused', function(done) { app.once('browser-window-focus', function(e, window) { assert.equal(w.id, window.id); - return done(); + done(); }); w = new BrowserWindow({ show: false }); - return w.emit('focus'); + w.emit('focus'); }); + it('should emit browser-window-blur event when window is blured', function(done) { app.once('browser-window-blur', function(e, window) { assert.equal(w.id, window.id); - return done(); + done(); }); w = new BrowserWindow({ show: false }); - return w.emit('blur'); + w.emit('blur'); }); - return it('should emit browser-window-created event when window is created', function(done) { + + it('should emit browser-window-created event when window is created', function(done) { app.once('browser-window-created', function(e, window) { - return setImmediate(function() { + setImmediate(function() { assert.equal(w.id, window.id); - return done(); + done(); }); }); w = new BrowserWindow({ show: false }); - return w.emit('blur'); + w.emit('blur'); }); }); }); diff --git a/spec/api-auto-updater-spec.js b/spec/api-auto-updater-spec.js index 72a1d90a7fe4..efd3afe3882f 100644 --- a/spec/api-auto-updater-spec.js +++ b/spec/api-auto-updater-spec.js @@ -2,6 +2,10 @@ const assert = require('assert'); const autoUpdater = require('electron').remote.autoUpdater; const ipcRenderer = require('electron').ipcRenderer; +// Skip autoUpdater tests in MAS build. +if (process.mas) + return; + describe('autoUpdater module', function() { describe('checkForUpdates', function() { it('emits an error on Windows when called the feed URL is not set', function (done) { diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index d59eb9a8baa4..58cf57cc8d0c 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -8,6 +8,7 @@ const os = require('os'); const remote = require('electron').remote; const screen = require('electron').screen; +const app = remote.require('electron').app; const ipcMain = remote.require('electron').ipcMain; const BrowserWindow = remote.require('electron').BrowserWindow; @@ -41,9 +42,8 @@ describe('browser-window module', function() { w.close(); }); w.on('closed', function() { - var content, test; - test = path.join(fixtures, 'api', 'unload'); - content = fs.readFileSync(test); + var test = path.join(fixtures, 'api', 'unload'); + var content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'unload'); done(); @@ -65,9 +65,8 @@ describe('browser-window module', function() { describe('window.close()', function() { it('should emit unload handler', function(done) { w.on('closed', function() { - var content, test; - test = path.join(fixtures, 'api', 'close'); - content = fs.readFileSync(test); + var test = path.join(fixtures, 'api', 'close'); + var content = fs.readFileSync(test); fs.unlinkSync(test); assert.equal(String(content), 'close'); done(); @@ -85,8 +84,7 @@ describe('browser-window module', function() { describe('BrowserWindow.destroy()', function() { it('prevents users to access methods of webContents', function() { - var webContents; - webContents = w.webContents; + var webContents = w.webContents; w.destroy(); assert.throws((function() { webContents.getId(); @@ -102,12 +100,22 @@ describe('browser-window module', function() { w.loadURL('about:blank'); }); - it('should emit did-fail-load event', function(done) { - w.webContents.on('did-fail-load', function() { + it('should emit did-fail-load event for files that do not exist', function(done) { + w.webContents.on('did-fail-load', function(event, code) { + assert.equal(code, -6); done(); }); w.loadURL('file://a.txt'); }); + + it('should emit did-fail-load event for invalid URL', function(done) { + w.webContents.on('did-fail-load', function(event, code, desc) { + assert.equal(desc, 'ERR_INVALID_URL'); + assert.equal(code, -300); + done(); + }); + w.loadURL('http://example:port'); + }); }); describe('BrowserWindow.show()', function() { @@ -167,8 +175,7 @@ describe('browser-window module', function() { it('sets the window position', function(done) { var pos = [10, 10]; w.once('move', function() { - var newPos; - newPos = w.getPosition(); + var newPos = w.getPosition(); assert.equal(newPos[0], pos[0]); assert.equal(newPos[1], pos[1]); done(); @@ -179,16 +186,14 @@ describe('browser-window module', function() { describe('BrowserWindow.setContentSize(width, height)', function() { it('sets the content size', function() { - var after, size; - size = [400, 400]; + var size = [400, 400]; w.setContentSize(size[0], size[1]); - after = w.getContentSize(); + var after = w.getContentSize(); assert.equal(after[0], size[0]); assert.equal(after[1], size[1]); }); it('works for framless window', function() { - var after, size; w.destroy(); w = new BrowserWindow({ show: false, @@ -196,9 +201,9 @@ describe('browser-window module', function() { width: 400, height: 400 }); - size = [400, 400]; + var size = [400, 400]; w.setContentSize(size[0], size[1]); - after = w.getContentSize(); + var after = w.getContentSize(); assert.equal(after[0], size[0]); assert.equal(after[1], size[1]); }); @@ -212,7 +217,6 @@ describe('browser-window module', function() { describe('"useContentSize" option', function() { it('make window created with content size when used', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -220,7 +224,7 @@ describe('browser-window module', function() { height: 400, useContentSize: true }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); assert.equal(contentSize[1], 400); }); @@ -232,7 +236,6 @@ describe('browser-window module', function() { }); it('works for framless window', function() { - var contentSize, size; w.destroy(); w = new BrowserWindow({ show: false, @@ -241,10 +244,10 @@ describe('browser-window module', function() { height: 400, useContentSize: true }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[0], 400); assert.equal(contentSize[1], 400); - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 400); assert.equal(size[1], 400); }); @@ -259,7 +262,6 @@ describe('browser-window module', function() { } it('creates browser window with hidden title bar', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -267,12 +269,11 @@ describe('browser-window module', function() { height: 400, titleBarStyle: 'hidden' }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[1], 400); }); it('creates browser window with hidden inset title bar', function() { - var contentSize; w.destroy(); w = new BrowserWindow({ show: false, @@ -280,7 +281,7 @@ describe('browser-window module', function() { height: 400, titleBarStyle: 'hidden-inset' }); - contentSize = w.getContentSize(); + var contentSize = w.getContentSize(); assert.equal(contentSize[1], 400); }); }); @@ -301,20 +302,18 @@ describe('browser-window module', function() { }); it('can move the window out of screen', function() { - var after; w.setPosition(-10, -10); - after = w.getPosition(); + var after = w.getPosition(); assert.equal(after[0], -10); assert.equal(after[1], -10); }); it('can set the window larger than screen', function() { - var after, size; - size = screen.getPrimaryDisplay().size; + var size = screen.getPrimaryDisplay().size; size.width += 100; size.height += 100; w.setSize(size.width, size.height); - after = w.getSize(); + var after = w.getSize(); assert.equal(after[0], size.width); assert.equal(after[1], size.height); }); @@ -327,8 +326,7 @@ describe('browser-window module', function() { describe('"preload" option', function() { it('loads the script before other scripts in window', function(done) { - var preload; - preload = path.join(fixtures, 'module', 'set-global.js'); + var preload = path.join(fixtures, 'module', 'set-global.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'preload'); done(); @@ -346,8 +344,7 @@ describe('browser-window module', function() { describe('"node-integration" option', function() { it('disables node integration when specified to false', function(done) { - var preload; - preload = path.join(fixtures, 'module', 'send-later.js'); + var preload = path.join(fixtures, 'module', 'send-later.js'); ipcMain.once('answer', function(event, test) { assert.equal(test, 'undefined'); done(); @@ -468,10 +465,18 @@ describe('browser-window module', function() { }); }); - xdescribe('beginFrameSubscription method', function() { + describe('beginFrameSubscription method', function() { + this.timeout(20000); + it('subscribes frame updates', function(done) { + let called = false; w.loadURL("file://" + fixtures + "/api/blank.html"); w.webContents.beginFrameSubscription(function(data) { + // This callback might be called twice. + if (called) + return; + called = true; + assert.notEqual(data.length, 0); w.webContents.endFrameSubscription(); done(); @@ -513,10 +518,9 @@ describe('browser-window module', function() { describe('BrowserWindow options argument is optional', function() { it('should create a window with default size (800x600)', function() { - var size; w.destroy(); w = new BrowserWindow(); - size = w.getSize(); + var size = w.getSize(); assert.equal(size[0], 800); assert.equal(size[1], 600); }); @@ -670,4 +674,20 @@ describe('browser-window module', function() { }, 'Missing required channel argument'); }); }); + + describe('dev tool extensions', function () { + it('serializes the registered extensions on quit', function () { + var extensionName = 'foo'; + var extensionPath = path.join(__dirname, 'fixtures', 'devtools-extensions', extensionName); + var serializedPath = path.join(app.getPath('userData'), 'DevTools Extensions'); + + BrowserWindow.addDevToolsExtension(extensionPath); + app.emit('will-quit'); + assert.deepEqual(JSON.parse(fs.readFileSync(serializedPath)), [extensionPath]); + + BrowserWindow.removeDevToolsExtension(extensionName); + app.emit('will-quit'); + assert.equal(fs.existsSync(serializedPath), false); + }); + }); }); diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index fe94e330d414..0b4a9f9521cf 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -1,55 +1,53 @@ -var assert, clipboard, nativeImage, path, ref; +const assert = require('assert'); +const path = require('path'); -assert = require('assert'); - -path = require('path'); - -ref = require('electron'), clipboard = ref.clipboard, nativeImage = ref.nativeImage; +const clipboard = require('electron').clipboard; +const nativeImage = require('electron').nativeImage; describe('clipboard module', function() { - var fixtures; - fixtures = path.resolve(__dirname, 'fixtures'); + var fixtures = path.resolve(__dirname, 'fixtures'); + describe('clipboard.readImage()', function() { - return it('returns NativeImage intance', function() { - var i, p; - p = path.join(fixtures, 'assets', 'logo.png'); - i = nativeImage.createFromPath(p); + it('returns NativeImage intance', function() { + var p = path.join(fixtures, 'assets', 'logo.png'); + var i = nativeImage.createFromPath(p); clipboard.writeImage(p); - return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); + assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); + describe('clipboard.readText()', function() { - return it('returns unicode string correctly', function() { - var text; - text = '千江有水千江月,万里无云万里天'; + it('returns unicode string correctly', function() { + var text = '千江有水千江月,万里无云万里天'; clipboard.writeText(text); - return assert.equal(clipboard.readText(), text); + assert.equal(clipboard.readText(), text); }); }); + describe('clipboard.readHtml()', function() { - return it('returns markup correctly', function() { - var markup, text; - text = 'Hi'; - markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; + it('returns markup correctly', function() { + var text = 'Hi'; + var markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; clipboard.writeHtml(text); - return assert.equal(clipboard.readHtml(), markup); + assert.equal(clipboard.readHtml(), markup); }); }); + describe('clipboard.readRtf', function() { - return it('returns rtf text correctly', function() { + it('returns rtf text correctly', function() { var rtf = "{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}"; clipboard.writeRtf(rtf); - return assert.equal(clipboard.readRtf(), rtf); + assert.equal(clipboard.readRtf(), rtf); }); }); - return describe('clipboard.write()', function() { - return it('returns data correctly', function() { - var i, markup, p, text, rtf; - text = 'test'; - rtf = '{\\rtf1\\utf8 text}'; - p = path.join(fixtures, 'assets', 'logo.png'); - i = nativeImage.createFromPath(p); - markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; + + describe('clipboard.write()', function() { + it('returns data correctly', function() { + var text = 'test'; + var rtf = '{\\rtf1\\utf8 text}'; + var p = path.join(fixtures, 'assets', 'logo.png'); + var i = nativeImage.createFromPath(p); + var markup = process.platform === 'darwin' ? 'Hi' : process.platform === 'linux' ? 'Hi' : 'Hi'; clipboard.write({ text: "test", html: 'Hi', @@ -59,7 +57,7 @@ describe('clipboard module', function() { assert.equal(clipboard.readText(), text); assert.equal(clipboard.readHtml(), markup); assert.equal(clipboard.readRtf(), rtf); - return assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); + assert.equal(clipboard.readImage().toDataURL(), i.toDataURL()); }); }); }); diff --git a/spec/api-crash-reporter-spec.js b/spec/api-crash-reporter-spec.js index b3c4c3115896..68dc1375fc39 100644 --- a/spec/api-crash-reporter-spec.js +++ b/spec/api-crash-reporter-spec.js @@ -1,47 +1,45 @@ -var BrowserWindow, app, assert, crashReporter, http, multiparty, path, ref, remote, url; +const assert = require('assert'); +const http = require('http'); +const multiparty = require('multiparty'); +const path = require('path'); +const url = require('url'); -assert = require('assert'); - -path = require('path'); - -http = require('http'); - -url = require('url'); - -multiparty = require('multiparty'); - -remote = require('electron').remote; - -ref = remote.require('electron'), app = ref.app, crashReporter = ref.crashReporter, BrowserWindow = ref.BrowserWindow; +const remote = require('electron').remote; +const app = remote.require('electron').app; +const crashReporter = remote.require('electron').crashReporter; +const BrowserWindow = remote.require('electron').BrowserWindow; describe('crash-reporter module', function() { - var fixtures, isCI, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false }); }); + afterEach(function() { - return w.destroy(); + w.destroy(); }); + if (process.mas) { return; } - isCI = remote.getGlobal('isCi'); + + var isCI = remote.getGlobal('isCi'); if (isCI) { return; } + it('should send minidump when renderer crashes', function(done) { - var called, port, server; this.timeout(120000); - called = false; - server = http.createServer(function(req, res) { - var form; + + var called = false; + var server = http.createServer(function(req, res) { server.close(); - form = new multiparty.Form(); - return form.parse(req, function(error, fields) { + var form = new multiparty.Form(); + form.parse(req, function(error, fields) { if (called) { return; } @@ -56,14 +54,14 @@ describe('crash-reporter module', function() { assert.equal(fields['_companyName'], 'Umbrella Corporation'); assert.equal(fields['_version'], app.getVersion()); res.end('abc-123-def'); - return done(); + done(); }); }); - port = remote.process.port; - return server.listen(port, '127.0.0.1', function() { + var port = remote.process.port; + server.listen(port, '127.0.0.1', function() { port = server.address().port; remote.process.port = port; - url = url.format({ + const crashUrl = url.format({ protocol: 'file', pathname: path.join(fixtures, 'api', 'crash.html'), search: "?port=" + port @@ -74,18 +72,19 @@ describe('crash-reporter module', function() { submitURL: "http://127.0.0.1:" + port }); } - return w.loadURL(url); + w.loadURL(crashUrl); }); }); - return describe(".start(options)", function() { - return it('requires that the companyName and submitURL options be specified', function() { + + describe(".start(options)", function() { + it('requires that the companyName and submitURL options be specified', function() { assert.throws(function() { - return crashReporter.start({ + crashReporter.start({ companyName: 'Missing submitURL' }); }); - return assert.throws(function() { - return crashReporter.start({ + assert.throws(function() { + crashReporter.start({ submitURL: 'Missing companyName' }); }); diff --git a/spec/api-debugger-spec.js b/spec/api-debugger-spec.js index 7a16ca7263c0..56b642e76e43 100644 --- a/spec/api-debugger-spec.js +++ b/spec/api-debugger-spec.js @@ -1,17 +1,11 @@ -var assert, path, remote, BrowserWindow; - -assert = require('assert'); - -path = require('path'); - -remote = require('electron').remote; - -BrowserWindow = remote.BrowserWindow; +const assert = require('assert'); +const path = require('path'); +const BrowserWindow = require('electron').remote.BrowserWindow; describe('debugger module', function() { - var fixtures, w; - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + beforeEach(function() { if (w != null) { w.destroy(); @@ -22,6 +16,7 @@ describe('debugger module', function() { height: 400 }); }); + afterEach(function() { if (w != null) { w.destroy(); @@ -100,7 +95,9 @@ describe('debugger module', function() { }); it('fires message event', function(done) { - var url = 'file://' + path.join(fixtures, 'pages', 'a.html'); + var url = process.platform != 'win32' ? + 'file://' + path.join(fixtures, 'pages', 'a.html') : + 'file:///' + path.join(fixtures, 'pages', 'a.html').replace(/\\/g, '/'); w.webContents.loadURL(url); try { w.webContents.debugger.attach(); diff --git a/spec/api-deprecations-spec.js b/spec/api-deprecations-spec.js new file mode 100644 index 000000000000..2f0100590598 --- /dev/null +++ b/spec/api-deprecations-spec.js @@ -0,0 +1,27 @@ +const assert = require('assert'); +const deprecations = require('electron').deprecations; + +describe('deprecations', function() { + beforeEach(function() { + deprecations.setHandler(null); + process.throwDeprecation = true; + }); + + it('allows a deprecation handler function to be specified', function() { + var messages = []; + + deprecations.setHandler(function (message) { + messages.push(message); + }); + + require('electron').webFrame.registerUrlSchemeAsSecure('some-scheme'); + + assert.deepEqual(messages, ['registerUrlSchemeAsSecure is deprecated. Use registerURLSchemeAsSecure instead.']); + }); + + it('throws an exception if no deprecation handler is specified', function() { + assert.throws(function() { + require('electron').webFrame.registerUrlSchemeAsPrivileged('some-scheme'); + }, "registerUrlSchemeAsPrivileged is deprecated. Use registerURLSchemeAsPrivileged instead."); + }); +}); diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 66f392a577c9..90e099fa612e 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -1,145 +1,191 @@ -var BrowserWindow, assert, comparePaths, ipcMain, ipcRenderer, path, ref, ref1, remote; +'use strict'; -assert = require('assert'); +const assert = require('assert'); +const path = require('path'); -path = require('path'); +const ipcRenderer = require('electron').ipcRenderer; +const remote = require('electron').remote; -ref = require('electron'), ipcRenderer = ref.ipcRenderer, remote = ref.remote; +const ipcMain = remote.require('electron').ipcMain; +const BrowserWindow = remote.require('electron').BrowserWindow; -ref1 = remote.require('electron'), ipcMain = ref1.ipcMain, BrowserWindow = ref1.BrowserWindow; - -comparePaths = function(path1, path2) { +const comparePaths = function(path1, path2) { if (process.platform === 'win32') { path1 = path1.toLowerCase(); path2 = path2.toLowerCase(); } - return assert.equal(path1, path2); + assert.equal(path1, path2); }; describe('ipc module', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('remote.require', function() { it('should returns same object for the same module', function() { - var dialog1, dialog2; - dialog1 = remote.require('electron'); - dialog2 = remote.require('electron'); - return assert.equal(dialog1, dialog2); + var dialog1 = remote.require('electron'); + var dialog2 = remote.require('electron'); + assert.equal(dialog1, dialog2); }); + it('should work when object contains id property', function() { - var a; - a = remote.require(path.join(fixtures, 'module', 'id.js')); - return assert.equal(a.id, 1127); + var a = remote.require(path.join(fixtures, 'module', 'id.js')); + assert.equal(a.id, 1127); }); - return it('should search module from the user app', function() { + + it('should search module from the user app', function() { comparePaths(path.normalize(remote.process.mainModule.filename), path.resolve(__dirname, 'static', 'main.js')); - return comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); + comparePaths(path.normalize(remote.process.mainModule.paths[0]), path.resolve(__dirname, 'static', 'node_modules')); }); }); + describe('remote.createFunctionWithReturnValue', function() { - return it('should be called in browser synchronously', function() { - var buf, call, result; - buf = new Buffer('test'); - call = remote.require(path.join(fixtures, 'module', 'call.js')); - result = call.call(remote.createFunctionWithReturnValue(buf)); - return assert.equal(result.constructor.name, 'Buffer'); + it('should be called in browser synchronously', function() { + var buf = new Buffer('test'); + var call = remote.require(path.join(fixtures, 'module', 'call.js')); + var result = call.call(remote.createFunctionWithReturnValue(buf)); + assert.equal(result.constructor.name, 'Buffer'); }); }); + describe('remote object in renderer', function() { it('can change its properties', function() { - var property, property2; - property = remote.require(path.join(fixtures, 'module', 'property.js')); + var property = remote.require(path.join(fixtures, 'module', 'property.js')); assert.equal(property.property, 1127); property.property = 1007; assert.equal(property.property, 1007); - property2 = remote.require(path.join(fixtures, 'module', 'property.js')); + var property2 = remote.require(path.join(fixtures, 'module', 'property.js')); assert.equal(property2.property, 1007); - return property.property = 1127; + property.property = 1127; }); - return it('can construct an object from its member', function() { - var call, obj; - call = remote.require(path.join(fixtures, 'module', 'call.js')); - obj = new call.constructor; - return assert.equal(obj.test, 'test'); + + it('can construct an object from its member', function() { + var call = remote.require(path.join(fixtures, 'module', 'call.js')); + var obj = new call.constructor; + assert.equal(obj.test, 'test'); }); }); + describe('remote value in browser', function() { - var print; - print = path.join(fixtures, 'module', 'print_name.js'); + var print = path.join(fixtures, 'module', 'print_name.js'); + it('keeps its constructor name for objects', function() { - var buf, print_name; - buf = new Buffer('test'); - print_name = remote.require(print); - return assert.equal(print_name.print(buf), 'Buffer'); + var buf = new Buffer('test'); + var print_name = remote.require(print); + assert.equal(print_name.print(buf), 'Buffer'); }); - return it('supports instanceof Date', function() { - var now, print_name; - now = new Date(); - print_name = remote.require(print); + + it('supports instanceof Date', function() { + var now = new Date(); + var print_name = remote.require(print); assert.equal(print_name.print(now), 'Date'); - return assert.deepEqual(print_name.echo(now), now); + assert.deepEqual(print_name.echo(now), now); }); }); + describe('remote promise', function() { - return it('can be used as promise in each side', function(done) { - var promise; - promise = remote.require(path.join(fixtures, 'module', 'promise.js')); - return promise.twicePromise(Promise.resolve(1234)).then(function(value) { + it('can be used as promise in each side', function(done) { + var promise = remote.require(path.join(fixtures, 'module', 'promise.js')); + promise.twicePromise(Promise.resolve(1234)).then(function(value) { assert.equal(value, 2468); - return done(); + done(); }); }); }); + + describe('remote webContents', function() { + it('can return same object with different getters', function() { + var contents1 = remote.getCurrentWindow().webContents; + var contents2 = remote.getCurrentWebContents(); + assert(contents1 == contents2); + }); + }); + + describe('remote class', function() { + let cl = remote.require(path.join(fixtures, 'module', 'class.js')); + let base = cl.base; + let derived = cl.derived; + + it('can get methods', function() { + assert.equal(base.method(), 'method'); + }); + + it('can get properties', function() { + assert.equal(base.readonly, 'readonly'); + }); + + it('can change properties', function() { + assert.equal(base.value, 'old'); + base.value = 'new'; + assert.equal(base.value, 'new'); + base.value = 'old'; + }); + + it('has unenumerable methods', function() { + assert(!base.hasOwnProperty('method')); + assert(Object.getPrototypeOf(base).hasOwnProperty('method')); + }); + + it('keeps prototype chain in derived class', function() { + assert.equal(derived.method(), 'method'); + assert.equal(derived.readonly, 'readonly'); + assert(!derived.hasOwnProperty('method')); + let proto = Object.getPrototypeOf(derived); + assert(!proto.hasOwnProperty('method')); + assert(Object.getPrototypeOf(proto).hasOwnProperty('method')); + }); + }); + describe('ipc.sender.send', function() { - return it('should work when sending an object containing id property', function(done) { - var obj; - obj = { + it('should work when sending an object containing id property', function(done) { + var obj = { id: 1, name: 'ly' }; ipcRenderer.once('message', function(event, message) { assert.deepEqual(message, obj); - return done(); + done(); }); - return ipcRenderer.send('message', obj); + ipcRenderer.send('message', obj); }); }); + describe('ipc.sendSync', function() { it('can be replied by setting event.returnValue', function() { - var msg; - msg = ipcRenderer.sendSync('echo', 'test'); - return assert.equal(msg, 'test'); + var msg = ipcRenderer.sendSync('echo', 'test'); + assert.equal(msg, 'test'); }); - return it('does not crash when reply is not sent and browser is destroyed', function(done) { - var w; + + it('does not crash when reply is not sent and browser is destroyed', function(done) { this.timeout(10000); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false }); ipcMain.once('send-sync-message', function(event) { event.returnValue = null; w.destroy(); - return done(); + done(); }); - return w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); + w.loadURL('file://' + path.join(fixtures, 'api', 'send-sync-message.html')); }); }); - return describe('remote listeners', function() { - var w; - w = null; + + describe('remote listeners', function() { + var w = null; + afterEach(function() { - return w.destroy(); + w.destroy(); }); - return it('can be added and removed correctly', function() { - var listener; + + it('can be added and removed correctly', function() { w = new BrowserWindow({ show: false }); - listener = function() {}; + var listener = function() {}; w.on('test', listener); assert.equal(w.listenerCount('test'), 1); w.removeListener('test', listener); - return assert.equal(w.listenerCount('test'), 0); + assert.equal(w.listenerCount('test'), 0); }); }); }); diff --git a/spec/api-menu-spec.js b/spec/api-menu-spec.js index 5771358337e4..b27840ec4f2e 100644 --- a/spec/api-menu-spec.js +++ b/spec/api-menu-spec.js @@ -1,27 +1,26 @@ -var Menu, MenuItem, assert, ipcRenderer, ref, ref1, remote; +const assert = require('assert'); -assert = require('assert'); +const remote = require('electron').remote; +const ipcRenderer = require('electron').ipcRenderer; -ref = require('electron'), remote = ref.remote, ipcRenderer = ref.ipcRenderer; - -ref1 = remote.require('electron'), Menu = ref1.Menu, MenuItem = ref1.MenuItem; +const Menu = remote.require('electron').Menu; +const MenuItem = remote.require('electron').MenuItem; describe('menu module', function() { describe('Menu.buildFromTemplate', function() { it('should be able to attach extra fields', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', extra: 'field' } ]); - return assert.equal(menu.items[0].extra, 'field'); + assert.equal(menu.items[0].extra, 'field'); }); + it('does not modify the specified template', function() { - var template; - template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); - return assert.deepStrictEqual(template, [ + var template = ipcRenderer.sendSync('eval', "var template = [{label: 'text', submenu: [{label: 'sub'}]}];\nrequire('electron').Menu.buildFromTemplate(template);\ntemplate;"); + assert.deepStrictEqual(template, [ { label: 'text', submenu: [ @@ -32,10 +31,10 @@ describe('menu module', function() { } ]); }); - return describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { + + describe('Menu.buildFromTemplate should reorder based on item position specifiers', function() { it('should position before existing item', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '2', id: '2' @@ -50,11 +49,11 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, '2'); - return assert.equal(menu.items[2].label, '3'); + assert.equal(menu.items[2].label, '3'); }); + it('should position after existing item', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: '1', id: '1' @@ -69,11 +68,11 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, '2'); - return assert.equal(menu.items[2].label, '3'); + assert.equal(menu.items[2].label, '3'); }); + it('should position at endof existing separator groups', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { type: 'separator', id: 'numbers' @@ -113,11 +112,11 @@ describe('menu module', function() { assert.equal(menu.items[4].id, 'letters'); assert.equal(menu.items[5].label, 'a'); assert.equal(menu.items[6].label, 'b'); - return assert.equal(menu.items[7].label, 'c'); + assert.equal(menu.items[7].label, 'c'); }); + it('should create separator group if endof does not reference existing separator group', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'a', id: 'a', @@ -151,11 +150,11 @@ describe('menu module', function() { assert.equal(menu.items[4].id, 'numbers'); assert.equal(menu.items[5].label, '1'); assert.equal(menu.items[6].label, '2'); - return assert.equal(menu.items[7].label, '3'); + assert.equal(menu.items[7].label, '3'); }); - return it('should continue inserting items at next index when no specifier is present', function() { - var menu; - menu = Menu.buildFromTemplate([ + + it('should continue inserting items at next index when no specifier is present', function() { + var menu = Menu.buildFromTemplate([ { label: '4', id: '4' @@ -178,14 +177,14 @@ describe('menu module', function() { assert.equal(menu.items[1].label, '2'); assert.equal(menu.items[2].label, '3'); assert.equal(menu.items[3].label, '4'); - return assert.equal(menu.items[4].label, '5'); + assert.equal(menu.items[4].label, '5'); }); }); }); + describe('Menu.insert', function() { - return it('should store item in @items by its index', function() { - var item, menu; - menu = Menu.buildFromTemplate([ + it('should store item in @items by its index', function() { + var menu = Menu.buildFromTemplate([ { label: '1' }, { @@ -194,36 +193,36 @@ describe('menu module', function() { label: '3' } ]); - item = new MenuItem({ + var item = new MenuItem({ label: 'inserted' }); menu.insert(1, item); assert.equal(menu.items[0].label, '1'); assert.equal(menu.items[1].label, 'inserted'); assert.equal(menu.items[2].label, '2'); - return assert.equal(menu.items[3].label, '3'); + assert.equal(menu.items[3].label, '3'); }); }); + describe('MenuItem.click', function() { - return it('should be called with the item object passed', function(done) { - var menu; - menu = Menu.buildFromTemplate([ + it('should be called with the item object passed', function(done) { + var menu = Menu.buildFromTemplate([ { label: 'text', click: function(item) { assert.equal(item.constructor.name, 'MenuItem'); assert.equal(item.label, 'text'); - return done(); + done(); } } ]); - return menu.delegate.executeCommand(menu.items[0].commandId); + menu.delegate.executeCommand(menu.items[0].commandId); }); }); - return describe('MenuItem with checked property', function() { + + describe('MenuItem with checked property', function() { it('clicking an checkbox item should flip the checked property', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', type: 'checkbox' @@ -231,11 +230,11 @@ describe('menu module', function() { ]); assert.equal(menu.items[0].checked, false); menu.delegate.executeCommand(menu.items[0].commandId); - return assert.equal(menu.items[0].checked, true); + assert.equal(menu.items[0].checked, true); }); + it('clicking an radio item should always make checked property true', function() { - var menu; - menu = Menu.buildFromTemplate([ + var menu = Menu.buildFromTemplate([ { label: 'text', type: 'radio' @@ -244,8 +243,9 @@ describe('menu module', function() { menu.delegate.executeCommand(menu.items[0].commandId); assert.equal(menu.items[0].checked, true); menu.delegate.executeCommand(menu.items[0].commandId); - return assert.equal(menu.items[0].checked, true); + assert.equal(menu.items[0].checked, true); }); + it('at least have one item checked in each group', function() { var i, j, k, menu, template; template = []; @@ -267,10 +267,11 @@ describe('menu module', function() { menu = Menu.buildFromTemplate(template); menu.delegate.menuWillShow(); assert.equal(menu.items[0].checked, true); - return assert.equal(menu.items[12].checked, true); + assert.equal(menu.items[12].checked, true); }); + it('should assign groupId automatically', function() { - var groupId, i, j, k, l, m, menu, results, template; + var groupId, i, j, k, l, m, menu, template; template = []; for (i = j = 0; j <= 10; i = ++j) { template.push({ @@ -292,14 +293,13 @@ describe('menu module', function() { for (i = l = 0; l <= 10; i = ++l) { assert.equal(menu.items[i].groupId, groupId); } - results = []; for (i = m = 12; m <= 20; i = ++m) { - results.push(assert.equal(menu.items[i].groupId, groupId + 1)); + assert.equal(menu.items[i].groupId, groupId + 1); } - return results; }); - return it("setting 'checked' should flip other items' 'checked' property", function() { - var i, j, k, l, m, menu, n, o, p, q, results, template; + + it("setting 'checked' should flip other items' 'checked' property", function() { + var i, j, k, l, m, menu, n, o, p, q, template; template = []; for (i = j = 0; j <= 10; i = ++j) { template.push({ @@ -339,11 +339,9 @@ describe('menu module', function() { assert.equal(menu.items[i].checked, false); } assert.equal(menu.items[12].checked, true); - results = []; for (i = q = 13; q <= 20; i = ++q) { - results.push(assert.equal(menu.items[i].checked, false)); + assert.equal(menu.items[i].checked, false); } - return results; }); }); }); diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 284033b967d8..215868bfdc8a 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -6,66 +6,68 @@ const remote = require('electron').remote; const protocol = remote.require('electron').protocol; describe('protocol module', function() { - var postData, protocolName, text; - protocolName = 'sp'; - text = 'valar morghulis'; - postData = { + var protocolName = 'sp'; + var text = 'valar morghulis'; + var postData = { name: 'post test', type: 'string' }; + afterEach(function(done) { - return protocol.unregisterProtocol(protocolName, function() { - return protocol.uninterceptProtocol('http', function() { - return done(); + protocol.unregisterProtocol(protocolName, function() { + protocol.uninterceptProtocol('http', function() { + done(); }); }); }); + describe('protocol.register(Any)Protocol', function() { - var emptyHandler; - emptyHandler = function(request, callback) { - return callback(); + var emptyHandler = function(request, callback) { + callback(); }; + it('throws error when scheme is already registered', function(done) { - return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { + protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { assert.equal(error, null); - return protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { + protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); + it('does not crash when handler is called twice', function(done) { - var doubleHandler; - doubleHandler = function(request, callback) { + var doubleHandler = function(request, callback) { try { callback(text); - return callback(); + callback(); } catch (error) { // Ignore error } }; - return protocol.registerStringProtocol(protocolName, doubleHandler, function(error) { + protocol.registerStringProtocol(protocolName, doubleHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('sends error when callback is called with nothing', function(done) { - return protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { + protocol.registerBufferProtocol(protocolName, emptyHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { return done('request succeeded but it should not'); @@ -77,236 +79,238 @@ describe('protocol module', function() { }); }); }); - return it('does not crash when callback is called in next tick', function(done) { - var handler; - handler = function(request, callback) { - return setImmediate(function() { - return callback(text); + + it('does not crash when callback is called in next tick', function(done) { + var handler = function(request, callback) { + setImmediate(function() { + callback(text); }); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); }); + describe('protocol.unregisterProtocol', function() { - return it('returns error when scheme does not exist', function(done) { - return protocol.unregisterProtocol('not-exist', function(error) { + it('returns error when scheme does not exist', function(done) { + protocol.unregisterProtocol('not-exist', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); + describe('protocol.registerStringProtocol', function() { it('sends string as response', function(done) { - var handler; - handler = function(request, callback) { - return callback(text); + var handler = function(request, callback) { + callback(text); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { - return callback(text); + var handler = function(request, callback) { + callback(text); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, text); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { - return callback({ + var handler = function(request, callback) { + callback({ data: text, mimeType: 'text/html' }); }; - return protocol.registerStringProtocol(protocolName, handler, function(error) { + protocol.registerStringProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('fails when sending object other than string', function(done) { - var handler; - handler = function(request, callback) { - return callback(new Date); + + it('fails when sending object other than string', function(done) { + var handler = function(request, callback) { + callback(new Date); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); }); + describe('protocol.registerBufferProtocol', function() { - var buffer; - buffer = new Buffer(text); + var buffer = new Buffer(text); + it('sends Buffer as response', function(done) { - var handler; - handler = function(request, callback) { - return callback(buffer); + var handler = function(request, callback) { + callback(buffer); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { - return callback(buffer); + var handler = function(request, callback) { + callback(buffer); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, text); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { - return callback({ + var handler = function(request, callback) { + callback({ data: buffer, mimeType: 'text/html' }); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('fails when sending string', function(done) { - var handler; - handler = function(request, callback) { - return callback(text); + + it('fails when sending string', function(done) { + var handler = function(request, callback) { + callback(text); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); }); + describe('protocol.registerFileProtocol', function() { - var fileContent, filePath, normalContent, normalPath; - filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1'); - fileContent = require('fs').readFileSync(filePath); - normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html'); - normalContent = require('fs').readFileSync(normalPath); + var filePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'file1'); + var fileContent = require('fs').readFileSync(filePath); + var normalPath = path.join(__dirname, 'fixtures', 'pages', 'a.html'); + var normalContent = require('fs').readFileSync(normalPath); + it('sends file path as response', function(done) { - var handler; - handler = function(request, callback) { - return callback(filePath); + var handler = function(request, callback) { + callback(filePath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(fileContent)); @@ -318,452 +322,452 @@ describe('protocol module', function() { }); }); }); + it('sets Access-Control-Allow-Origin', function(done) { - var handler; - handler = function(request, callback) { - return callback(filePath); + var handler = function(request, callback) { + callback(filePath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data, status, request) { assert.equal(data, String(fileContent)); assert.equal(request.getResponseHeader('Access-Control-Allow-Origin'), '*'); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); it('sends object as response', function(done) { - var handler; - handler = function(request, callback) { - return callback({ + var handler = function(request, callback) { + callback({ path: filePath }); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(fileContent)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('can send normal file', function(done) { - var handler; - handler = function(request, callback) { - return callback(normalPath); + var handler = function(request, callback) { + callback(normalPath); }; - return protocol.registerFileProtocol(protocolName, handler, function(error) { + + protocol.registerFileProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, String(normalContent)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('fails when sending unexist-file', function(done) { - var fakeFilePath, handler; - fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'); - handler = function(request, callback) { - return callback(fakeFilePath); + var fakeFilePath = path.join(__dirname, 'fixtures', 'asar', 'a.asar', 'not-exist'); + var handler = function(request, callback) { + callback(fakeFilePath); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); - return it('fails when sending unsupported content', function(done) { - var handler; - handler = function(request, callback) { - return callback(new Date); + + it('fails when sending unsupported content', function(done) { + var handler = function(request, callback) { + callback(new Date); }; - return protocol.registerBufferProtocol(protocolName, handler, function(error) { + protocol.registerBufferProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); }); + describe('protocol.registerHttpProtocol', function() { it('sends url as response', function(done) { - var server; - server = http.createServer(function(req, res) { + var server = http.createServer(function(req, res) { assert.notEqual(req.headers.accept, ''); res.end(text); - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { - var handler, port, url; - port = server.address().port; - url = "http://127.0.0.1:" + port; - handler = function(request, callback) { - return callback({ + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; + var url = "http://127.0.0.1:" + port; + var handler = function(request, callback) { + callback({ url: url }); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); }); + it('fails when sending invalid url', function(done) { - var handler; - handler = function(request, callback) { - return callback({ + var handler = function(request, callback) { + callback({ url: 'url' }); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); - return it('fails when sending unsupported content', function(done) { - var handler; - handler = function(request, callback) { - return callback(new Date); + + it('fails when sending unsupported content', function(done) { + var handler = function(request, callback) { + callback(new Date); }; - return protocol.registerHttpProtocol(protocolName, handler, function(error) { + protocol.registerHttpProtocol(protocolName, handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: protocolName + "://fake-host", success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); }); + describe('protocol.isProtocolHandled', function() { it('returns true for file:', function(done) { - return protocol.isProtocolHandled('file', function(result) { + protocol.isProtocolHandled('file', function(result) { assert.equal(result, true); - return done(); + done(); }); }); + it('returns true for http:', function(done) { - return protocol.isProtocolHandled('http', function(result) { + protocol.isProtocolHandled('http', function(result) { assert.equal(result, true); - return done(); + done(); }); }); + it('returns true for https:', function(done) { - return protocol.isProtocolHandled('https', function(result) { + protocol.isProtocolHandled('https', function(result) { assert.equal(result, true); - return done(); + done(); }); }); + it('returns false when scheme is not registred', function(done) { - return protocol.isProtocolHandled('no-exist', function(result) { + protocol.isProtocolHandled('no-exist', function(result) { assert.equal(result, false); - return done(); + done(); }); }); + it('returns true for custom protocol', function(done) { - var emptyHandler; - emptyHandler = function(request, callback) { - return callback(); + var emptyHandler = function(request, callback) { + callback(); }; - return protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { + protocol.registerStringProtocol(protocolName, emptyHandler, function(error) { assert.equal(error, null); - return protocol.isProtocolHandled(protocolName, function(result) { + protocol.isProtocolHandled(protocolName, function(result) { assert.equal(result, true); - return done(); + done(); }); }); }); - return it('returns true for intercepted protocol', function(done) { - var emptyHandler; - emptyHandler = function(request, callback) { - return callback(); + + it('returns true for intercepted protocol', function(done) { + var emptyHandler = function(request, callback) { + callback(); }; - return protocol.interceptStringProtocol('http', emptyHandler, function(error) { + protocol.interceptStringProtocol('http', emptyHandler, function(error) { assert.equal(error, null); - return protocol.isProtocolHandled('http', function(result) { + protocol.isProtocolHandled('http', function(result) { assert.equal(result, true); - return done(); + done(); }); }); }); }); + describe('protocol.intercept(Any)Protocol', function() { - var emptyHandler; - emptyHandler = function(request, callback) { - return callback(); + var emptyHandler = function(request, callback) { + callback(); }; + it('throws error when scheme is already intercepted', function(done) { - return protocol.interceptStringProtocol('http', emptyHandler, function(error) { + protocol.interceptStringProtocol('http', emptyHandler, function(error) { assert.equal(error, null); - return protocol.interceptBufferProtocol('http', emptyHandler, function(error) { + protocol.interceptBufferProtocol('http', emptyHandler, function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); + it('does not crash when handler is called twice', function(done) { - var doubleHandler; - doubleHandler = function(request, callback) { + var doubleHandler = function(request, callback) { try { callback(text); - return callback(); + callback(); } catch (error) { // Ignore error } }; - return protocol.interceptStringProtocol('http', doubleHandler, function(error) { + protocol.interceptStringProtocol('http', doubleHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('sends error when callback is called with nothing', function(done) { + + it('sends error when callback is called with nothing', function(done) { if (process.env.TRAVIS === 'true') { return done(); } - return protocol.interceptBufferProtocol('http', emptyHandler, function(error) { + protocol.interceptBufferProtocol('http', emptyHandler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function() { - return done('request succeeded but it should not'); + done('request succeeded but it should not'); }, error: function(xhr, errorType) { assert.equal(errorType, 'error'); - return done(); + done(); } }); }); }); }); + describe('protocol.interceptStringProtocol', function() { it('can intercept http protocol', function(done) { - var handler; - handler = function(request, callback) { - return callback(text); + var handler = function(request, callback) { + callback(text); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); + it('can set content-type', function(done) { - var handler; - handler = function(request, callback) { - return callback({ + var handler = function(request, callback) { + callback({ mimeType: 'application/json', data: '{"value": 1}' }); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(typeof data, 'object'); assert.equal(data.value, 1); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('can receive post data', function(done) { - var handler; - handler = function(request, callback) { - var uploadData; - uploadData = request.uploadData[0].bytes.toString(); - return callback({ + + it('can receive post data', function(done) { + var handler = function(request, callback) { + var uploadData = request.uploadData[0].bytes.toString(); + callback({ data: uploadData }); }; - return protocol.interceptStringProtocol('http', handler, function(error) { + protocol.interceptStringProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.deepEqual(qs.parse(data), postData); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); }); + describe('protocol.interceptBufferProtocol', function() { it('can intercept http protocol', function(done) { - var handler; - handler = function(request, callback) { - return callback(new Buffer(text)); + var handler = function(request, callback) { + callback(new Buffer(text)); }; - return protocol.interceptBufferProtocol('http', handler, function(error) { + protocol.interceptBufferProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: 'http://fake-host', success: function(data) { assert.equal(data, text); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); - return it('can receive post data', function(done) { - var handler; - handler = function(request, callback) { - var uploadData; - uploadData = request.uploadData[0].bytes; - return callback(uploadData); + + it('can receive post data', function(done) { + var handler = function(request, callback) { + var uploadData = request.uploadData[0].bytes; + callback(uploadData); }; - return protocol.interceptBufferProtocol('http', handler, function(error) { + protocol.interceptBufferProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.equal(data, $.param(postData)); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); }); + describe('protocol.interceptHttpProtocol', function() { - return it('can send POST request', function(done) { - var server; - server = http.createServer(function(req, res) { - var body; - body = ''; + it('can send POST request', function(done) { + var server = http.createServer(function(req, res) { + var body = ''; req.on('data', function(chunk) { - return body += chunk; + body += chunk; }); req.on('end', function() { - return res.end(body); + res.end(body); }); - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { - var handler, port, url; - port = server.address().port; - url = "http://127.0.0.1:" + port; - handler = function(request, callback) { - var data; - data = { + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; + var url = "http://127.0.0.1:" + port; + var handler = function(request, callback) { + var data = { url: url, method: 'POST', uploadData: { @@ -772,39 +776,41 @@ describe('protocol module', function() { }, session: null }; - return callback(data); + callback(data); }; - return protocol.interceptHttpProtocol('http', handler, function(error) { + protocol.interceptHttpProtocol('http', handler, function(error) { if (error) { return done(error); } - return $.ajax({ + $.ajax({ url: "http://fake-host", type: "POST", data: postData, success: function(data) { assert.deepEqual(qs.parse(data), postData); - return done(); + done(); }, error: function(xhr, errorType, error) { - return done(error); + done(error); } }); }); }); }); }); - return describe('protocol.uninterceptProtocol', function() { + + describe('protocol.uninterceptProtocol', function() { it('returns error when scheme does not exist', function(done) { - return protocol.uninterceptProtocol('not-exist', function(error) { + protocol.uninterceptProtocol('not-exist', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); - return it('returns error when scheme is not intercepted', function(done) { - return protocol.uninterceptProtocol('http', function(error) { + + it('returns error when scheme is not intercepted', function(done) { + protocol.uninterceptProtocol('http', function(error) { assert.notEqual(error, null); - return done(); + done(); }); }); }); diff --git a/spec/api-screen-spec.js b/spec/api-screen-spec.js index b393d4b99ee8..34828e863e82 100644 --- a/spec/api-screen-spec.js +++ b/spec/api-screen-spec.js @@ -1,25 +1,21 @@ -var assert, screen; - -assert = require('assert'); - -screen = require('electron').screen; +const assert = require('assert'); +const screen = require('electron').screen; describe('screen module', function() { describe('screen.getCursorScreenPoint()', function() { - return it('returns a point object', function() { - var point; - point = screen.getCursorScreenPoint(); + it('returns a point object', function() { + var point = screen.getCursorScreenPoint(); assert.equal(typeof point.x, 'number'); - return assert.equal(typeof point.y, 'number'); + assert.equal(typeof point.y, 'number'); }); }); - return describe('screen.getPrimaryDisplay()', function() { - return it('returns a display object', function() { - var display; - display = screen.getPrimaryDisplay(); + + describe('screen.getPrimaryDisplay()', function() { + it('returns a display object', function() { + var display = screen.getPrimaryDisplay(); assert.equal(typeof display.scaleFactor, 'number'); assert(display.size.width > 0); - return assert(display.size.height > 0); + assert(display.size.height > 0); }); }); }); diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index fe27f932cee0..9fedcc29e779 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -11,36 +11,36 @@ const session = remote.session; const BrowserWindow = remote.BrowserWindow; describe('session module', function() { - var fixtures, url, w; this.timeout(10000); - fixtures = path.resolve(__dirname, 'fixtures'); - w = null; - url = "http://127.0.0.1"; + + var fixtures = path.resolve(__dirname, 'fixtures'); + var w = null; + var url = "http://127.0.0.1"; + beforeEach(function() { - return w = new BrowserWindow({ + w = new BrowserWindow({ show: false, width: 400, height: 400 }); }); + afterEach(function() { - return w.destroy(); + w.destroy(); }); describe('session.cookies', function() { it('should get cookies', function(done) { - var server; - server = http.createServer(function(req, res) { + var server = http.createServer(function(req, res) { res.setHeader('Set-Cookie', ['0=0']); res.end('finished'); - return server.close(); + server.close(); }); - return server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; w.loadURL(url + ":" + port); - return w.webContents.on('did-finish-load', function() { - return w.webContents.session.cookies.get({ + w.webContents.on('did-finish-load', function() { + w.webContents.session.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -57,13 +57,14 @@ describe('session module', function() { } } } - return done('Can not find cookie'); + done('Can not find cookie'); }); }); }); }); + it('should over-write the existent cookie', function(done) { - return session.defaultSession.cookies.set({ + session.defaultSession.cookies.set({ url: url, name: '1', value: '1' @@ -71,7 +72,7 @@ describe('session module', function() { if (error) { return done(error); } - return session.defaultSession.cookies.get({ + session.defaultSession.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -88,12 +89,13 @@ describe('session module', function() { } } } - return done('Can not find cookie'); + done('Can not find cookie'); }); }); }); + it('should remove cookies', function(done) { - return session.defaultSession.cookies.set({ + session.defaultSession.cookies.set({ url: url, name: '2', value: '2' @@ -101,8 +103,8 @@ describe('session module', function() { if (error) { return done(error); } - return session.defaultSession.cookies.remove(url, '2', function() { - return session.defaultSession.cookies.get({ + session.defaultSession.cookies.remove(url, '2', function() { + session.defaultSession.cookies.get({ url: url }, function(error, list) { var cookie, i, len; @@ -115,7 +117,7 @@ describe('session module', function() { return done('Cookie not deleted'); } } - return done(); + done(); }); }); }); @@ -124,22 +126,21 @@ describe('session module', function() { describe('session.clearStorageData(options)', function() { fixtures = path.resolve(__dirname, 'fixtures'); - return it('clears localstorage data', function(done) { + it('clears localstorage data', function(done) { ipcMain.on('count', function(event, count) { ipcMain.removeAllListeners('count'); assert(!count); - return done(); + done(); }); w.loadURL('file://' + path.join(fixtures, 'api', 'localstorage.html')); - return w.webContents.on('did-finish-load', function() { - var options; - options = { + w.webContents.on('did-finish-load', function() { + var options = { origin: "file://", storages: ['localstorage'], quotas: ['persistent'] }; - return w.webContents.session.clearStorageData(options, function() { - return w.webContents.send('getcount'); + w.webContents.session.clearStorageData(options, function() { + w.webContents.send('getcount'); }); }); }); @@ -155,8 +156,9 @@ describe('session module', function() { height: 400 }); }); + afterEach(function() { - return w.destroy(); + w.destroy(); }); it('can cancel default download behavior', function(done) { @@ -188,21 +190,20 @@ describe('session module', function() { }); }); - return describe('DownloadItem', function() { - var assertDownload, contentDisposition, downloadFilePath, downloadServer, mockPDF; - mockPDF = new Buffer(1024 * 1024 * 5); - contentDisposition = 'inline; filename="mock.pdf"'; - downloadFilePath = path.join(fixtures, 'mock.pdf'); - downloadServer = http.createServer(function(req, res) { + describe('DownloadItem', function() { + var mockPDF = new Buffer(1024 * 1024 * 5); + var contentDisposition = 'inline; filename="mock.pdf"'; + var downloadFilePath = path.join(fixtures, 'mock.pdf'); + var downloadServer = http.createServer(function(req, res) { res.writeHead(200, { 'Content-Length': mockPDF.length, 'Content-Type': 'application/pdf', 'Content-Disposition': contentDisposition }); res.end(mockPDF); - return downloadServer.close(); + downloadServer.close(); }); - assertDownload = function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port) { + var assertDownload = function(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 + "/"); @@ -211,52 +212,52 @@ describe('session module', function() { assert.equal(totalBytes, mockPDF.length); assert.equal(disposition, contentDisposition); assert(fs.existsSync(downloadFilePath)); - return fs.unlinkSync(downloadFilePath); + fs.unlinkSync(downloadFilePath); }; + it('can download using BrowserWindow.loadURL', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', false, false); w.loadURL(url + ":" + port); - return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { + ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); - return done(); + done(); }); }); }); + it('can download using WebView.downloadURL', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port, webview; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', false, false); - webview = new WebView; + var webview = new WebView; webview.src = "file://" + fixtures + "/api/blank.html"; webview.addEventListener('did-finish-load', function() { - return webview.downloadURL(url + ":" + port + "/"); + webview.downloadURL(url + ":" + port + "/"); }); ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { assertDownload(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename, port); document.body.removeChild(webview); - return done(); + done(); }); - return document.body.appendChild(webview); + document.body.appendChild(webview); }); }); + it('can cancel download', function(done) { - return downloadServer.listen(0, '127.0.0.1', function() { - var port; - port = downloadServer.address().port; + downloadServer.listen(0, '127.0.0.1', function() { + var port = downloadServer.address().port; ipcRenderer.sendSync('set-download-option', true, false); w.loadURL(url + ":" + port + "/"); - return ipcRenderer.once('download-done', function(event, state, url, mimeType, receivedBytes, totalBytes, disposition, filename) { + ipcRenderer.once('download-done', function(event, 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); - return done(); + done(); }); }); }); diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index 3d287a6acba9..15f31aa8f095 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -1,24 +1,18 @@ -var assert, path, webFrame; - -assert = require('assert'); - -path = require('path'); - -webFrame = require('electron').webFrame; +const assert = require('assert'); +const path = require('path'); +const webFrame = require('electron').webFrame; describe('webFrame module', function() { - var fixtures; - fixtures = path.resolve(__dirname, 'fixtures'); - return describe('webFrame.registerURLSchemeAsPrivileged', function() { - return it('supports fetch api', function(done) { - var url; + var fixtures = path.resolve(__dirname, 'fixtures'); + describe('webFrame.registerURLSchemeAsPrivileged', function() { + it('supports fetch api', function(done) { webFrame.registerURLSchemeAsPrivileged('file'); - url = "file://" + fixtures + "/assets/logo.png"; - return fetch(url).then(function(response) { + var url = "file://" + fixtures + "/assets/logo.png"; + fetch(url).then(function(response) { assert(response.ok); - return done(); - })["catch"](function(err) { - return done('unexpected error : ' + err); + done(); + }).catch(function(err) { + done('unexpected error : ' + err); }); }); }); diff --git a/spec/api-web-request-spec.js b/spec/api-web-request-spec.js index 91b84c77e1b3..77f160a20041 100644 --- a/spec/api-web-request-spec.js +++ b/spec/api-web-request-spec.js @@ -5,78 +5,80 @@ const remote = require('electron').remote; const session = remote.session; describe('webRequest module', function() { - var defaultURL, server, ses; - ses = session.defaultSession; - server = http.createServer(function(req, res) { - var content; + var ses = session.defaultSession; + var server = http.createServer(function(req, res) { res.setHeader('Custom', ['Header']); - content = req.url; + var content = req.url; if (req.headers.accept === '*/*;test/header') { content += 'header/received'; } - return res.end(content); + res.end(content); }); - defaultURL = null; + var defaultURL = null; + before(function(done) { - return server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; defaultURL = "http://127.0.0.1:" + port + "/"; - return done(); + done(); }); }); + after(function() { - return server.close(); + server.close(); }); + describe('webRequest.onBeforeRequest', function() { afterEach(function() { - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); + it('can cancel the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function() { - return done('unexpected success'); + done('unexpected success'); }, error: function() { - return done(); + done(); } }); }); + it('can filter URLs', function(done) { - var filter; - filter = { + var filter = { urls: [defaultURL + "filter/*"] }; ses.webRequest.onBeforeRequest(filter, function(details, callback) { - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL + "nofilter/test", success: function(data) { assert.equal(data, '/nofilter/test'); - return $.ajax({ + $.ajax({ url: defaultURL + "filter/test", success: function() { - return done('unexpected success'); + done('unexpected success'); }, error: function() { - return done(); + done(); } }); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); + it('receives details object', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { assert.equal(typeof details.id, 'number'); @@ -85,36 +87,36 @@ describe('webRequest module', function() { assert.equal(details.method, 'GET'); assert.equal(details.resourceType, 'xhr'); assert(!details.uploadData); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); + it('receives post data in details object', function(done) { var postData = { name: 'post test', type: 'string' }; ses.webRequest.onBeforeRequest(function(details, callback) { - var data; assert.equal(details.url, defaultURL); assert.equal(details.method, 'POST'); assert.equal(details.uploadData.length, 1); - data = qs.parse(details.uploadData[0].bytes.toString()); + var data = qs.parse(details.uploadData[0].bytes.toString()); assert.deepEqual(data, postData); - return callback({ + callback({ cancel: true }); }); - return $.ajax({ + $.ajax({ url: defaultURL, type: 'POST', data: postData, @@ -125,270 +127,285 @@ describe('webRequest module', function() { } }); }); - return it('can redirect the request', function(done) { + + it('can redirect the request', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { if (details.url === defaultURL) { - return callback({ + callback({ redirectURL: defaultURL + "redirect" }); } else { - return callback({}); + callback({}); } }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/redirect'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onBeforeSendHeaders', function() { afterEach(function() { - return ses.webRequest.onBeforeSendHeaders(null); + ses.webRequest.onBeforeSendHeaders(null); }); + it('receives details object', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { assert.equal(typeof details.requestHeaders, 'object'); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); + it('can change the request headers', function(done) { ses.webRequest.onBeforeSendHeaders(function(details, callback) { - var requestHeaders; - requestHeaders = details.requestHeaders; + var requestHeaders = details.requestHeaders; requestHeaders.Accept = '*/*;test/header'; - return callback({ + callback({ requestHeaders: requestHeaders }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/header/received'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); - return it('resets the whole headers', function(done) { - var requestHeaders; - requestHeaders = { + + it('resets the whole headers', function(done) { + var requestHeaders = { Test: 'header' }; ses.webRequest.onBeforeSendHeaders(function(details, callback) { - return callback({ + callback({ requestHeaders: requestHeaders }); }); ses.webRequest.onSendHeaders(function(details) { assert.deepEqual(details.requestHeaders, requestHeaders); - return done(); + done(); }); - return $.ajax({ + $.ajax({ url: defaultURL, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onSendHeaders', function() { afterEach(function() { - return ses.webRequest.onSendHeaders(null); + ses.webRequest.onSendHeaders(null); }); - return it('receives details object', function(done) { + + it('receives details object', function(done) { ses.webRequest.onSendHeaders(function(details) { - return assert.equal(typeof details.requestHeaders, 'object'); + assert.equal(typeof details.requestHeaders, 'object'); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onHeadersReceived', function() { afterEach(function() { - return ses.webRequest.onHeadersReceived(null); + ses.webRequest.onHeadersReceived(null); }); + it('receives details object', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusCode, 200); assert.equal(details.responseHeaders['Custom'], 'Header'); - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); + it('can change the response header', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { - var responseHeaders; - responseHeaders = details.responseHeaders; + var responseHeaders = details.responseHeaders; responseHeaders['Custom'] = ['Changed']; - return callback({ + callback({ responseHeaders: responseHeaders }); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Changed'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); - return it('does not change header by default', function(done) { + + it('does not change header by default', function(done) { ses.webRequest.onHeadersReceived(function(details, callback) { - return callback({}); + callback({}); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onResponseStarted', function() { afterEach(function() { - return ses.webRequest.onResponseStarted(null); + ses.webRequest.onResponseStarted(null); }); - return it('receives details object', function(done) { + + it('receives details object', function(done) { ses.webRequest.onResponseStarted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); assert.equal(details.statusCode, 200); - return assert.equal(details.responseHeaders['Custom'], 'Header'); + assert.equal(details.responseHeaders['Custom'], 'Header'); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data, status, xhr) { assert.equal(xhr.getResponseHeader('Custom'), 'Header'); assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onBeforeRedirect', function() { afterEach(function() { ses.webRequest.onBeforeRedirect(null); - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); - return it('receives details object', function(done) { - var redirectURL; - redirectURL = defaultURL + "redirect"; + + it('receives details object', function(done) { + var redirectURL = defaultURL + "redirect"; ses.webRequest.onBeforeRequest(function(details, callback) { if (details.url === defaultURL) { - return callback({ + callback({ redirectURL: redirectURL }); } else { - return callback({}); + callback({}); } }); ses.webRequest.onBeforeRedirect(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 307 Internal Redirect'); assert.equal(details.statusCode, 307); - return assert.equal(details.redirectURL, redirectURL); + assert.equal(details.redirectURL, redirectURL); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/redirect'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); + describe('webRequest.onCompleted', function() { afterEach(function() { - return ses.webRequest.onCompleted(null); + ses.webRequest.onCompleted(null); }); - return it('receives details object', function(done) { + + it('receives details object', function(done) { ses.webRequest.onCompleted(function(details) { assert.equal(typeof details.fromCache, 'boolean'); assert.equal(details.statusLine, 'HTTP/1.1 200 OK'); - return assert.equal(details.statusCode, 200); + assert.equal(details.statusCode, 200); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function(data) { assert.equal(data, '/'); - return done(); + done(); }, error: function(xhr, errorType) { - return done(errorType); + done(errorType); } }); }); }); - return describe('webRequest.onErrorOccurred', function() { + + describe('webRequest.onErrorOccurred', function() { afterEach(function() { ses.webRequest.onErrorOccurred(null); - return ses.webRequest.onBeforeRequest(null); + ses.webRequest.onBeforeRequest(null); }); - return it('receives details object', function(done) { + + it('receives details object', function(done) { ses.webRequest.onBeforeRequest(function(details, callback) { - return callback({ + callback({ cancel: true }); }); ses.webRequest.onErrorOccurred(function(details) { assert.equal(details.error, 'net::ERR_BLOCKED_BY_CLIENT'); - return done(); + done(); }); - return $.ajax({ + $.ajax({ url: defaultURL, success: function() { - return done('unexpected success'); + done('unexpected success'); } }); }); diff --git a/spec/asar-spec.js b/spec/asar-spec.js index 81d881f7eb40..060074390f1b 100644 --- a/spec/asar-spec.js +++ b/spec/asar-spec.js @@ -10,8 +10,8 @@ const ipcMain = remote.require('electron').ipcMain; const BrowserWindow = remote.require('electron').BrowserWindow; describe('asar package', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('node api', function() { describe('fs.readFileSync', function() { it('does not leak fd', function() { @@ -21,124 +21,124 @@ describe('asar package', function() { readCalls++; } }); + it('reads a normal file', function() { - var file1, file2, file3; - file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); assert.equal(fs.readFileSync(file1).toString().trim(), 'file1'); - file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); + var file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); assert.equal(fs.readFileSync(file2).toString().trim(), 'file2'); - file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); - return assert.equal(fs.readFileSync(file3).toString().trim(), 'file3'); + var file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); + assert.equal(fs.readFileSync(file3).toString().trim(), 'file3'); }); + it('reads from a empty file', function() { - var buffer, file; - file = path.join(fixtures, 'asar', 'empty.asar', 'file1'); - buffer = fs.readFileSync(file); + var file = path.join(fixtures, 'asar', 'empty.asar', 'file1'); + var buffer = fs.readFileSync(file); assert.equal(buffer.length, 0); - return assert.equal(buffer.toString(), ''); + assert.equal(buffer.toString(), ''); }); + it('reads a linked file', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); + it('reads a file from linked directory', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); + assert.equal(fs.readFileSync(p).toString().trim(), 'file1'); }); + it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { - return fs.readFileSync(p); + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { + fs.readFileSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); + it('passes ENOENT error to callback when can not find file', function() { - var async, p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - async = false; + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var async = false; fs.readFile(p, function(e) { assert(async); - return assert(/ENOENT/.test(e)); + assert(/ENOENT/.test(e)); }); - return async = true; + async = true; }); - return it('reads a normal file with unpacked files', function() { - var p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return assert.equal(fs.readFileSync(p).toString().trim(), 'a'); + + it('reads a normal file with unpacked files', function() { + var p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); + assert.equal(fs.readFileSync(p).toString().trim(), 'a'); }); }); + describe('fs.readFile', function() { it('reads a normal file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); + it('reads from a empty file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'empty.asar', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'empty.asar', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content), ''); - return done(); + done(); }); }); + it('reads a linked file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); + it('reads a file from linked directory', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return fs.readFile(p, function(err, content) { + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + fs.readFile(p, function(err, content) { assert.equal(err, null); assert.equal(String(content).trim(), 'file1'); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.readFile(p, function(err) { + + it('throws ENOENT error when can not find file', function(done) { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + fs.readFile(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); + describe('fs.lstatSync', function() { it('handles path with trailing slash correctly', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); fs.lstatSync(p); - return fs.lstatSync(p + '/'); + fs.lstatSync(p + '/'); }); + it('returns information of root', function() { - var p, stats; - p = path.join(fixtures, 'asar', 'a.asar'); - stats = fs.lstatSync(p); + var p = path.join(fixtures, 'asar', 'a.asar'); + var stats = fs.lstatSync(p); assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); - return assert.equal(stats.size, 0); + assert.equal(stats.size, 0); }); + it('returns information of a normal file', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['file1', 'file2', 'file3', path.join('dir1', 'file1'), path.join('link2', 'file1')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -146,14 +146,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), true); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), false); - results.push(assert.equal(stats.size, 6)); + assert.equal(stats.size, 6); } - return results; }); + it('returns information of a normal directory', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['dir1', 'dir2', 'dir3']; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -161,14 +160,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - return results; }); + it('returns information of a linked file', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['link1', path.join('dir1', 'link1'), path.join('link2', 'link2')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -176,14 +174,13 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - return results; }); + it('returns information of a linked directory', function() { - var file, j, len, p, ref2, results, stats; + var file, j, len, p, ref2, stats; ref2 = ['link2', path.join('dir1', 'link2'), path.join('link2', 'link2')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -191,31 +188,30 @@ describe('asar package', function() { assert.equal(stats.isFile(), false); assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); - results.push(assert.equal(stats.size, 0)); + assert.equal(stats.size, 0); } - return results; }); - return it('throws ENOENT error when can not find file', function() { - var file, j, len, p, ref2, results, throws; + + it('throws ENOENT error when can not find file', function() { + var file, j, len, p, ref2, throws; ref2 = ['file4', 'file5', path.join('dir1', 'file4')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); throws = function() { - return fs.lstatSync(p); + fs.lstatSync(p); }; - results.push(assert.throws(throws, /ENOENT/)); + assert.throws(throws, /ENOENT/); } - return results; }); }); + describe('fs.lstat', function() { it('handles path with trailing slash correctly', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); - return fs.lstat(p + '/', done); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2', 'file1'); + fs.lstat(p + '/', done); }); + it('returns information of root', function(done) { var p = path.join(fixtures, 'asar', 'a.asar'); fs.lstat(p, function(err, stats) { @@ -224,9 +220,10 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 0); - return done(); + done(); }); }); + it('returns information of a normal file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'file1'); fs.lstat(p, function(err, stats) { @@ -235,9 +232,10 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 6); - return done(); + done(); }); }); + it('returns information of a normal directory', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); fs.lstat(p, function(err, stats) { @@ -246,9 +244,10 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), true); assert.equal(stats.isSymbolicLink(), false); assert.equal(stats.size, 0); - return done(); + done(); }); }); + it('returns information of a linked file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link1'); fs.lstat(p, function(err, stats) { @@ -257,9 +256,10 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); assert.equal(stats.size, 0); - return done(); + done(); }); }); + it('returns information of a linked directory', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); fs.lstat(p, function(err, stats) { @@ -268,167 +268,168 @@ describe('asar package', function() { assert.equal(stats.isDirectory(), false); assert.equal(stats.isSymbolicLink(), true); assert.equal(stats.size, 0); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { + + it('throws ENOENT error when can not find file', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'file4'); fs.lstat(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); + describe('fs.realpathSync', function() { it('returns real path root', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = 'a.asar'; - r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = 'a.asar'; + var r = fs.realpathSync(path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); + it('returns real path of a normal file', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'file1'); - r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'file1'); + var r = fs.realpathSync(path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); + it('returns real path of a normal directory', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'dir1'); - r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, p)); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'dir1'); + var r = fs.realpathSync(path.join(parent, p)); + assert.equal(r, path.join(parent, p)); }); + it('returns real path of a linked file', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link1'); - r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, 'a.asar', 'file1')); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link1'); + var r = fs.realpathSync(path.join(parent, p)); + assert.equal(r, path.join(parent, 'a.asar', 'file1')); }); + it('returns real path of a linked directory', function() { - var p, parent, r; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link2'); - r = fs.realpathSync(path.join(parent, p)); - return assert.equal(r, path.join(parent, 'a.asar', 'dir1')); + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link2'); + var r = fs.realpathSync(path.join(parent, p)); + assert.equal(r, path.join(parent, 'a.asar', 'dir1')); }); - return it('throws ENOENT error when can not find file', function() { - var p, parent, throws; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'not-exist'); - throws = function() { - return fs.realpathSync(path.join(parent, p)); + + it('throws ENOENT error when can not find file', function() { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'not-exist'); + var throws = function() { + fs.realpathSync(path.join(parent, p)); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); + describe('fs.realpath', function() { it('returns real path root', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = 'a.asar'; - return fs.realpath(path.join(parent, p), function(err, r) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = 'a.asar'; + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); + it('returns real path of a normal file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'file1'); - return fs.realpath(path.join(parent, p), function(err, r) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'file1'); + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); + it('returns real path of a normal directory', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'dir1'); - return fs.realpath(path.join(parent, p), function(err, r) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'dir1'); + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, p)); - return done(); + done(); }); }); + it('returns real path of a linked file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link1'); - return fs.realpath(path.join(parent, p), function(err, r) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link1'); + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'file1')); - return done(); + done(); }); }); + it('returns real path of a linked directory', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'link2', 'link2'); - return fs.realpath(path.join(parent, p), function(err, r) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'link2', 'link2'); + fs.realpath(path.join(parent, p), function(err, r) { assert.equal(err, null); assert.equal(r, path.join(parent, 'a.asar', 'dir1')); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { - var p, parent; - parent = fs.realpathSync(path.join(fixtures, 'asar')); - p = path.join('a.asar', 'not-exist'); - return fs.realpath(path.join(parent, p), function(err) { + it('throws ENOENT error when can not find file', function(done) { + var parent = fs.realpathSync(path.join(fixtures, 'asar')); + var p = path.join('a.asar', 'not-exist'); + fs.realpath(path.join(parent, p), function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); describe('fs.readdirSync', function() { it('reads dirs from root', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar'); - dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); + var p = path.join(fixtures, 'asar', 'a.asar'); + var dirs = fs.readdirSync(p); + assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); }); + it('reads dirs from a normal dir', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); - dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); + var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + var dirs = fs.readdirSync(p); + assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); + it('reads dirs from a linked dir', function() { - var dirs, p; - p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); - dirs = fs.readdirSync(p); - return assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); + var p = path.join(fixtures, 'asar', 'a.asar', 'link2', 'link2'); + var dirs = fs.readdirSync(p); + assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); }); - return it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { - return fs.readdirSync(p); + + it('throws ENOENT error when can not find file', function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { + fs.readdirSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); + describe('fs.readdir', function() { it('reads dirs from root', function(done) { var p = path.join(fixtures, 'asar', 'a.asar'); fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['dir1', 'dir2', 'dir3', 'file1', 'file2', 'file3', 'link1', 'link2', 'ping.js']); - return done(); + done(); }); }); + it('reads dirs from a normal dir', function(done) { var p = path.join(fixtures, 'asar', 'a.asar', 'dir1'); fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); - return done(); + done(); }); }); it('reads dirs from a linked dir', function(done) { @@ -436,23 +437,23 @@ describe('asar package', function() { fs.readdir(p, function(err, dirs) { assert.equal(err, null); assert.deepEqual(dirs, ['file1', 'file2', 'file3', 'link1', 'link2']); - return done(); + done(); }); }); - return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.readdir(p, function(err) { + + it('throws ENOENT error when can not find file', function(done) { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + fs.readdir(p, function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); + describe('fs.openSync', function() { it('opens a normal/linked/under-linked-directory file', function() { - var buffer, fd, file, j, len, p, ref2, results; + var buffer, fd, file, j, len, p, ref2; ref2 = ['file1', 'link1', path.join('link2', 'file1')]; - results = []; for (j = 0, len = ref2.length; j < len; j++) { file = ref2[j]; p = path.join(fixtures, 'asar', 'a.asar', file); @@ -460,84 +461,82 @@ describe('asar package', function() { buffer = new Buffer(6); fs.readSync(fd, buffer, 0, 6, 0); assert.equal(String(buffer).trim(), 'file1'); - results.push(fs.closeSync(fd)); + fs.closeSync(fd); } - return results; }); - return it('throws ENOENT error when can not find file', function() { - var p, throws; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - throws = function() { - return fs.openSync(p); + + it('throws ENOENT error when can not find file', function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + var throws = function() { + fs.openSync(p); }; - return assert.throws(throws, /ENOENT/); + assert.throws(throws, /ENOENT/); }); }); + describe('fs.open', function() { it('opens a normal file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'file1'); - return fs.open(p, 'r', function(err, fd) { - var buffer; + var p = path.join(fixtures, 'asar', 'a.asar', 'file1'); + fs.open(p, 'r', function(err, fd) { assert.equal(err, null); - buffer = new Buffer(6); - return fs.read(fd, buffer, 0, 6, 0, function(err) { + var buffer = new Buffer(6); + fs.read(fd, buffer, 0, 6, 0, function(err) { assert.equal(err, null); assert.equal(String(buffer).trim(), 'file1'); - return fs.close(fd, done); + fs.close(fd, done); }); }); }); - return it('throws ENOENT error when can not find file', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.open(p, 'r', function(err) { + + it('throws ENOENT error when can not find file', function(done) { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + fs.open(p, 'r', function(err) { assert.equal(err.code, 'ENOENT'); - return done(); + done(); }); }); }); + describe('fs.mkdir', function() { - return it('throws error when calling inside asar archive', function(done) { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return fs.mkdir(p, function(err) { + it('throws error when calling inside asar archive', function(done) { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + fs.mkdir(p, function(err) { assert.equal(err.code, 'ENOTDIR'); - return done(); + done(); }); }); }); + describe('fs.mkdirSync', function() { - return it('throws error when calling inside asar archive', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return assert.throws((function() { - return fs.mkdirSync(p); + it('throws error when calling inside asar archive', function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + assert.throws((function() { + fs.mkdirSync(p); }), new RegExp('ENOTDIR')); }); }); + describe('child_process.fork', function() { - child_process = require('child_process'); it('opens a normal js file', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); + var child = child_process.fork(path.join(fixtures, 'asar', 'a.asar', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); - return it('supports asar in the forked js', function(done) { - var child, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - child = child_process.fork(path.join(fixtures, 'module', 'asar.js')); + + it('supports asar in the forked js', function(done) { + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var child = child_process.fork(path.join(fixtures, 'module', 'asar.js')); child.on('message', function(content) { assert.equal(content, fs.readFileSync(file).toString()); - return done(); + done(); }); - return child.send(file); + child.send(file); }); }); + describe('child_process.execFile', function() { var echo, execFile, execFileSync, ref2; if (process.platform !== 'darwin') { @@ -545,244 +544,249 @@ describe('asar package', function() { } ref2 = require('child_process'), execFile = ref2.execFile, execFileSync = ref2.execFileSync; echo = path.join(fixtures, 'asar', 'echo.asar', 'echo'); + it('executes binaries', function(done) { execFile(echo, ['test'], function(error, stdout) { assert.equal(error, null); assert.equal(stdout, 'test\n'); - return done(); + done(); }); }); - return xit('execFileSync executes binaries', function() { - var output; - output = execFileSync(echo, ['test']); - return assert.equal(String(output), 'test\n'); + + xit('execFileSync executes binaries', function() { + var output = execFileSync(echo, ['test']); + assert.equal(String(output), 'test\n'); }); }); + describe('internalModuleReadFile', function() { - var internalModuleReadFile; - internalModuleReadFile = process.binding('fs').internalModuleReadFile; + var internalModuleReadFile = process.binding('fs').internalModuleReadFile; + it('read a normal file', function() { - var file1, file2, file3; - file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var file1 = path.join(fixtures, 'asar', 'a.asar', 'file1'); assert.equal(internalModuleReadFile(file1).toString().trim(), 'file1'); - file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); + var file2 = path.join(fixtures, 'asar', 'a.asar', 'file2'); assert.equal(internalModuleReadFile(file2).toString().trim(), 'file2'); - file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); - return assert.equal(internalModuleReadFile(file3).toString().trim(), 'file3'); + var file3 = path.join(fixtures, 'asar', 'a.asar', 'file3'); + assert.equal(internalModuleReadFile(file3).toString().trim(), 'file3'); }); - return it('reads a normal file with unpacked files', function() { - var p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return assert.equal(internalModuleReadFile(p).toString().trim(), 'a'); + + it('reads a normal file with unpacked files', function() { + var p = path.join(fixtures, 'asar', 'unpack.asar', 'a.txt'); + assert.equal(internalModuleReadFile(p).toString().trim(), 'a'); }); }); - return describe('process.noAsar', function() { - var errorName; - errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'; + + describe('process.noAsar', function() { + var errorName = process.platform === 'win32' ? 'ENOENT' : 'ENOTDIR'; + beforeEach(function() { - return process.noAsar = true; + process.noAsar = true; }); + afterEach(function() { - return process.noAsar = false; + process.noAsar = false; }); + it('disables asar support in sync API', function() { - var dir, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); assert.throws((function() { - return fs.readFileSync(file); + fs.readFileSync(file); }), new RegExp(errorName)); assert.throws((function() { - return fs.lstatSync(file); + fs.lstatSync(file); }), new RegExp(errorName)); assert.throws((function() { - return fs.realpathSync(file); + fs.realpathSync(file); }), new RegExp(errorName)); - return assert.throws((function() { - return fs.readdirSync(dir); + assert.throws((function() { + fs.readdirSync(dir); }), new RegExp(errorName)); }); + it('disables asar support in async API', function(done) { - var dir, file; - file = path.join(fixtures, 'asar', 'a.asar', 'file1'); - dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); - return fs.readFile(file, function(error) { + var file = path.join(fixtures, 'asar', 'a.asar', 'file1'); + var dir = path.join(fixtures, 'asar', 'a.asar', 'dir1'); + fs.readFile(file, function(error) { assert.equal(error.code, errorName); - return fs.lstat(file, function(error) { + fs.lstat(file, function(error) { assert.equal(error.code, errorName); - return fs.realpath(file, function(error) { + fs.realpath(file, function(error) { assert.equal(error.code, errorName); - return fs.readdir(dir, function(error) { + fs.readdir(dir, function(error) { assert.equal(error.code, errorName); - return done(); + done(); }); }); }); }); }); - return it('treats *.asar as normal file', function() { - var asar, content1, content2, originalFs; - originalFs = require('original-fs'); - asar = path.join(fixtures, 'asar', 'a.asar'); - content1 = fs.readFileSync(asar); - content2 = originalFs.readFileSync(asar); + + it('treats *.asar as normal file', function() { + var originalFs = require('original-fs'); + var asar = path.join(fixtures, 'asar', 'a.asar'); + var content1 = fs.readFileSync(asar); + var content2 = originalFs.readFileSync(asar); assert.equal(content1.compare(content2), 0); - return assert.throws((function() { - return fs.readdirSync(asar); + assert.throws((function() { + fs.readdirSync(asar); }), /ENOTDIR/); }); }); }); + describe('asar protocol', function() { - var url; - url = require('url'); + var url = require('url'); + it('can request a file in package', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'file1'); - return $.get("file://" + p, function(data) { + var p = path.resolve(fixtures, 'asar', 'a.asar', 'file1'); + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); - return done(); + done(); }); }); + it('can request a file in package with unpacked files', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt'); - return $.get("file://" + p, function(data) { + var p = path.resolve(fixtures, 'asar', 'unpack.asar', 'a.txt'); + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'a'); - return done(); + done(); }); }); + it('can request a linked file in package', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1'); - return $.get("file://" + p, function(data) { + var p = path.resolve(fixtures, 'asar', 'a.asar', 'link2', 'link1'); + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file1'); - return done(); + done(); }); }); + it('can request a file in filesystem', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'file'); - return $.get("file://" + p, function(data) { + var p = path.resolve(fixtures, 'asar', 'file'); + $.get("file://" + p, function(data) { assert.equal(data.trim(), 'file'); - return done(); + done(); }); }); + it('gets 404 when file is not found', function(done) { - var p; - p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist'); - return $.ajax({ + var p = path.resolve(fixtures, 'asar', 'a.asar', 'no-exist'); + $.ajax({ url: "file://" + p, error: function(err) { assert.equal(err.status, 404); - return done(); + done(); } }); }); + it('sets __dirname correctly', function(done) { - var p, u, w; after(function() { w.destroy(); - return ipcMain.removeAllListeners('dirname'); + ipcMain.removeAllListeners('dirname'); }); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false, width: 400, height: 400 }); - p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html'); - u = url.format({ + var p = path.resolve(fixtures, 'asar', 'web.asar', 'index.html'); + var u = url.format({ protocol: 'file', slashed: true, pathname: p }); ipcMain.once('dirname', function(event, dirname) { assert.equal(dirname, path.dirname(p)); - return done(); + done(); }); - return w.loadURL(u); + w.loadURL(u); }); - return it('loads script tag in html', function(done) { - var p, u, w; + + it('loads script tag in html', function(done) { after(function() { w.destroy(); - return ipcMain.removeAllListeners('ping'); + ipcMain.removeAllListeners('ping'); }); - w = new BrowserWindow({ + + var w = new BrowserWindow({ show: false, width: 400, height: 400 }); - p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html'); - u = url.format({ + var p = path.resolve(fixtures, 'asar', 'script.asar', 'index.html'); + var u = url.format({ protocol: 'file', slashed: true, pathname: p }); w.loadURL(u); - return ipcMain.once('ping', function(event, message) { + ipcMain.once('ping', function(event, message) { assert.equal(message, 'pong'); - return done(); + done(); }); }); }); + describe('original-fs module', function() { - var originalFs; - originalFs = require('original-fs'); + var originalFs = require('original-fs'); + it('treats .asar as file', function() { - var file, stats; - file = path.join(fixtures, 'asar', 'a.asar'); - stats = originalFs.statSync(file); - return assert(stats.isFile()); + var file = path.join(fixtures, 'asar', 'a.asar'); + var stats = originalFs.statSync(file); + assert(stats.isFile()); }); - return it('is available in forked scripts', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); + + it('is available in forked scripts', function(done) { + var child = child_process.fork(path.join(fixtures, 'module', 'original-fs.js')); child.on('message', function(msg) { assert.equal(msg, 'object'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); }); + describe('graceful-fs module', function() { - var gfs; - gfs = require('graceful-fs'); + var gfs = require('graceful-fs'); + it('recognize asar archvies', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'link1'); - return assert.equal(gfs.readFileSync(p).toString().trim(), 'file1'); + var p = path.join(fixtures, 'asar', 'a.asar', 'link1'); + assert.equal(gfs.readFileSync(p).toString().trim(), 'file1'); }); - return it('does not touch global fs object', function() { - return assert.notEqual(fs.readdir, gfs.readdir); + it('does not touch global fs object', function() { + assert.notEqual(fs.readdir, gfs.readdir); }); }); + describe('mkdirp module', function() { - var mkdirp; - mkdirp = require('mkdirp'); - return it('throws error when calling inside asar archive', function() { - var p; - p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); - return assert.throws((function() { - return mkdirp.sync(p); + var mkdirp = require('mkdirp'); + + it('throws error when calling inside asar archive', function() { + var p = path.join(fixtures, 'asar', 'a.asar', 'not-exist'); + assert.throws((function() { + mkdirp.sync(p); }), new RegExp('ENOTDIR')); }); }); - return describe('native-image', function() { + + describe('native-image', function() { it('reads image from asar archive', function() { - var logo, p; - p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png'); - logo = nativeImage.createFromPath(p); - return assert.deepEqual(logo.getSize(), { + var p = path.join(fixtures, 'asar', 'logo.asar', 'logo.png'); + var logo = nativeImage.createFromPath(p); + assert.deepEqual(logo.getSize(), { width: 55, height: 55 }); }); - return it('reads image from asar archive with unpacked files', function() { - var logo, p; - p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png'); - logo = nativeImage.createFromPath(p); - return assert.deepEqual(logo.getSize(), { + + it('reads image from asar archive with unpacked files', function() { + var p = path.join(fixtures, 'asar', 'unpack.asar', 'atom.png'); + var logo = nativeImage.createFromPath(p); + assert.deepEqual(logo.getSize(), { width: 1024, height: 1024 }); diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 56fa21c89a77..e4444f55b11d 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -8,130 +8,142 @@ const BrowserWindow = remote.require('electron').BrowserWindow; const session = remote.require('electron').session; describe('chromium feature', function() { - var fixtures, listener; - fixtures = path.resolve(__dirname, 'fixtures'); - listener = null; + var fixtures = path.resolve(__dirname, 'fixtures'); + var listener = null; + afterEach(function() { if (listener != null) { window.removeEventListener('message', listener); } - return listener = null; + listener = null; }); + xdescribe('heap snapshot', function() { - return it('does not crash', function() { - return process.atomBinding('v8_util').takeHeapSnapshot(); + it('does not crash', function() { + process.atomBinding('v8_util').takeHeapSnapshot(); }); }); + describe('sending request of http protocol urls', function() { - return it('does not crash', function(done) { - var server; + it('does not crash', function(done) { this.timeout(5000); - server = http.createServer(function(req, res) { + + var server = http.createServer(function(req, res) { res.end(); server.close(); - return done(); + done(); }); - return server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; - return $.get("http://127.0.0.1:" + port); + server.listen(0, '127.0.0.1', function() { + var port = server.address().port; + $.get("http://127.0.0.1:" + port); }); }); }); + describe('document.hidden', function() { - var url, w; - url = "file://" + fixtures + "/pages/document-hidden.html"; - w = null; + var url = "file://" + fixtures + "/pages/document-hidden.html"; + var w = null; + afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); + it('is set correctly when window is not shown', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['hidden', true]); - return done(); + done(); }); - return w.loadURL(url); + w.loadURL(url); }); - return it('is set correctly when window is inactive', function(done) { + + it('is set correctly when window is inactive', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['hidden', false]); - return done(); + done(); }); w.showInactive(); - return w.loadURL(url); + w.loadURL(url); }); }); + xdescribe('navigator.webkitGetUserMedia', function() { - return it('calls its callbacks', function(done) { + it('calls its callbacks', function(done) { this.timeout(5000); - return navigator.webkitGetUserMedia({ + + navigator.webkitGetUserMedia({ audio: true, video: false }, function() { - return done(); + done(); }, function() { - return done(); + done(); }); }); }); + describe('navigator.language', function() { - return it('should not be empty', function() { - return assert.notEqual(navigator.language, ''); + it('should not be empty', function() { + assert.notEqual(navigator.language, ''); }); }); + describe('navigator.serviceWorker', function() { - var url, w; - url = "file://" + fixtures + "/pages/service-worker/index.html"; - w = null; + var url = "file://" + fixtures + "/pages/service-worker/index.html"; + var w = null; + afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); - return it('should register for file scheme', function(done) { + + it('should register for file scheme', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { if (args[0] === 'reload') { - return w.webContents.reload(); + w.webContents.reload(); } else if (args[0] === 'error') { - return done('unexpected error : ' + args[1]); + done('unexpected error : ' + args[1]); } else if (args[0] === 'response') { assert.equal(args[1], 'Hello from serviceWorker!'); - return session.defaultSession.clearStorageData({ + session.defaultSession.clearStorageData({ storages: ['serviceworkers'] }, function() { - return done(); + done(); }); } }); - return w.loadURL(url); + w.loadURL(url); }); }); + describe('window.open', function() { this.timeout(20000); + it('returns a BrowserWindowProxy object', function() { - var b; - b = window.open('about:blank', '', 'show=no'); + var b = window.open('about:blank', '', 'show=no'); assert.equal(b.closed, false); assert.equal(b.constructor.name, 'BrowserWindowProxy'); - return b.close(); + b.close(); }); + it('accepts "node-integration" as feature', function(done) { var b; listener = function(event) { assert.equal(event.data, 'undefined'); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); + b = window.open("file://" + fixtures + "/pages/window-opener-node.html", '', 'nodeIntegration=no,show=no'); }); + it('inherit options of parent window', function(done) { var b; listener = function(event) { @@ -139,12 +151,13 @@ describe('chromium feature', function() { ref1 = remote.getCurrentWindow().getSize(), width = ref1[0], height = ref1[1]; assert.equal(event.data, "size: " + width + " " + height); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); + b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', 'show=no'); }); - return it('does not override child options', function(done) { + + it('does not override child options', function(done) { var b, size; size = { width: 350, @@ -153,156 +166,167 @@ describe('chromium feature', function() { listener = function(event) { assert.equal(event.data, "size: " + size.width + " " + size.height); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); + b = window.open("file://" + fixtures + "/pages/window-open-size.html", '', "show=no,width=" + size.width + ",height=" + size.height); }); }); + describe('window.opener', function() { - var url, w; this.timeout(10000); - url = "file://" + fixtures + "/pages/window-opener.html"; - w = null; + + var url = "file://" + fixtures + "/pages/window-opener.html"; + var w = null; + afterEach(function() { - return w != null ? w.destroy() : void 0; + w != null ? w.destroy() : void 0; }); + it('is null for main window', function(done) { w = new BrowserWindow({ show: false }); w.webContents.on('ipc-message', function(event, args) { assert.deepEqual(args, ['opener', null]); - return done(); + done(); }); - return w.loadURL(url); + w.loadURL(url); }); - return it('is not null for window opened by window.open', function(done) { + + it('is not null for window opened by window.open', function(done) { var b; listener = function(event) { assert.equal(event.data, 'object'); b.close(); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open(url, '', 'show=no'); + b = window.open(url, '', 'show=no'); }); }); + describe('window.postMessage', function() { - return it('sets the source and origin correctly', function(done) { + it('sets the source and origin correctly', function(done) { var b, sourceId; sourceId = remote.getCurrentWindow().id; listener = function(event) { - var message; window.removeEventListener('message', listener); b.close(); - message = JSON.parse(event.data); + var message = JSON.parse(event.data); assert.equal(message.data, 'testing'); assert.equal(message.origin, 'file://'); assert.equal(message.sourceEqualsOpener, true); assert.equal(message.sourceId, sourceId); assert.equal(event.origin, 'file://'); - return done(); + done(); }; window.addEventListener('message', listener); b = window.open("file://" + fixtures + "/pages/window-open-postMessage.html", '', 'show=no'); - return BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { - return b.postMessage('testing', '*'); + BrowserWindow.fromId(b.guestId).webContents.once('did-finish-load', function() { + b.postMessage('testing', '*'); }); }); }); + describe('window.opener.postMessage', function() { - return it('sets source and origin correctly', function(done) { + it('sets source and origin correctly', function(done) { var b; listener = function(event) { window.removeEventListener('message', listener); b.close(); assert.equal(event.source, b); assert.equal(event.origin, 'file://'); - return done(); + done(); }; window.addEventListener('message', listener); - return b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no'); + b = window.open("file://" + fixtures + "/pages/window-opener-postMessage.html", '', 'show=no'); }); }); + describe('creating a Uint8Array under browser side', function() { - return it('does not crash', function() { - var RUint8Array; - RUint8Array = remote.getGlobal('Uint8Array'); - return new RUint8Array; + it('does not crash', function() { + var RUint8Array = remote.getGlobal('Uint8Array'); + new RUint8Array; }); }); + describe('webgl', function() { - return it('can be get as context in canvas', function() { - var webgl; + it('can be get as context in canvas', function() { if (process.platform === 'linux') { return; } - webgl = document.createElement('canvas').getContext('webgl'); - return assert.notEqual(webgl, null); + var webgl = document.createElement('canvas').getContext('webgl'); + assert.notEqual(webgl, null); }); }); + describe('web workers', function() { it('Worker can work', function(done) { - var message, worker; - worker = new Worker('../fixtures/workers/worker.js'); - message = 'ping'; + var worker = new Worker('../fixtures/workers/worker.js'); + var message = 'ping'; worker.onmessage = function(event) { assert.equal(event.data, message); worker.terminate(); - return done(); + done(); }; - return worker.postMessage(message); + worker.postMessage(message); }); - return it('SharedWorker can work', function(done) { - var message, worker; - worker = new SharedWorker('../fixtures/workers/shared_worker.js'); - message = 'ping'; + + it('SharedWorker can work', function(done) { + var worker = new SharedWorker('../fixtures/workers/shared_worker.js'); + var message = 'ping'; worker.port.onmessage = function(event) { assert.equal(event.data, message); - return done(); + done(); }; - return worker.port.postMessage(message); + worker.port.postMessage(message); }); }); + describe('iframe', function() { - var iframe; - iframe = null; + var iframe = null; + beforeEach(function() { - return iframe = document.createElement('iframe'); + iframe = document.createElement('iframe'); }); + afterEach(function() { - return document.body.removeChild(iframe); + document.body.removeChild(iframe); }); - return it('does not have node integration', function(done) { + + it('does not have node integration', function(done) { iframe.src = "file://" + fixtures + "/pages/set-global.html"; document.body.appendChild(iframe); - return iframe.onload = function() { + iframe.onload = function() { assert.equal(iframe.contentWindow.test, 'undefined undefined undefined'); - return done(); + done(); }; }); }); + describe('storage', function() { - return it('requesting persitent quota works', function(done) { - return navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { + it('requesting persitent quota works', function(done) { + navigator.webkitPersistentStorage.requestQuota(1024 * 1024, function(grantedBytes) { assert.equal(grantedBytes, 1048576); - return done(); + done(); }); }); }); + describe('websockets', function() { - var WebSocketServer, server, wss; - wss = null; - server = null; - WebSocketServer = ws.Server; + var wss = null; + var server = null; + var WebSocketServer = ws.Server; + afterEach(function() { wss.close(); - return server.close(); + server.close(); }); - return it('has user agent', function(done) { + + it('has user agent', function(done) { server = http.createServer(); - return server.listen(0, '127.0.0.1', function() { + server.listen(0, '127.0.0.1', function() { var port = server.address().port; wss = new WebSocketServer({ server: server @@ -310,16 +334,17 @@ describe('chromium feature', function() { wss.on('error', done); wss.on('connection', function(ws) { if (ws.upgradeReq.headers['user-agent']) { - return done(); + done(); } else { - return done('user agent is empty'); + done('user agent is empty'); } }); new WebSocket("ws://127.0.0.1:" + port); }); }); }); - return describe('Promise', function() { + + describe('Promise', function() { it('resolves correctly in Node.js calls', function(done) { document.registerElement('x-element', { prototype: Object.create(HTMLElement.prototype, { @@ -328,17 +353,17 @@ describe('chromium feature', function() { } }) }); - return setImmediate(function() { - var called; - called = false; + setImmediate(function() { + var called = false; Promise.resolve().then(function() { - return done(called ? void 0 : new Error('wrong sequence')); + done(called ? void 0 : new Error('wrong sequence')); }); document.createElement('x-element'); - return called = true; + called = true; }); }); - return it('resolves correctly in Electron calls', function(done) { + + it('resolves correctly in Electron calls', function(done) { document.registerElement('y-element', { prototype: Object.create(HTMLElement.prototype, { createdCallback: { @@ -346,14 +371,13 @@ describe('chromium feature', function() { } }) }); - return remote.getGlobal('setImmediate')(function() { - var called; - called = false; + remote.getGlobal('setImmediate')(function() { + var called = false; Promise.resolve().then(function() { - return done(called ? void 0 : new Error('wrong sequence')); + done(called ? void 0 : new Error('wrong sequence')); }); document.createElement('y-element'); - return called = true; + called = true; }); }); }); diff --git a/spec/fixtures/api/quit-app/main.js b/spec/fixtures/api/quit-app/main.js index e2f97affe6de..114e830076a0 100644 --- a/spec/fixtures/api/quit-app/main.js +++ b/spec/fixtures/api/quit-app/main.js @@ -1,12 +1,12 @@ -var app = require('electron').app +var app = require('electron').app; app.on('ready', function () { // This setImmediate call gets the spec passing on Linux setImmediate(function () { - app.exit(123) - }) -}) + app.exit(123); + }); +}); process.on('exit', function (code) { - console.log('Exit event with code: ' + code) -}) + console.log('Exit event with code: ' + code); +}); diff --git a/spec/fixtures/devtools-extensions/foo/manifest.json b/spec/fixtures/devtools-extensions/foo/manifest.json new file mode 100644 index 000000000000..bde99de9287a --- /dev/null +++ b/spec/fixtures/devtools-extensions/foo/manifest.json @@ -0,0 +1,3 @@ +{ + "name": "foo" +} diff --git a/spec/fixtures/module/call.js b/spec/fixtures/module/call.js index 4cf232e220de..ce0eb6324df4 100644 --- a/spec/fixtures/module/call.js +++ b/spec/fixtures/module/call.js @@ -1,7 +1,7 @@ exports.call = function(func) { return func(); -} +}; exports.constructor = function() { this.test = 'test'; -} +}; diff --git a/spec/fixtures/module/class.js b/spec/fixtures/module/class.js new file mode 100644 index 000000000000..f25eb2593ff3 --- /dev/null +++ b/spec/fixtures/module/class.js @@ -0,0 +1,29 @@ +'use strict'; + +let value = 'old'; + +class BaseClass { + method() { + return 'method'; + } + + get readonly() { + return 'readonly'; + } + + get value() { + return value; + } + + set value(val) { + value = val; + } +} + +class DerivedClass extends BaseClass { +} + +module.exports = { + base: new BaseClass, + derived: new DerivedClass, +} diff --git a/spec/fixtures/module/id.js b/spec/fixtures/module/id.js index 2faec9d38321..5bfae457fe0b 100644 --- a/spec/fixtures/module/id.js +++ b/spec/fixtures/module/id.js @@ -1 +1 @@ -exports.id = 1127 +exports.id = 1127; diff --git a/spec/fixtures/module/locale-compare.js b/spec/fixtures/module/locale-compare.js index f99e7c3be119..32dfb309926b 100644 --- a/spec/fixtures/module/locale-compare.js +++ b/spec/fixtures/module/locale-compare.js @@ -1,4 +1,4 @@ -process.on('message', function (msg) { +process.on('message', function () { process.send([ 'a'.localeCompare('a'), 'ä'.localeCompare('z', 'de'), diff --git a/spec/fixtures/module/original-fs.js b/spec/fixtures/module/original-fs.js index 90b6abcf9b78..7a527c633585 100644 --- a/spec/fixtures/module/original-fs.js +++ b/spec/fixtures/module/original-fs.js @@ -1,3 +1,3 @@ -process.on('message', function (msg) { +process.on('message', function () { process.send(typeof require('original-fs')); }); diff --git a/spec/fixtures/module/print_name.js b/spec/fixtures/module/print_name.js index 01d13f4ba8bf..96ac2d6f3cb5 100644 --- a/spec/fixtures/module/print_name.js +++ b/spec/fixtures/module/print_name.js @@ -1,7 +1,7 @@ exports.print = function(obj) { return obj.constructor.name; -} +}; exports.echo = function(obj) { return obj; -} +}; diff --git a/spec/fixtures/module/promise.js b/spec/fixtures/module/promise.js index 2e52ed374400..b9b568855e30 100644 --- a/spec/fixtures/module/promise.js +++ b/spec/fixtures/module/promise.js @@ -2,4 +2,4 @@ exports.twicePromise = function (promise) { return promise.then(function (value) { return value * 2; }); -} +}; diff --git a/spec/fixtures/module/property.js b/spec/fixtures/module/property.js index 88e596f73083..36286d800e16 100644 --- a/spec/fixtures/module/property.js +++ b/spec/fixtures/module/property.js @@ -1 +1 @@ -exports.property = 1127 +exports.property = 1127; diff --git a/spec/fixtures/module/send-later.js b/spec/fixtures/module/send-later.js index 13f02452db1c..704f47d328df 100644 --- a/spec/fixtures/module/send-later.js +++ b/spec/fixtures/module/send-later.js @@ -1,4 +1,4 @@ var ipcRenderer = require('electron').ipcRenderer; window.onload = function() { ipcRenderer.send('answer', typeof window.process); -} +}; diff --git a/spec/fixtures/module/set-immediate.js b/spec/fixtures/module/set-immediate.js index e7d44a75d1fe..d36355ee23b4 100644 --- a/spec/fixtures/module/set-immediate.js +++ b/spec/fixtures/module/set-immediate.js @@ -3,7 +3,7 @@ process.on('uncaughtException', function(error) { process.exit(1); }); -process.on('message', function(msg) { +process.on('message', function() { setImmediate(function() { process.send('ok'); process.exit(0); diff --git a/spec/fixtures/pages/process-exit.html b/spec/fixtures/pages/process-exit.html new file mode 100644 index 000000000000..012c9f85b155 --- /dev/null +++ b/spec/fixtures/pages/process-exit.html @@ -0,0 +1,9 @@ + + + + + diff --git a/spec/fixtures/workers/shared_worker.js b/spec/fixtures/workers/shared_worker.js index d35b47435e8a..402207939793 100644 --- a/spec/fixtures/workers/shared_worker.js +++ b/spec/fixtures/workers/shared_worker.js @@ -1,7 +1,7 @@ -onconnect = function(event) { +this.onconnect = function(event) { var port = event.ports[0]; port.start(); port.onmessage = function(event) { port.postMessage(event.data); - } -} + }; +}; diff --git a/spec/fixtures/workers/worker.js b/spec/fixtures/workers/worker.js index 6f9533708a0d..4f445470b9ad 100644 --- a/spec/fixtures/workers/worker.js +++ b/spec/fixtures/workers/worker.js @@ -1,3 +1,3 @@ this.onmessage = function(msg) { this.postMessage(msg.data); -} +}; diff --git a/spec/modules-spec.js b/spec/modules-spec.js index 6a0471e4cea2..fb53a90cf735 100644 --- a/spec/modules-spec.js +++ b/spec/modules-spec.js @@ -3,43 +3,43 @@ const path = require('path'); const temp = require('temp'); describe('third-party module', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); temp.track(); + if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) { describe('runas', function() { it('can be required in renderer', function() { - return require('runas'); + require('runas'); }); - return it('can be required in node binary', function(done) { - var child, runas; - runas = path.join(fixtures, 'module', 'runas.js'); - child = require('child_process').fork(runas); - return child.on('message', function(msg) { + + it('can be required in node binary', function(done) { + var runas = path.join(fixtures, 'module', 'runas.js'); + var child = require('child_process').fork(runas); + child.on('message', function(msg) { assert.equal(msg, 'ok'); - return done(); + done(); }); }); }); + describe('ffi', function() { - return it('does not crash', function() { - var ffi, libm; - ffi = require('ffi'); - libm = ffi.Library('libm', { + it('does not crash', function() { + var ffi = require('ffi'); + var libm = ffi.Library('libm', { ceil: ['double', ['double']] }); - return assert.equal(libm.ceil(1.5), 2); + assert.equal(libm.ceil(1.5), 2); }); }); } - return describe('q', function() { - var Q; - Q = require('q'); - return describe('Q.when', function() { - return it('emits the fullfil callback', function(done) { - return Q(true).then(function(val) { + + describe('q', function() { + var Q = require('q'); + describe('Q.when', function() { + it('emits the fullfil callback', function(done) { + Q(true).then(function(val) { assert.equal(val, true); - return done(); + done(); }); }); }); diff --git a/spec/node-spec.js b/spec/node-spec.js index 6f84f59921f9..83f685d95f04 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -6,95 +6,96 @@ const os = require('os'); const remote = require('electron').remote; describe('node feature', function() { - var fixtures; - fixtures = path.join(__dirname, 'fixtures'); + var fixtures = path.join(__dirname, 'fixtures'); + describe('child_process', function() { - return describe('child_process.fork', function() { + describe('child_process.fork', function() { it('works in current process', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'ping.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); + it('preserves args', function(done) { - var args, child; - args = ['--expose_gc', '-test', '1']; - child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args); + var args = ['--expose_gc', '-test', '1']; + var child = child_process.fork(path.join(fixtures, 'module', 'process_args.js'), args); child.on('message', function(msg) { assert.deepEqual(args, msg.slice(2)); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); + it('works in forked process', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); + it('works in forked process when options.env is specifed', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], { + var child = child_process.fork(path.join(fixtures, 'module', 'fork_ping.js'), [], { path: process.env['PATH'] }); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); + it('works in browser process', function(done) { - var child, fork; - fork = remote.require('child_process').fork; - child = fork(path.join(fixtures, 'module', 'ping.js')); + var fork = remote.require('child_process').fork; + var child = fork(path.join(fixtures, 'module', 'ping.js')); child.on('message', function(msg) { assert.equal(msg, 'message'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); + it('has String::localeCompare working in script', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); + var child = child_process.fork(path.join(fixtures, 'module', 'locale-compare.js')); child.on('message', function(msg) { assert.deepEqual(msg, [0, -1, 1]); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); - return it('has setImmediate working in script', function(done) { - var child; - child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js')); + + it('has setImmediate working in script', function(done) { + var child = child_process.fork(path.join(fixtures, 'module', 'set-immediate.js')); child.on('message', function(msg) { assert.equal(msg, 'ok'); - return done(); + done(); }); - return child.send('message'); + child.send('message'); }); }); }); + describe('contexts', function() { describe('setTimeout in fs callback', function() { if (process.env.TRAVIS === 'true') { return; } - return it('does not crash', function(done) { - return fs.readFile(__filename, function() { - return setTimeout(done, 0); + + it('does not crash', function(done) { + fs.readFile(__filename, function() { + setTimeout(done, 0); }); }); }); + describe('throw error in node context', function() { - return it('gets caught', function(done) { - var error, lsts; - error = new Error('boo!'); - lsts = process.listeners('uncaughtException'); + it('gets caught', function(done) { + var error = new Error('boo!'); + var lsts = process.listeners('uncaughtException'); process.removeAllListeners('uncaughtException'); process.on('uncaughtException', function() { var i, len, lst; @@ -103,91 +104,97 @@ describe('node feature', function() { lst = lsts[i]; process.on('uncaughtException', lst); } - return done(); + done(); }); - return fs.readFile(__filename, function() { + fs.readFile(__filename, function() { throw error; }); }); }); + describe('setTimeout called under Chromium event loop in browser process', function() { - return it('can be scheduled in time', function(done) { - return remote.getGlobal('setTimeout')(done, 0); + it('can be scheduled in time', function(done) { + remote.getGlobal('setTimeout')(done, 0); }); }); - return describe('setInterval called under Chromium event loop in browser process', function() { - return it('can be scheduled in time', function(done) { + + describe('setInterval called under Chromium event loop in browser process', function() { + it('can be scheduled in time', function(done) { var clear, interval; clear = function() { remote.getGlobal('clearInterval')(interval); - return done(); + done(); }; - return interval = remote.getGlobal('setInterval')(clear, 10); + interval = remote.getGlobal('setInterval')(clear, 10); }); }); }); + describe('message loop', function() { describe('process.nextTick', function() { it('emits the callback', function(done) { - return process.nextTick(done); + process.nextTick(done); }); - return it('works in nested calls', function(done) { - return process.nextTick(function() { - return process.nextTick(function() { - return process.nextTick(done); + + it('works in nested calls', function(done) { + process.nextTick(function() { + process.nextTick(function() { + process.nextTick(done); }); }); }); }); - return describe('setImmediate', function() { + + describe('setImmediate', function() { it('emits the callback', function(done) { - return setImmediate(done); + setImmediate(done); }); - return it('works in nested calls', function(done) { - return setImmediate(function() { - return setImmediate(function() { - return setImmediate(done); + + it('works in nested calls', function(done) { + setImmediate(function() { + setImmediate(function() { + setImmediate(done); }); }); }); }); }); + describe('net.connect', function() { if (process.platform !== 'darwin') { return; } - return it('emit error when connect to a socket path without listeners', function(done) { - var child, script, socketPath; - socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); - script = path.join(fixtures, 'module', 'create_socket.js'); - child = child_process.fork(script, [socketPath]); - return child.on('exit', function(code) { - var client; + + it('emit error when connect to a socket path without listeners', function(done) { + var socketPath = path.join(os.tmpdir(), 'atom-shell-test.sock'); + var script = path.join(fixtures, 'module', 'create_socket.js'); + var child = child_process.fork(script, [socketPath]); + child.on('exit', function(code) { assert.equal(code, 0); - client = require('net').connect(socketPath); - return client.on('error', function(error) { + var client = require('net').connect(socketPath); + client.on('error', function(error) { assert.equal(error.code, 'ECONNREFUSED'); - return done(); + done(); }); }); }); }); + describe('Buffer', function() { it('can be created from WebKit external string', function() { - var b, p; - p = document.createElement('p'); + var p = document.createElement('p'); p.innerText = '闲云潭影日悠悠,物换星移几度秋'; - b = new Buffer(p.innerText); + var b = new Buffer(p.innerText); assert.equal(b.toString(), '闲云潭影日悠悠,物换星移几度秋'); - return assert.equal(Buffer.byteLength(p.innerText), 45); + assert.equal(Buffer.byteLength(p.innerText), 45); }); - return it('correctly parses external one-byte UTF8 string', function() { - var b, p; - p = document.createElement('p'); + + it('correctly parses external one-byte UTF8 string', function() { + var p = document.createElement('p'); p.innerText = 'Jøhänñéß'; - b = new Buffer(p.innerText); + var b = new Buffer(p.innerText); assert.equal(b.toString(), 'Jøhänñéß'); - return assert.equal(Buffer.byteLength(p.innerText), 13); + assert.equal(Buffer.byteLength(p.innerText), 13); }); }); diff --git a/spec/static/main.js b/spec/static/main.js index 125ef72f609c..48fdf17c3dcf 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -74,7 +74,7 @@ app.on('ready', function() { // Send auto updater errors to window to be verified in specs electron.autoUpdater.on('error', function (error) { - window.send('auto-updater-error', error.message) + window.send('auto-updater-error', error.message); }); window = new BrowserWindow({ @@ -108,7 +108,7 @@ app.on('ready', function() { // reply the result to renderer for verifying var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); ipcMain.on('set-download-option', function(event, need_cancel, prevent_default) { - window.webContents.session.once('will-download', function(e, item, webContents) { + window.webContents.session.once('will-download', function(e, item) { if (prevent_default) { e.preventDefault(); const url = item.getURL(); diff --git a/spec/webview-spec.js b/spec/webview-spec.js index a18e152ea6aa..d73a177d0970 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -95,8 +95,7 @@ describe(' tag', function() { describe('preload attribute', function() { it('loads the script before other scripts in window', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'function object object'); webview.removeEventListener('console-message', listener); done(); @@ -118,15 +117,14 @@ describe(' tag', function() { }); it('receives ipc message in preload script', function(done) { - var listener, listener2, message; - message = 'boom!'; - listener = function(e) { + var message = 'boom!'; + var listener = function(e) { assert.equal(e.channel, 'pong'); assert.deepEqual(e.args, [message]); webview.removeEventListener('ipc-message', listener); done(); }; - listener2 = function() { + var listener2 = function() { webview.send('ping', message); webview.removeEventListener('did-finish-load', listener2); }; @@ -140,9 +138,8 @@ describe(' tag', function() { describe('httpreferrer attribute', function() { it('sets the referrer url', function(done) { - var listener, referrer; - referrer = 'http://github.com/'; - listener = function(e) { + var referrer = 'http://github.com/'; + var listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); done(); @@ -156,9 +153,8 @@ describe(' tag', function() { describe('useragent attribute', function() { it('sets the user agent', function(done) { - var listener, referrer; - referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; - listener = function(e) { + var referrer = 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko'; + var listener = function(e) { assert.equal(e.message, referrer); webview.removeEventListener('console-message', listener); done(); @@ -172,10 +168,9 @@ describe(' tag', function() { describe('disablewebsecurity attribute', function() { it('does not disable web security when not set', function(done) { - var encoded, listener, src; - src = " "; - encoded = btoa(unescape(encodeURIComponent(src))); - listener = function(e) { + var src = " "; + var encoded = btoa(unescape(encodeURIComponent(src))); + var listener = function(e) { assert(/Not allowed to load local resource/.test(e.message)); webview.removeEventListener('console-message', listener); done(); @@ -186,10 +181,9 @@ describe(' tag', function() { }); it('disables web security when set', function(done) { - var encoded, listener, src; - src = " "; - encoded = btoa(unescape(encodeURIComponent(src))); - listener = function(e) { + var src = " "; + var encoded = btoa(unescape(encodeURIComponent(src))); + var listener = function(e) { assert.equal(e.message, 'ok'); webview.removeEventListener('console-message', listener); done(); @@ -223,8 +217,7 @@ describe(' tag', function() { }); it('isolates storage for different id', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, " 0"); webview.removeEventListener('console-message', listener); done(); @@ -237,8 +230,7 @@ describe(' tag', function() { }); it('uses current session storage when no id is provided', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, "one 1"); webview.removeEventListener('console-message', listener); done(); @@ -252,8 +244,7 @@ describe(' tag', function() { describe('allowpopups attribute', function() { it('can not open new window when not set', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'null'); webview.removeEventListener('console-message', listener); done(); @@ -264,8 +255,7 @@ describe(' tag', function() { }); it('can open new window when set', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.message, 'window'); webview.removeEventListener('console-message', listener); done(); @@ -327,9 +317,8 @@ describe(' tag', function() { describe('page-favicon-updated event', function() { it('emits when favicon urls are received', function(done) { webview.addEventListener('page-favicon-updated', function(e) { - var pageUrl; assert.equal(e.favicons.length, 2); - pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; + var pageUrl = process.platform === 'win32' ? 'file:///C:/favicon.png' : 'file:///favicon.png'; assert.equal(e.favicons[0], pageUrl); done(); }); @@ -350,10 +339,9 @@ describe(' tag', function() { }); describe('did-navigate event', function() { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); + var p = path.join(fixtures, 'pages', 'webview-will-navigate.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -370,10 +358,9 @@ describe(' tag', function() { }); describe('did-navigate-in-page event', function() { it('emits when an anchor link is clicked', function(done) { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page.html'); + var p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -396,10 +383,9 @@ describe(' tag', function() { }); it('emits when window.location.hash is changed', function(done) { - var p, pageUrl; - p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); + var p = path.join(fixtures, 'pages', 'webview-did-navigate-in-page-with-hash.html'); p = p.replace(/\\/g, '/'); - pageUrl = url.format({ + var pageUrl = url.format({ protocol: 'file', slashes: true, pathname: p @@ -425,8 +411,7 @@ describe(' tag', function() { describe('devtools-opened event', function() { it('should fire when webview.openDevTools() is called', function(done) { - var listener; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); done(); @@ -442,12 +427,11 @@ describe(' tag', function() { describe('devtools-closed event', function() { it('should fire when webview.closeDevTools() is called', function(done) { - var listener, listener2; - listener2 = function() { + var listener2 = function() { webview.removeEventListener('devtools-closed', listener2); done(); }; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-opened', listener); webview.closeDevTools(); }; @@ -463,8 +447,7 @@ describe(' tag', function() { describe('devtools-focused event', function() { it('should fire when webview.openDevTools() is called', function(done) { - var listener; - listener = function() { + var listener = function() { webview.removeEventListener('devtools-focused', listener); webview.closeDevTools(); done(); @@ -480,13 +463,12 @@ describe(' tag', function() { describe('.reload()', function() { it('should emit beforeunload handler', function(done) { - var listener, listener2; - listener = function(e) { + var listener = function(e) { assert.equal(e.channel, 'onbeforeunload'); webview.removeEventListener('ipc-message', listener); done(); }; - listener2 = function() { + var listener2 = function() { webview.reload(); webview.removeEventListener('did-finish-load', listener2); }; @@ -500,8 +482,7 @@ describe(' tag', function() { describe('.clearHistory()', function() { it('should clear the navigation history', function(done) { - var listener; - listener = function(e) { + var listener = function(e) { assert.equal(e.channel, 'history'); assert.equal(e.args[0], 2); assert(webview.canGoBack()); @@ -518,14 +499,12 @@ describe(' tag', function() { }); describe('basic auth', function() { - var auth; - auth = require('basic-auth'); + var auth = require('basic-auth'); + it('should authenticate with correct credentials', function(done) { - var message, server; - message = 'Authenticated'; - server = http.createServer(function(req, res) { - var credentials; - credentials = auth(req); + var message = 'Authenticated'; + var server = http.createServer(function(req, res) { + var credentials = auth(req); if (credentials.name === 'test' && credentials.pass === 'test') { res.end(message); } else { @@ -534,8 +513,7 @@ describe(' tag', function() { server.close(); }); server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; webview.addEventListener('ipc-message', function(e) { assert.equal(e.channel, message); done(); @@ -549,11 +527,9 @@ describe(' tag', function() { describe('dom-ready event', function() { it('emits when document is loaded', function(done) { - var server; - server = http.createServer(function() {}); + var server = http.createServer(function() {}); server.listen(0, '127.0.0.1', function() { - var port; - port = server.address().port; + var port = server.address().port; webview.addEventListener('dom-ready', function() { done(); }); @@ -575,14 +551,12 @@ describe(' tag', function() { } it('should support user gesture', function(done) { - var listener, listener2; - listener = function() { + var listener = function() { webview.removeEventListener('enter-html-full-screen', listener); done(); }; - listener2 = function() { - var jsScript; - jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; + var listener2 = function() { + var jsScript = 'document.getElementsByTagName("video")[0].webkitRequestFullScreen()'; webview.executeJavaScript(jsScript, true); webview.removeEventListener('did-finish-load', listener2); }; @@ -634,8 +608,7 @@ describe(' tag', function() { describe('media-started-playing media-paused events', function() { it('emits when audio starts and stops playing', function(done) { - var audioPlayed; - audioPlayed = false; + var audioPlayed = false; webview.addEventListener('media-started-playing', function() { audioPlayed = true; }); @@ -650,9 +623,8 @@ describe(' tag', function() { describe('found-in-page event', function() { it('emits when a request is made', function(done) { - var listener, listener2, requestId; - requestId = null; - listener = function(e) { + var requestId = null; + var listener = function(e) { assert.equal(e.result.requestId, requestId); if (e.result.finalUpdate) { assert.equal(e.result.matches, 3); @@ -660,7 +632,7 @@ describe(' tag', function() { done(); } }; - listener2 = function() { + var listener2 = function() { requestId = webview.findInPage("virtual"); }; webview.addEventListener('found-in-page', listener); @@ -731,4 +703,17 @@ describe(' tag', function() { document.body.appendChild(webview); }); }); + + describe('.getWebContents', function() { + it('can return the webcontents associated', function(done) { + webview.addEventListener('did-finish-load', function() { + const webviewContents = webview.getWebContents(); + assert(webviewContents); + assert.equal(webviewContents.getURL(), 'about:blank'); + done(); + }); + webview.src = "about:blank"; + document.body.appendChild(webview); + }); + }); }); diff --git a/vendor/brightray b/vendor/brightray index 2a5cd7178b64..d06de26dff8b 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 2a5cd7178b641de91ca6eb0bca826fea588f923a +Subproject commit d06de26dff8b641d9aee4c78ee830b416710f554 diff --git a/vendor/node b/vendor/node index a130651f868f..a507a3c3816d 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit a130651f868f5ad23cb366abacea02f9ed50b769 +Subproject commit a507a3c3816d6ac085ed46250c489a3d76ab8b3c