From 5e73b0372df30f13e993c33dbd71d04cf8699ee0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 May 2016 17:38:03 +0900 Subject: [PATCH 001/510] Make the drag box fill the remaining height of window --- default_app/index.html | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/default_app/index.html b/default_app/index.html index c10d67a089ac..a6126e5de6c7 100644 --- a/default_app/index.html +++ b/default_app/index.html @@ -10,10 +10,15 @@ font-variant: normal; padding: 0; margin: 0; + display: flex; + flex-direction: column; } .container { - padding: 15px 30px; + margin: 15px 30px 30px 30px; + flex: 1; + display: flex; + flex-direction: column; } .header { @@ -90,11 +95,9 @@ #holder { display: flex; + flex: 1; align-items: center; justify-content: center; - margin: 0 auto; - padding: 10px; - height: 275px; border: 1px solid #e0e5e6; background-color: #f6f8f8; color: #466a72; @@ -132,7 +135,7 @@ }; -
+
-
+
From 7074789011541b72ef838107baa2a1d68ef9cd76 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 4 May 2016 17:43:21 +0900 Subject: [PATCH 002/510] Remove some unnecessary css rules --- default_app/index.html | 6 ------ 1 file changed, 6 deletions(-) diff --git a/default_app/index.html b/default_app/index.html index a6126e5de6c7..b7910f00ef84 100644 --- a/default_app/index.html +++ b/default_app/index.html @@ -4,11 +4,7 @@ +``` + +## Tag 属性 + +`webview`タグは下記のような属性を持っています: + +### `src` + +```html + +``` + +表示されているURLを返します。本属性への書き込みは、トップレベルナビゲーションを開始させます。 + +`src`の値を現在の値に再度設定することで、現在のページを再読み込みさせることができます。 + +また、`src`属性はdata URLを指定することができます(例: `data:text/plain,Hello, world!`)。 + +### `autosize` + +```html + +``` + +"on"の際は、`minwidth`, `minheight`, `maxwidth`, `maxheight`で設定された範囲内で、自動的に大きさが変化します。 +これらの制限値は、`autosize`が有効でない場合は影響しません。 +`autosize`が有効の際は、`webview`コンテナサイズは指定した最小値より小さくなりませんし、最大値より大きくなりません。 + +### `nodeintegration` + +```html + +``` + +"on"の際は、`webview`内のゲストページ(外部コンテンツ)でnode integrationが有効となり、`require`や`process`と行ったnode APIでシステムリソースにアクセスできるようになります。1 + +**注意:** 親ウィンドウでnode integrationが無効の場合は、`webview`でも常に無効になります。 + + +### `plugins` + +```html + +``` + +"on"の際は、ゲストページはブラウザプラグインを使用できます。 + +### `preload` + +```html + +``` + +ゲストページ上のスクリプトより先に実行されるスクリプトを指定してください。内部では、ゲストページ内で`require`で読み込まれるので、スクリプトのURLのプロトコルはは`file:`または`asar:`でなければなりません。 + +ゲストページがnode integrationが無効の場合でも、このスクリプトは全てのNode APIにアクセスできます。ただし、グローバルオブジェクトはこのスクリプトの実行終了後にすべて削除されます。 + +### `httpreferrer` + +```html + +``` + +ゲストページのためにリファラを設定します。 + +### `useragent` + +```html + +``` + +ページ遷移の前に、User agentを指定します。すでにページが読み込まれている場合は、`setUserAgent`メソッドを利用して変更してください。 + +### `disablewebsecurity` + +```html + +``` + +"on"の際は、ゲストページのウェブセキュリティは無効となります。 + +### `partition` + +```html + + +``` + +ページで使用されるセッションを設定します。もし、`partition`が`persist:`から始まる場合、アプリ上の同じ`partition`を指定した全てのページで有効な永続セッションを使用します。 +`persist:`接頭辞なしで指定した場合、メモリ内セッションを使用します。同じセッションを指定すると複数のページで同じセッションを使用できます。 +`partition`を設定しない場合は、アプリケーションのデフォルトセッションが使用されます。 + +レンダラプロセスのセッションは変更できないため、この値は最初のページ遷移の前に変更されないといけません。 +その後に変更をしようとしても、DOM例外を起こすことになります。 + +### `allowpopups` + +```html + +``` + +"on"の場合、ゲストページは新しいウィンドウを開くことができます。 + +### `blinkfeatures` + +```html + +``` + +有効にしたいblink featureを`,`で区切って指定します。 +サポートされている全ての機能は、[setFeatureEnabledFromString][blink-feature-string]にリストがあります。 + +## メソッド + +`webview`タグは、下記のようなメソッドを持っています: + +**注意:** webview要素はメソッドを使用する前に読み込まれていないといけません。 + +**例** + +```javascript +webview.addEventListener('dom-ready', () => { + webview.openDevTools(); +}); +``` + +### `.loadURL(url[, options])` + +* `url` URL +* `options` Object (optional) + * `httpReferrer` String - リファラURL + * `userAgent` String - リクエストに使用されるUser agent + * `extraHeaders` String - 追加のヘッダを"\n"で区切って指定します。 + +`url`をwebviewで読み込みます。`url`はプロトコル接頭辞(`http://`や`file://`など)を含んでいなければいけません。 + +### `.getURL()` + +ゲストページのURLを取得します。 + +### `.getTitle()` + +ゲストページのタイトルを返します。 + +### `.isLoading()` + +ゲストページが読み込み中かのbool値を返します。 + +### `.isWaitingForResponse()` + +ゲストページがページの最初の返答を待っているかのbool値を返します。 + +### `.stop()` + +実行待ち中のナビゲーションを中止します。 + +### `.reload()` + +ゲストページを再読み込みします。 + +### `.reloadIgnoringCache()` + +キャッシュを無効にして再読み込みします。 + +### `.canGoBack()` + +ページを戻ることができるかのbool値を返します。 + +### `.canGoForward()` + +ページを進むことができるかのbool値を返します。 + +### `.canGoToOffset(offset)` + +* `offset` Integer + +`offset`だけ、移動できるかのbool値を返します。 + +### `.clearHistory()` + +移動履歴をクリアします。 + +### `.goBack()` + +ページを戻ります。 + +### `.goForward()` + +ページを進みます。 + +### `.goToIndex(index)` + +* `index` Integer + +インデックスを指定して移動します。 + +### `.goToOffset(offset)` + +* `offset` Integer + +現在の場所からの移動量を指定して移動します。 + +### `.isCrashed()` + +レンダラプロセスがクラッシュしているかを返します。 + +### `.setUserAgent(userAgent)` + +* `userAgent` String + +ゲストページ用のUser agentを変更します。 + +### `.getUserAgent()` + +User agentを取得します。 + +### `.insertCSS(css)` + +* `css` String + +ゲストエージにCSSを追加します。 + +### `.executeJavaScript(code, userGesture, callback)` + +* `code` String +* `userGesture` Boolean - Default `false`. +* `callback` Function (optional) - Called after script has been executed. + * `result` + +ページ内で`code`を評価します。`userGesture`を設定した場合、ページ内でgesture contextを作成します。例えば`requestFullScreen`のようなユーザーの対応が必要なHTML APIでは、自動化時にこれが有利になる時があります。 + +### `.openDevTools()` + +DevToolsを開きます。 + +### `.closeDevTools()` + +DevToolsを閉じます。 + +### `.isDevToolsOpened()` + +DevToolsが開いているかのbool値を返します。 + +### `.isDevToolsFocused()` + +DevToolsがフォーカスを得ているかのbool値を返します。 + +### `.inspectElement(x, y)` + +* `x` Integer +* `y` Integer + +ゲストページの(`x`, `y`)の位置にある要素を調べます。 + +### `.inspectServiceWorker()` + +ゲストページのサービスワーカーのDevToolsを開きます。 + +### `.setAudioMuted(muted)` + +* `muted` Boolean + +ページをミュートするかを設定します。 + +### `.isAudioMuted()` + +ページがミュートされているかを返します。 + +### `.undo()` + +`undo` (元に戻す)を行います。 +Executes editing command `undo` in page. + +### `.redo()` + +`redo` (やり直し)を行います。 + +### `.cut()` + +`cut` (切り取り)を行います。 + +### `.copy()` + +`copy` (コピー)を行います。 + +### `.paste()` + +`paste` (貼り付け)を行います。 + +### `.pasteAndMatchStyle()` + +`pasteAndMatchStyle`(貼り付けてスタイルを合わせる)を行います。 + +### `.delete()` + +`delete` (削除)を行います。 + +### `.selectAll()` + +`selectAll` (全て選択)を行います。 + +### `.unselect()` + +`unselect` (選択を解除)を行います。 + +### `.replace(text)` + +* `text` String + +`replace` (置き換え)を行います。 + +### `.replaceMisspelling(text)` + +* `text` String + +`replaceMisspelling` (スペル違いを置き換え)を行います。 + +### `.insertText(text)` + +* `text` String + +`text`を選択された要素に挿入します。 + +### `.findInPage(text[, options])` + +* `text` String - 検索する文字列(空文字列にはできません) +* `options` Object (省略可) + * `forward` Boolean - 前方・後方のどちらを検索するかどうかです。省略時は`true`で前方に検索します。 + * `findNext` Boolean - 初回検索か、次を検索するかを選びます。省略時は`false`で、初回検索です。 + * `matchCase` Boolean - 大文字・小文字を区別するかを指定します。省略時は`false`で、区別しません。 + * `wordStart` Boolean - ワード始まりからの検索かを指定します。省略時は`false`で、語途中でもマッチします。 + * `medialCapitalAsWordStart` Boolean - `wordStart`指定時、CamelCaseの途中もワード始まりと見なすかを指定します。省略時は`false`です。 + +`text`をページ内全てから検索し、リクエストに使用するリクエストID(`Integer`)を返します。リクエストの結果は、[`found-in-page`](web-view-tag.md#event-found-in-page)イベントを介して受け取ることができます。 + +### `.stopFindInPage(action)` + +* `action` String - [`.findInPage`](web-view-tag.md#webviewtagfindinpage)リクエストを終わらせる時にとるアクションを指定します。 + * `clearSelection` - 選択をクリアします。 + * `keepSelection` - 選択を通常の選択へと変換します。 + * `activateSelection` - 選択ノードにフォーカスを当て、クリックします。 + +`action`にしたがって`webview`への`findInPage`リクエストを中止します。 + +### `.print([options])` + +`webview`で表示されているウェブページを印刷します。`webContents.print([options])`と同じです。 + +### `.printToPDF(options, callback)` + +`webview`のウェブサイトをPDFとして印刷します。`webContents.printToPDF(options, callback)`と同じです。 + +### `.send(channel[, arg1][, arg2][, ...])` + +* `channel` String +* `arg` (optional) + +`channel`を通じてレンダラプロセスに非同期メッセージを送ります。合わせて、 +任意のメッセージを送ることができます。レンダラプロセスは`ipcRenderer`モジュールを +使用して、`channel`イベントでメッセージを把握することができます。 + +サンプルが[webContents.send](web-contents.md#webcontentssendchannel-args)にあります。 + +### `.sendInputEvent(event)` + +* `event` Object + +入力イベント(`event`)をページに送ります。 + +`event`に関する詳しい説明は、[webContents.sendInputEvent](web-contents.md##webcontentssendinputeventevent)を +参照してください。 + +### `.getWebContents()` + +`webview`に関連付けられた[WebContents](web-contents.md)を取得します。 + +## DOM events + +`webview`タグで有効なイベントは次の通りです: + +### Event: 'load-commit' + +返り値: + +* `url` String +* `isMainFrame` Boolean + +読み込みが行われる時に発生するイベントです。 +これには、現在のドキュメントやサブフレームの読み込みが含まれます。ただし、非同期なリソース読み込みは含まれません。 + +### Event: 'did-finish-load' + +ナビゲーションが完了した際に発生するイベントです。 +言い換えると、タブ上の"くるくる"が止まった時に発生し、`onload`イベントが配信されます。 + +### Event: 'did-fail-load' + +返り値: + +* `errorCode` Integer +* `errorDescription` String +* `validatedURL` String +* `isMainFrame` Boolean + +`did-finish-load`と同じようですが、読み込みに失敗した時やキャンセルされた時に発生します。 +例えば、`window.stop()`が呼ばれた時などです。 + +### Event: 'did-frame-finish-load' + +返り値: + +* `isMainFrame` Boolean + +フレームがナビゲーションを終えた時に発生します。 + +### Event: 'did-start-loading' + +タブ上の"くるくる"が回転を始めた時点でこのイベントが発生します。 + +### Event: 'did-stop-loading' + +タブ上の"くるくる"が回転をやめた時点でこのイベントが発生します。 + +### Event: 'did-get-response-details' + +返り値: + +* `status` Boolean +* `newURL` String +* `originalURL` String +* `httpResponseCode` Integer +* `requestMethod` String +* `referrer` String +* `headers` Object +* `resourceType` String + +読み込むリソースの詳細がわかった時点で発生します。 +`status`は、リソースをダウンロードするソケット接続であるかを示します。 + +### Event: 'did-get-redirect-request' + +返り値: + +* `oldURL` String +* `newURL` String +* `isMainFrame` Boolean + +リソースの取得中に、リダイレクトを受け取った際に発生します。 + +### Event: 'dom-ready' + +該当フレーム内のドキュメントが読み込まれた時に発生します。 + +### Event: 'page-title-updated' + +返り値: + +* `title` String +* `explicitSet` Boolean + +ページのタイトルが設定された時に発生します。 +タイトルがurlから作られたものであれば、`explicitSet`は`false`になります。 + +### Event: 'page-favicon-updated' + +返り値: + +* `favicons` Array - URLの配列 + +ページのfavicon URLを受け取った時に発生します。 + +### Event: 'enter-html-full-screen' + +HTML APIでフルスクリーンになった際に発生します。 + +### Event: 'leave-html-full-screen' + +HTML APIでフルスクリーンでなくなった際に発生します。 + +### Event: 'console-message' + +返り値: + +* `level` Integer +* `message` String +* `line` Integer +* `sourceId` String + +ゲストウィンドウがコンソールメッセージを記録する際に発生します。 + +下記のサンプルは、埋め込まれたサイトのログを、log levelに関係なく親側に転送します。 + + +```javascript +webview.addEventListener('console-message', (e) => { + console.log('Guest page logged a message:', e.message); +}); +``` + +### Event: 'found-in-page' + +返り値: + +* `result` Object + * `requestId` Integer + * `finalUpdate` Boolean - 次のレスポンスが待っているかを示します。 + * `activeMatchOrdinal` Integer (optional) - このマッチの場所を示します。 + * `matches` Integer (optional) - マッチした数です。 + * `selectionArea` Object (optional) - 最初のマッチした場所です。 + +[`webview.findInPage`](web-view-tag.md#webviewtagfindinpage)リクエストで結果が得られた場合に発生します。 + +```javascript +webview.addEventListener('found-in-page', (e) => { + if (e.result.finalUpdate) + webview.stopFindInPage('keepSelection'); +}); + +const requestId = webview.findInPage('test'); +``` + +### Event: 'new-window' + +返り値: + +* `url` String +* `frameName` String +* `disposition` String -`default`, `foreground-tab`, `background-tab`, + `new-window`, `other`のどれかです。 +* `options` Object - 新しい`BrowserWindow`を作る際に使用されるoptionです。 + +ゲストページが新しいブラウザウィンドウを開こうとする際に発生します。 + +下記のサンプルは、新しいURLをシステムのデフォルトブラウザで開きます。 + +```javascript +const {shell} = require('electron'); + +webview.addEventListener('new-window', (e) => { + const protocol = require('url').parse(e.url).protocol; + if (protocol === 'http:' || protocol === 'https:') { + shell.openExternal(e.url); + } +}); +``` + +### Event: 'will-navigate' + +返り値: + +* `url` String + +ユーザーまたはページがナビゲーションを始めようとする際に発生します。これは、 +`window.location`が変更になる時や、ユーザーがリンクをクリックした際に発生します。 + +`.loadURL`や`.back`でプログラムによりナビゲーションが始まった場合は +このイベントは発生しません。 + +アンカーリンクのクリックや`window.location.hash`の変更といった、ページ内遷移でも、このイベントは発生しません。 +この場合は、`did-navigate-in-page`イベントを使ってください。 + +`event.preventDefault()`は使用しても__何も起こりません__。 + +### Event: 'did-navigate' + +返り値: + +* `url` String + +ナビゲーション終了時に呼ばれます。 + +アンカーリンクのクリックや`window.location.hash`の変更といった、ページ内遷移では、このイベントは発生しません。 +この場合は、`did-navigate-in-page`イベントを使ってください。 + +### Event: 'did-navigate-in-page' + +返り値: + +* `url` String + +ページ内遷移の際に発生します。 + +ページ内遷移の際は、ページURLは変更になりますが、ページ外部へのナビゲーションは発生しません。 +例として、アンカーリンクのクリック時や、DOMの`hashchange`イベントが発生した時にこれが起こります。 + +### Event: 'close' + +ゲストページそのものが、閉じられようとしている際に発生します。 + +下記のサンプルは、`webview`が閉じられる際に、`about:blank`にナビゲートします。 + +```javascript +webview.addEventListener('close', () => { + webview.src = 'about:blank'; +}); +``` + +### Event: 'ipc-message' + +返り値: + +* `channel` String +* `args` Array + +ゲストページが埋め込み元に非同期メッセージを送ってきた際に発生します。 + +`sendToHost`メソッドと、`ipc-message`イベントを利用すると、ゲストページと埋め込み元のページでデータのやり取りを簡単に行うことができます。 + +```javascript +// 埋め込み元ページ(があるページ)で +webview.addEventListener('ipc-message', (event) => { + console.log(event.channel); + // Prints "pong" +}); +webview.send('ping'); +``` + +```javascript +// ゲストページ(内)で +const {ipcRenderer} = require('electron'); +ipcRenderer.on('ping', () => { + ipcRenderer.sendToHost('pong'); +}); +``` + +### Event: 'crashed' + +プロセスがクラッシュした際に発生します。 + +### Event: 'gpu-crashed' + +GPUプロセスがクラッシュした際に発生します。 + +### Event: 'plugin-crashed' + +返り値: + +* `name` String +* `version` String + +プラグインプロセスがクラッシュした際に発生します。 + +### Event: 'destroyed' + +WebContentsが破壊された際に呼ばれます。 + +### Event: 'media-started-playing' + +メディアの再生が開始された際に呼ばれます。 + +### Event: 'media-paused' + +メディアが一時停止になるか、再生を終えた際に呼ばれます。 + +### Event: 'did-change-theme-color' + +返り値: + +* `themeColor` String + +ページのテーマカラーが変更になった際に呼ばれます。 +これは、下記のようなメタタグがある際に通常発生します: + +```html + +``` + +### Event: 'devtools-opened' + +DevToolsが開かれた際に発生します。 + +### Event: 'devtools-closed' + +DevToolsが閉じられた際に発生します。 + +### Event: 'devtools-focused' + +DevToolsにフォーカスが当たった際 / 開かれた際に発生します。 + +[blink-feature-string]: https://code.google.com/p/chromium/codesearch#chromium/src/out/Debug/gen/blink/platform/RuntimeEnabledFeatures.cpp&sq=package:chromium&type=cs&l=527 From 5ab86cc2dfc5bb550ff42b66824f95a90862041d Mon Sep 17 00:00:00 2001 From: TAKAHASHI Kyohei Date: Mon, 30 May 2016 14:02:15 +0900 Subject: [PATCH 485/510] :memo: trivial change in web-view-tag.md There is a mistake about the information of `stopFindInPage`. [ci skip] --- docs/api/web-view-tag.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index b1d3aaead1e5..f99bb4fdb5a1 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -171,7 +171,7 @@ page is loaded, use the `setUserAgent` method to change the user agent. If "on", the guest page will have web security disabled. -### partition +### `partition` ```html @@ -445,8 +445,8 @@ obtained by subscribing to [`found-in-page`](web-view-tag.md#event-found-in-page * `action` String - Specifies the action to take place when ending [`.findInPage`](web-view-tag.md#webviewtagfindinpage) request. - * `clearSelection` - Translate the selection into a normal selection. - * `keepSelection` - Clear the selection. + * `clearSelection` - Clear the selection. + * `keepSelection` - Translate the selection into a normal selection. * `activateSelection` - Focus and click the selection node. Stops any `findInPage` request for the `webview` with the provided `action`. @@ -457,7 +457,7 @@ Prints `webview`'s web page. Same with `webContents.print([options])`. ### `.printToPDF(options, callback)` -Prints webview's web page as PDF, Same with `webContents.printToPDF(options, callback)` +Prints `webview`'s web page as PDF, Same with `webContents.printToPDF(options, callback)` ### `.send(channel[, arg1][, arg2][, ...])` @@ -628,7 +628,7 @@ webview.addEventListener('found-in-page', (e) => { webview.stopFindInPage('keepSelection'); }); -const rquestId = webview.findInPage('test'); +const requestId = webview.findInPage('test'); ``` ### Event: 'new-window' From ce0d3d93abe060b5c46a55b85bc93eca1b6a9984 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 May 2016 15:20:53 +0900 Subject: [PATCH 486/510] spec: disablewebsecurity should not break preload and node integration --- spec/api-ipc-spec.js | 2 +- spec/webview-spec.js | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spec/api-ipc-spec.js b/spec/api-ipc-spec.js index 66fa308dd621..e88815873af9 100644 --- a/spec/api-ipc-spec.js +++ b/spec/api-ipc-spec.js @@ -29,7 +29,7 @@ describe('ipc module', function () { assert.equal(a.id, 1127) }) - it.only('should work when object has no prototype', function () { + it('should work when object has no prototype', function () { var a = remote.require(path.join(fixtures, 'module', 'no-prototype.js')) assert.equal(a.foo.bar, 'baz') assert.equal(a.foo.baz, false) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 7bdb3a632e0c..b1fa4405ada8 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -259,6 +259,30 @@ describe(' tag', function () { webview.src = 'data:text/html;base64,' + encoded document.body.appendChild(webview) }) + + it('does not break node integration', function (done) { + webview.addEventListener('console-message', function (e) { + assert.equal(e.message, 'function object object') + done() + }) + webview.setAttribute('nodeintegration', 'on') + webview.setAttribute('disablewebsecurity', '') + webview.src = 'file://' + fixtures + '/pages/d.html' + document.body.appendChild(webview) + }) + + it('does not break preload script', function (done) { + var listener = function (e) { + assert.equal(e.message, 'function object object') + webview.removeEventListener('console-message', listener) + done() + } + webview.addEventListener('console-message', listener) + webview.setAttribute('disablewebsecurity', '') + webview.setAttribute('preload', fixtures + '/module/preload.js') + webview.src = 'file://' + fixtures + '/pages/e.html' + document.body.appendChild(webview) + }) }) describe('partition attribute', function () { From 6755aa44f67b6dcad4937d09e14d87b38a8686e7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 May 2016 14:56:31 +0900 Subject: [PATCH 487/510] Initialize script context in DidClearWindowObject Doing it in RunScriptsAtDocumentStart would somehow result in weird results when webSecurity is off. --- atom/renderer/atom_renderer_client.cc | 12 +++++++++--- atom/renderer/atom_renderer_client.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/atom/renderer/atom_renderer_client.cc b/atom/renderer/atom_renderer_client.cc index 283930b829a2..ee2dd7d54e04 100644 --- a/atom/renderer/atom_renderer_client.cc +++ b/atom/renderer/atom_renderer_client.cc @@ -68,6 +68,10 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver { renderer_client_(renderer_client) {} // content::RenderFrameObserver: + void DidClearWindowObject() override { + renderer_client_->DidClearWindowObject(render_frame_); + } + void DidCreateScriptContext(v8::Handle context, int extension_group, int world_id) override { @@ -185,12 +189,14 @@ void AtomRendererClient::RenderViewCreated(content::RenderView* render_view) { } } -void AtomRendererClient::RunScriptsAtDocumentStart( +void AtomRendererClient::DidClearWindowObject( content::RenderFrame* render_frame) { // Make sure every page will get a script context created. - render_frame->GetWebFrame()->executeScript( - blink::WebScriptSource("void 0")); + render_frame->GetWebFrame()->executeScript(blink::WebScriptSource("void 0")); +} +void AtomRendererClient::RunScriptsAtDocumentStart( + content::RenderFrame* render_frame) { // Inform the document start pharse. node::Environment* env = node_bindings_->uv_env(); if (env) { diff --git a/atom/renderer/atom_renderer_client.h b/atom/renderer/atom_renderer_client.h index 51872e5bcba9..f4a548908e06 100644 --- a/atom/renderer/atom_renderer_client.h +++ b/atom/renderer/atom_renderer_client.h @@ -21,6 +21,7 @@ class AtomRendererClient : public content::ContentRendererClient { AtomRendererClient(); virtual ~AtomRendererClient(); + void DidClearWindowObject(content::RenderFrame* render_frame); void DidCreateScriptContext( v8::Handle context, content::RenderFrame* render_frame); void WillReleaseScriptContext( From 49f127860183bbc4fa9a95ceb7b2e3d08c3ec996 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 May 2016 20:31:00 +0900 Subject: [PATCH 488/510] Refactor the URLRequestFetchJob code This makes the read end and write end of the pipe have same logic, so it is more easy to maintain. --- atom/browser/net/url_request_fetch_job.cc | 93 +++++++++++------------ atom/browser/net/url_request_fetch_job.h | 25 +++--- spec/api-protocol-spec.js | 2 +- 3 files changed, 61 insertions(+), 59 deletions(-) diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 388b9f9550b3..0f293c22fcf6 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -77,7 +77,8 @@ class ResponsePiper : public net::URLFetcherResponseWriter { URLRequestFetchJob::URLRequestFetchJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) : JsAsker(request, network_delegate), - pending_buffer_size_(0) { + pending_buffer_size_(0), + write_num_bytes_(0) { } void URLRequestFetchJob::BeforeStartInUI( @@ -169,22 +170,21 @@ void URLRequestFetchJob::HeadersCompleted() { int URLRequestFetchJob::DataAvailable(net::IOBuffer* buffer, int num_bytes, const net::CompletionCallback& callback) { - // Store the data in a drainable IO buffer if pending_buffer_ is empty, i.e. - // there's no ReadRawData() operation waiting for IO completion. + // When pending_buffer_ is empty, there's no ReadRawData() operation waiting + // for IO completion, we have to save the parameters until the request is + // ready to read data. if (!pending_buffer_.get()) { - response_piper_callback_ = callback; - drainable_buffer_ = new net::DrainableIOBuffer(buffer, num_bytes); + write_buffer_ = buffer; + write_num_bytes_ = num_bytes; + write_callback_ = callback; return net::ERR_IO_PENDING; } - // pending_buffer_ is set to the IOBuffer instance provided to ReadRawData() - // by URLRequestJob. - int bytes_read = std::min(num_bytes, pending_buffer_size_); - memcpy(pending_buffer_->data(), buffer->data(), bytes_read); - - ClearPendingBuffer(); - + // Write data to the pending buffer and clear them after the writing. + int bytes_read = BufferCopy(buffer, num_bytes, + pending_buffer_.get(), pending_buffer_size_); ReadRawDataComplete(bytes_read); + ClearPendingBuffer(); return bytes_read; } @@ -193,46 +193,26 @@ void URLRequestFetchJob::Kill() { fetcher_.reset(); } -void URLRequestFetchJob::StartReading() { - if (drainable_buffer_.get()) { - auto num_bytes = drainable_buffer_->BytesRemaining(); - if (num_bytes <= 0 && !response_piper_callback_.is_null()) { - int size = drainable_buffer_->BytesConsumed(); - drainable_buffer_ = nullptr; - response_piper_callback_.Run(size); - response_piper_callback_.Reset(); - return; - } - - int bytes_read = std::min(num_bytes, pending_buffer_size_); - memcpy(pending_buffer_->data(), drainable_buffer_->data(), bytes_read); - - drainable_buffer_->DidConsume(bytes_read); - - ClearPendingBuffer(); - - ReadRawDataComplete(bytes_read); - } -} - -void URLRequestFetchJob::ClearPendingBuffer() { - // Clear the buffers before notifying the read is complete, so that it is - // safe for the observer to read. - pending_buffer_ = nullptr; - pending_buffer_size_ = 0; -} - int URLRequestFetchJob::ReadRawData(net::IOBuffer* dest, int dest_size) { if (GetResponseCode() == 204) { request()->set_received_response_content_length(prefilter_bytes_read()); return net::OK; } - pending_buffer_ = dest; - pending_buffer_size_ = dest_size; - // Read from drainable_buffer_ if available, i.e. response data became - // available before ReadRawData was called. - StartReading(); - return net::ERR_IO_PENDING; + + // When write_buffer_ is empty, there is no data valable yet, we have to save + // the dest buffer util DataAvailable. + if (!write_buffer_.get()) { + pending_buffer_ = dest; + pending_buffer_size_ = dest_size; + return net::ERR_IO_PENDING; + } + + // Read from the write buffer and clear them after reading. + int bytes_read = BufferCopy(write_buffer_.get(), write_num_bytes_, + dest, dest_size); + write_callback_.Run(bytes_read); + ClearWriteBuffer(); + return bytes_read; } bool URLRequestFetchJob::GetMimeType(std::string* mime_type) const { @@ -264,6 +244,7 @@ void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) { } ClearPendingBuffer(); + ClearWriteBuffer(); if (fetcher_->GetStatus().is_success()) ReadRawDataComplete(0); @@ -271,4 +252,22 @@ void URLRequestFetchJob::OnURLFetchComplete(const net::URLFetcher* source) { NotifyStartError(fetcher_->GetStatus()); } +int URLRequestFetchJob::BufferCopy(net::IOBuffer* source, int num_bytes, + net::IOBuffer* target, int target_size) { + int bytes_written = std::min(num_bytes, target_size); + memcpy(target->data(), source->data(), bytes_written); + return bytes_written; +} + +void URLRequestFetchJob::ClearPendingBuffer() { + pending_buffer_ = nullptr; + pending_buffer_size_ = 0; +} + +void URLRequestFetchJob::ClearWriteBuffer() { + write_buffer_ = nullptr; + write_num_bytes_ = 0; + write_callback_.Reset(); +} + } // namespace atom diff --git a/atom/browser/net/url_request_fetch_job.h b/atom/browser/net/url_request_fetch_job.h index da1c1678e58a..906ba68d3965 100644 --- a/atom/browser/net/url_request_fetch_job.h +++ b/atom/browser/net/url_request_fetch_job.h @@ -9,14 +9,10 @@ #include "atom/browser/net/js_asker.h" #include "browser/url_request_context_getter.h" -#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_job.h" namespace atom { -class AtomBrowserContext; - class URLRequestFetchJob : public JsAsker, public net::URLFetcherDelegate, public brightray::URLRequestContextGetter::Delegate { @@ -30,9 +26,6 @@ class URLRequestFetchJob : public JsAsker, const net::CompletionCallback& callback); protected: - void StartReading(); - void ClearPendingBuffer(); - // JsAsker: void BeforeStartInUI(v8::Isolate*, v8::Local) override; void StartAsync(std::unique_ptr options) override; @@ -48,13 +41,23 @@ class URLRequestFetchJob : public JsAsker, void OnURLFetchComplete(const net::URLFetcher* source) override; private: + int BufferCopy(net::IOBuffer* source, int num_bytes, + net::IOBuffer* target, int target_size); + void ClearPendingBuffer(); + void ClearWriteBuffer(); + scoped_refptr url_request_context_getter_; std::unique_ptr fetcher_; - scoped_refptr pending_buffer_; - scoped_refptr drainable_buffer_; - int pending_buffer_size_; std::unique_ptr response_info_; - net::CompletionCallback response_piper_callback_; + + // Saved arguments passed to ReadRawData. + scoped_refptr pending_buffer_; + int pending_buffer_size_; + + // Saved arguments passed to DataAvailable. + scoped_refptr write_buffer_; + int write_num_bytes_; + net::CompletionCallback write_callback_; DISALLOW_COPY_AND_ASSIGN(URLRequestFetchJob); }; diff --git a/spec/api-protocol-spec.js b/spec/api-protocol-spec.js index 1b46d586a41a..803511917104 100644 --- a/spec/api-protocol-spec.js +++ b/spec/api-protocol-spec.js @@ -511,7 +511,7 @@ describe('protocol module', function () { }) }) - it('loads resource for webContents', function (done) { + it('works when target URL redirects', function (done) { var contents = null var server = http.createServer(function (req, res) { if (req.url == '/serverRedirect') { From f02143b8f2dbd125e40c13aa537c6a6a639299e7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Mon, 30 May 2016 22:31:38 +0900 Subject: [PATCH 489/510] Clear the buffers before notifying the other end of the pipe --- atom/browser/net/url_request_fetch_job.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/atom/browser/net/url_request_fetch_job.cc b/atom/browser/net/url_request_fetch_job.cc index 0f293c22fcf6..8279d09d5dad 100644 --- a/atom/browser/net/url_request_fetch_job.cc +++ b/atom/browser/net/url_request_fetch_job.cc @@ -183,8 +183,8 @@ int URLRequestFetchJob::DataAvailable(net::IOBuffer* buffer, // Write data to the pending buffer and clear them after the writing. int bytes_read = BufferCopy(buffer, num_bytes, pending_buffer_.get(), pending_buffer_size_); - ReadRawDataComplete(bytes_read); ClearPendingBuffer(); + ReadRawDataComplete(bytes_read); return bytes_read; } @@ -210,8 +210,9 @@ int URLRequestFetchJob::ReadRawData(net::IOBuffer* dest, int dest_size) { // Read from the write buffer and clear them after reading. int bytes_read = BufferCopy(write_buffer_.get(), write_num_bytes_, dest, dest_size); - write_callback_.Run(bytes_read); + net::CompletionCallback write_callback = write_callback_; ClearWriteBuffer(); + write_callback.Run(bytes_read); return bytes_read; } From 381da769671baf10008532c6dfb0cbda8fbddee5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 31 May 2016 10:19:13 +0900 Subject: [PATCH 490/510] Correctly redirect output to console --- atom/app/atom_main.cc | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/atom/app/atom_main.cc b/atom/app/atom_main.cc index 03055e04daf5..1e69ba4ba839 100644 --- a/atom/app/atom_main.cc +++ b/atom/app/atom_main.cc @@ -15,6 +15,7 @@ #include "atom/app/atom_main_delegate.h" #include "atom/common/crash_reporter/win/crash_service_main.h" #include "base/environment.h" +#include "base/process/launch.h" #include "base/win/windows_version.h" #include "content/public/app/sandbox_helper_win.h" #include "sandbox/win/src/sandbox_types.h" @@ -46,10 +47,6 @@ bool IsEnvSet(const char* name) { #endif } -bool IsRunAsNode() { - return IsEnvSet(kRunAsNode); -} - } // namespace #if defined(OS_WIN) @@ -57,14 +54,11 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { int argc = 0; wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); - // Make output work in console if we are not in cygiwn. - if (!IsEnvSet("TERM") && !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) { - AttachConsole(ATTACH_PARENT_PROCESS); + bool run_as_node = IsEnvSet(kRunAsNode); - FILE* dontcare; - freopen_s(&dontcare, "CON", "w", stdout); - freopen_s(&dontcare, "CON", "w", stderr); - } + // Make sure the output is printed to console. + if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE")) + base::RouteStdioToConsole(false); // Convert argv to to UTF8 char** argv = new char*[argc]; @@ -100,7 +94,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { } } - if (IsRunAsNode()) { + if (run_as_node) { // Now that argv conversion is done, we can finally start. base::AtExitManager atexit_manager; base::i18n::InitializeICU(); @@ -123,7 +117,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) { #elif defined(OS_LINUX) // defined(OS_WIN) int main(int argc, const char* argv[]) { - if (IsRunAsNode()) { + if (IsEnvSet(kRunAsNode)) { base::i18n::InitializeICU(); base::AtExitManager atexit_manager; return atom::NodeMain(argc, const_cast(argv)); @@ -140,7 +134,7 @@ int main(int argc, const char* argv[]) { #else // defined(OS_LINUX) int main(int argc, const char* argv[]) { - if (IsRunAsNode()) { + if (IsEnvSet(kRunAsNode)) { return AtomInitializeICUandStartNode(argc, const_cast(argv)); } From 4d8994df921087653c2e134e39a1da16a957bf39 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 31 May 2016 10:26:19 +0900 Subject: [PATCH 491/510] spec: child_process.fork shouble be able to pipe stdio --- spec/fixtures/module/process-stdout.js | 1 + spec/node-spec.js | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 spec/fixtures/module/process-stdout.js diff --git a/spec/fixtures/module/process-stdout.js b/spec/fixtures/module/process-stdout.js new file mode 100644 index 000000000000..953750a247f9 --- /dev/null +++ b/spec/fixtures/module/process-stdout.js @@ -0,0 +1 @@ +process.stdout.write('pipes stdio') diff --git a/spec/node-spec.js b/spec/node-spec.js index 71fdbac98664..93a247ef4ff6 100644 --- a/spec/node-spec.js +++ b/spec/node-spec.js @@ -76,6 +76,19 @@ describe('node feature', function () { }) child.send('message') }) + + it('pipes stdio', function (done) { + let child = child_process.fork(path.join(fixtures, 'module', 'process-stdout.js'), {silent: true}) + let data = '' + child.stdout.on('data', (chunk) => { + data += String(chunk) + }) + child.on('exit', (code) => { + assert.equal(code, 0) + assert.equal(data, 'pipes stdio') + done() + }) + }) }) }) From aea2135016a45c90b28d5e1c89fdd46787d328de Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Tue, 31 May 2016 17:47:45 +0900 Subject: [PATCH 492/510] Keep copies of window icons --- atom/browser/native_window_views.cc | 10 +++++++--- atom/browser/native_window_views.h | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 21bff6388a66..e699892d4ac5 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -786,12 +786,16 @@ gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() { } #if defined(OS_WIN) -void NativeWindowViews::SetIcon(HICON small_icon, HICON app_icon) { +void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) { + // We are responsible for storing the images. + window_icon_ = base::win::ScopedHICON(CopyIcon(window_icon)); + app_icon_ = base::win::ScopedHICON(CopyIcon(app_icon)); + HWND hwnd = GetAcceleratedWidget(); SendMessage(hwnd, WM_SETICON, ICON_SMALL, - reinterpret_cast(small_icon)); + reinterpret_cast(window_icon_.get())); SendMessage(hwnd, WM_SETICON, ICON_BIG, - reinterpret_cast(app_icon)); + reinterpret_cast(app_icon_.get())); } #elif defined(USE_X11) void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) { diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index 85c7ddbeba7a..909c5b6fd4ba 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -17,6 +17,7 @@ #if defined(OS_WIN) #include "atom/browser/ui/win/message_handler_delegate.h" #include "atom/browser/ui/win/taskbar_host.h" +#include "base/win/scoped_gdi_object.h" #endif namespace views { @@ -205,6 +206,10 @@ class NativeWindowViews : public NativeWindow, // If true we have enabled a11y bool enabled_a11y_support_; + + // The icons of window and taskbar. + base::win::ScopedHICON window_icon_; + base::win::ScopedHICON app_icon_; #endif // Handles unhandled keyboard messages coming back from the renderer process. From fc6628d159395731832cf58c5adb61108923bcea Mon Sep 17 00:00:00 2001 From: Vasu Mahesh Date: Tue, 31 May 2016 22:29:07 +0530 Subject: [PATCH 493/510] Add: custom pageSize for printToPDF --- docs/api/web-contents.md | 2 +- lib/browser/api/web-contents.js | 28 ++++++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index d0716305ab9f..89d7e1245d77 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -655,7 +655,7 @@ size. * `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`. + `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` & `width` in Microns. * `printBackground` Boolean - Whether to print CSS backgrounds. * `printSelectionOnly` Boolean - Whether to print selection only. * `landscape` Boolean - `true` for landscape, `false` for portrait. diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 0f79a185ffc9..00057e16e8b8 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -197,11 +197,31 @@ let wrapWebContents = function (webContents) { if (options.printBackground) { printingSetting.shouldPrintBackgrounds = options.printBackground } - if (options.pageSize && PDFPageSize[options.pageSize]) { - printingSetting.mediaSize = PDFPageSize[options.pageSize] - } else { - printingSetting.mediaSize = PDFPageSize['A4'] + + if (options.pageSize) { + let height = 0 + let width = 0 + if (typeof options.pageSize === 'object') { + // Dimensions in Microns + // 1 meter = 10^6 microns + height = options.pageSize.height ? options.pageSize.height : 0 + width = options.pageSize.width ? options.pageSize.width : 0 + } + + if (height > 0 && width > 0) { + printingSetting.mediaSize = { + height_microns: height, + name: 'CUSTOM', + width_microns: width, + custom_display_name: 'Custom' + } + } else if (PDFPageSize[options.pageSize]) { + printingSetting.mediaSize = PDFPageSize[options.pageSize] + } else { + printingSetting.mediaSize = PDFPageSize['A4'] + } } + return this._printToPDF(printingSetting, callback) } } From 606fc1a5b7b66cd23b489b8ecd7097ed3d0b46a4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 31 May 2016 16:48:03 -0700 Subject: [PATCH 494/510] Add plist path variables --- .../mac-app-store-submission-guide.md | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/tutorial/mac-app-store-submission-guide.md b/docs/tutorial/mac-app-store-submission-guide.md index c6ae061bd762..d240cc13371b 100644 --- a/docs/tutorial/mac-app-store-submission-guide.md +++ b/docs/tutorial/mac-app-store-submission-guide.md @@ -94,21 +94,24 @@ RESULT_PATH="~/Desktop/$APP.pkg" # The name of certificates you requested. APP_KEY="3rd Party Mac Developer Application: Company Name (APPIDENTITY)" INSTALLER_KEY="3rd Party Mac Developer Installer: Company Name (APPIDENTITY)" +# The path of your plist files. +CHILD_PLIST="/path/to/child.plist" +PARENT_PLIST="/path/to/parent.plist" FRAMEWORKS_PATH="$APP_PATH/Contents/Frameworks" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/Electron Framework.framework" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper.app/" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP Helper EH" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper EH.app/" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP" -codesign -s "$APP_KEY" -f --entitlements child.plist "$FRAMEWORKS_PATH/$APP Helper NP.app/" -codesign -s "$APP_KEY" -f --entitlements child.plist "$APP_PATH/Contents/MacOS/$APP" -codesign -s "$APP_KEY" -f --entitlements parent.plist "$APP_PATH" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Electron Framework" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libffmpeg.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework/Versions/A/Libraries/libnode.dylib" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/Electron Framework.framework" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/Contents/MacOS/$APP Helper" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper.app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/Contents/MacOS/$APP Helper EH" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper EH.app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/Contents/MacOS/$APP Helper NP" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$FRAMEWORKS_PATH/$APP Helper NP.app/" +codesign -s "$APP_KEY" -f --entitlements "$CHILD_PLIST" "$APP_PATH/Contents/MacOS/$APP" +codesign -s "$APP_KEY" -f --entitlements "$PARENT_PLIST" "$APP_PATH" productbuild --component "$APP_PATH" /Applications --sign "$INSTALLER_KEY" "$RESULT_PATH" ``` From 2aa1aedd92c58106ecbeddb31c4aeaabdfe9044c Mon Sep 17 00:00:00 2001 From: Garen Torikian Date: Tue, 31 May 2016 17:51:09 -0700 Subject: [PATCH 495/510] Fix typo --- docs/tutorial/electron-versioning.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/electron-versioning.md b/docs/tutorial/electron-versioning.md index 10e9679b0bd9..bf442041c2cc 100644 --- a/docs/tutorial/electron-versioning.md +++ b/docs/tutorial/electron-versioning.md @@ -4,7 +4,7 @@ If you are a seasoned Node developer, you are surely aware of `semver` - and might be used to giving your dependency management systems only rough guidelines rather than fixed version numbers. Due to the hard dependency on Node and Chromium, Electron is in a slightly more difficult position and does not follow -semver. You should therefor always reference a specific version of Electron. +semver. You should therefore always reference a specific version of Electron. Version numbers are bumped using the following rules: From d10552413578e24c4d4087268a3712767235761f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 10:42:24 +0900 Subject: [PATCH 496/510] Cleanup the JavaScript code of session --- lib/browser/api/session.js | 19 ++++++++++++------- lib/browser/api/web-contents.js | 7 ------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/lib/browser/api/session.js b/lib/browser/api/session.js index 9c42f3645603..49b169bd3ac5 100644 --- a/lib/browser/api/session.js +++ b/lib/browser/api/session.js @@ -1,14 +1,12 @@ +const {EventEmitter} = require('events') const bindings = process.atomBinding('session') + const PERSIST_PREFIX = 'persist:' // Returns the Session from |partition| string. -exports.fromPartition = function (partition) { - if (partition == null) { - partition = '' - } - if (partition === '') { - return exports.defaultSession - } +exports.fromPartition = function (partition = '') { + if (partition === '') return exports.defaultSession + if (partition.startsWith(PERSIST_PREFIX)) { return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false) } else { @@ -23,3 +21,10 @@ Object.defineProperty(exports, 'defaultSession', { return bindings.fromPartition('', false) } }) + +const wrapSession = function (session) { + // Session is an EventEmitter. + Object.setPrototypeOf(session, EventEmitter.prototype) +} + +bindings._setWrapSession(wrapSession) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 0f79a185ffc9..fbb91879f80c 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -5,7 +5,6 @@ const {ipcMain, Menu, NavigationController} = require('electron') const binding = process.atomBinding('web_contents') const debuggerBinding = process.atomBinding('debugger') -const sessionBinding = process.atomBinding('session') let nextId = 0 @@ -212,14 +211,8 @@ let wrapDebugger = function (webContentsDebugger) { Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype) } -var wrapSession = function (session) { - // session is an EventEmitter. - Object.setPrototypeOf(session, EventEmitter.prototype) -} - binding._setWrapWebContents(wrapWebContents) debuggerBinding._setWrapDebugger(wrapDebugger) -sessionBinding._setWrapSession(wrapSession) module.exports = { create (options = {}) { From 8dfbbcefc8213f6f7eca9dc2b023e1d47c6b50de Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 10:53:06 +0900 Subject: [PATCH 497/510] Throw error when session module is used before app is ready --- lib/browser/api/session.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/browser/api/session.js b/lib/browser/api/session.js index 49b169bd3ac5..dc1c529878fb 100644 --- a/lib/browser/api/session.js +++ b/lib/browser/api/session.js @@ -1,16 +1,26 @@ const {EventEmitter} = require('events') +const electron = require('electron') const bindings = process.atomBinding('session') const PERSIST_PREFIX = 'persist:' +// Wrapper of binding.fromPartition that checks for ready event. +const fromPartition = function (partition, persist) { + if (!electron.app.isReady()) { + throw new Error('session module can only be used when app is ready') + } + + return bindings.fromPartition(partition, persist) +} + // Returns the Session from |partition| string. exports.fromPartition = function (partition = '') { if (partition === '') return exports.defaultSession if (partition.startsWith(PERSIST_PREFIX)) { - return bindings.fromPartition(partition.substr(PERSIST_PREFIX.length), false) + return fromPartition(partition.substr(PERSIST_PREFIX.length), false) } else { - return bindings.fromPartition(partition, true) + return fromPartition(partition, true) } } @@ -18,7 +28,7 @@ exports.fromPartition = function (partition = '') { Object.defineProperty(exports, 'defaultSession', { enumerable: true, get: function () { - return bindings.fromPartition('', false) + return fromPartition('', false) } }) From 89adc122c3bfcb0bbd9404bfc5e85de7c952a9d1 Mon Sep 17 00:00:00 2001 From: Colin Eberhardt Date: Wed, 1 Jun 2016 06:36:45 +0100 Subject: [PATCH 498/510] Minor typo fixes --- docs/tutorial/security.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/security.md b/docs/tutorial/security.md index 947948720371..2ac25d135ebc 100644 --- a/docs/tutorial/security.md +++ b/docs/tutorial/security.md @@ -9,7 +9,7 @@ discovered security threats. When working with Electron, it is important to understand that Electron is not a web browser. It allows you to build feature-rich desktop applications with familiar web technologies, but your code wields much greater power. JavaScript -can access to the filesystem, the user shell, and more. This allows you to build +can access the filesystem, user shell, and more. This allows you to build high quality native applications, but the inherent security risks scale with the additional powers granted to your code. From 523e8c2e1c815d58a7facf65a34f072f593ccfd5 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 14:01:59 +0900 Subject: [PATCH 499/510] Update libchromiumcontent and brightray for #5781 --- script/lib/config.py | 2 +- vendor/brightray | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/script/lib/config.py b/script/lib/config.py index 006faf1b920a..43423e514368 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 = 'eda589282bd7729f36960d2e669d4b81375b897c' +LIBCHROMIUMCONTENT_COMMIT = '8f2a0aa0a9dd107e4d574cc9d552781c55c86bab' PLATFORM = { 'cygwin': 'win32', diff --git a/vendor/brightray b/vendor/brightray index e9b2a4ffa292..9ccab3c9a87c 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit e9b2a4ffa29209fbd12a0b1613e8633d42f0b103 +Subproject commit 9ccab3c9a87cc57b4a37c4a03e17b589ac81d6ae From 5bb8da60737802d9c4e09b2c813ec93539fb92be Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 14:57:35 +0900 Subject: [PATCH 500/510] Explicitly initialize session before webContents --- lib/browser/api/app.js | 5 +++-- lib/browser/api/web-contents.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/browser/api/app.js b/lib/browser/api/app.js index f8a531626bf7..09835a792e0e 100644 --- a/lib/browser/api/app.js +++ b/lib/browser/api/app.js @@ -1,6 +1,7 @@ 'use strict' -const {deprecate, Menu, session} = require('electron') +const electron = require('electron') +const {deprecate, Menu} = electron const {EventEmitter} = require('events') const bindings = process.atomBinding('app') @@ -49,7 +50,7 @@ app.allowNTLMCredentialsForAllDomains = function (allow) { if (!this.isReady()) { this.commandLine.appendSwitch('auth-server-whitelist', domains) } else { - session.defaultSession.allowNTLMCredentialsForDomains(domains) + electron.session.defaultSession.allowNTLMCredentialsForDomains(domains) } } diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index cb8cf41e3aa6..059f204e1ee7 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -1,7 +1,11 @@ 'use strict' const {EventEmitter} = require('events') -const {ipcMain, Menu, NavigationController} = require('electron') +const {ipcMain, session, Menu, NavigationController} = require('electron') + +// session is not used here, the purpose is to make sure session is initalized +// before the webContents module. +session const binding = process.atomBinding('web_contents') const debuggerBinding = process.atomBinding('debugger') From eb882855bcd5dc925695ceb54669da51696f9bcd Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:08:51 +0900 Subject: [PATCH 501/510] Cleanup the CoffeeScript converted code --- lib/browser/api/web-contents.js | 46 ++++++++++++++------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 059f204e1ee7..d7bcdb455b33 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -11,12 +11,11 @@ const binding = process.atomBinding('web_contents') const debuggerBinding = process.atomBinding('debugger') let nextId = 0 - -let getNextId = function () { +const getNextId = function () { return ++nextId } -let PDFPageSize = { +const PDFPageSize = { A5: { custom_display_name: 'A5', height_microns: 210000, @@ -64,9 +63,9 @@ const webFrameMethods = [ 'setZoomLevelLimits' ] -let wrapWebContents = function (webContents) { +// Add JavaScript wrappers for WebContents class. +const wrapWebContents = function (webContents) { // webContents is an EventEmitter. - var controller, method, name, ref1 Object.setPrototypeOf(webContents, EventEmitter.prototype) // Every remote callback from renderer process would add a listenter to the @@ -85,21 +84,18 @@ let wrapWebContents = function (webContents) { webContents.sendToAll = sendWrapper.bind(null, true) // The navigation controller. - controller = new NavigationController(webContents) - ref1 = NavigationController.prototype - for (name in ref1) { - method = ref1[name] + const controller = new NavigationController(webContents) + for (const name in NavigationController.prototype) { + const method = NavigationController.prototype[name] if (method instanceof Function) { - (function (name, method) { - webContents[name] = function () { - return method.apply(controller, arguments) - } - })(name, method) + webContents[name] = function () { + return method.apply(controller, arguments) + } } } // Mapping webFrame methods. - for (let method of webFrameMethods) { + for (const method of webFrameMethods) { webContents[method] = function (...args) { this.send('ELECTRON_INTERNAL_RENDERER_WEB_FRAME_METHOD', method, args) } @@ -115,7 +111,7 @@ let wrapWebContents = function (webContents) { // Make sure webContents.executeJavaScript would run the code only when the // webContents has been loaded. webContents.executeJavaScript = function (code, hasUserGesture, callback) { - let requestId = getNextId() + const requestId = getNextId() if (typeof hasUserGesture === 'function') { callback = hasUserGesture hasUserGesture = false @@ -131,18 +127,16 @@ let wrapWebContents = function (webContents) { // Dispatch IPC messages to the ipc module. webContents.on('ipc-message', function (event, [channel, ...args]) { - ipcMain.emit.apply(ipcMain, [channel, event].concat(args)) + ipcMain.emit(channel, event, ...args) }) webContents.on('ipc-message-sync', function (event, [channel, ...args]) { Object.defineProperty(event, 'returnValue', { set: function (value) { return event.sendReply(JSON.stringify(value)) }, - get: function () { - return undefined - } + get: function () {} }) - return ipcMain.emit.apply(ipcMain, [channel, event].concat(args)) + ipcMain.emit(channel, event, ...args) }) // Handle context menu action request from pepper plugin. @@ -164,8 +158,7 @@ let wrapWebContents = function (webContents) { }) webContents.printToPDF = function (options, callback) { - var printingSetting - printingSetting = { + const printingSetting = { pageRage: [], mediaSize: {}, landscape: false, @@ -229,13 +222,14 @@ let wrapWebContents = function (webContents) { } } -// Wrapper for native class. -let wrapDebugger = function (webContentsDebugger) { +binding._setWrapWebContents(wrapWebContents) + +// Add JavaScript wrappers for Debugger class. +const wrapDebugger = function (webContentsDebugger) { // debugger is an EventEmitter. Object.setPrototypeOf(webContentsDebugger, EventEmitter.prototype) } -binding._setWrapWebContents(wrapWebContents) debuggerBinding._setWrapDebugger(wrapDebugger) module.exports = { From a70749e80ae8fbc17f96c6007f3d440af5e38610 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 30 May 2016 18:08:09 +0530 Subject: [PATCH 502/510] browser: implement bluetooth chooser interface --- atom/browser/api/atom_api_web_contents.cc | 9 ++ atom/browser/api/atom_api_web_contents.h | 3 + atom/browser/bluetooth_chooser.cc | 107 ++++++++++++++++++++++ atom/browser/bluetooth_chooser.h | 45 +++++++++ filenames.gypi | 2 + 5 files changed, 166 insertions(+) create mode 100644 atom/browser/bluetooth_chooser.cc create mode 100644 atom/browser/bluetooth_chooser.h diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 736fb7ca0fb1..ab68fafe716d 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -14,6 +14,7 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_security_state_model_client.h" +#include "atom/browser/bluetooth_chooser.h" #include "atom/browser/native_window.h" #include "atom/browser/net/atom_network_delegate.h" #include "atom/browser/web_contents_permission_helper.h" @@ -504,6 +505,14 @@ void WebContents::RequestToLockMouse( permission_helper->RequestPointerLockPermission(user_gesture); } +std::unique_ptr WebContents::RunBluetoothChooser( + content::RenderFrameHost* frame, + const content::BluetoothChooser::EventHandler& event_handler) { + std::unique_ptr bluetooth_chooser( + new BluetoothChooser(this, event_handler)); + return std::move(bluetooth_chooser); +} + void WebContents::BeforeUnloadFired(const base::TimeTicks& proceed_time) { // Do nothing, we override this method just to avoid compilation error since // there are two virtual functions named BeforeUnloadFired. diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index e03ab653a8ce..85c43f1486aa 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -211,6 +211,9 @@ class WebContents : public mate::TrackableObject, content::WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) override; + std::unique_ptr RunBluetoothChooser( + content::RenderFrameHost* frame, + const content::BluetoothChooser::EventHandler& handler) override; // content::WebContentsObserver: void BeforeUnloadFired(const base::TimeTicks& proceed_time) override; diff --git a/atom/browser/bluetooth_chooser.cc b/atom/browser/bluetooth_chooser.cc new file mode 100644 index 000000000000..37c30a36081a --- /dev/null +++ b/atom/browser/bluetooth_chooser.cc @@ -0,0 +1,107 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/bluetooth_chooser.h" +#include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/string16_converter.h" +#include "native_mate/dictionary.h" + +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8( + v8::Isolate* isolate, const atom::BluetoothChooser::DeviceInfo& val) { + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + dict.Set("deviceName", val.device_name); + dict.Set("deviceId", val.device_id); + return mate::ConvertToV8(isolate, dict); + } +}; + +} // namespace mate + +namespace atom { + +namespace { + +const int kMaxScanRetries = 5; + +void OnDeviceChosen( + const content::BluetoothChooser::EventHandler& handler, + const std::string& device_id) { + if (device_id.empty()) { + handler.Run(content::BluetoothChooser::Event::CANCELLED, device_id); + } else { + handler.Run(content::BluetoothChooser::Event::SELECTED, device_id); + } +} + +} // namespace + +BluetoothChooser::BluetoothChooser( + api::WebContents* contents, + const EventHandler& event_handler) + : api_web_contents_(contents), + event_handler_(event_handler), + num_retries_(0) { +} + +BluetoothChooser::~BluetoothChooser() { +} + +void BluetoothChooser::SetAdapterPresence(AdapterPresence presence) { + switch (presence) { + case AdapterPresence::ABSENT: + case AdapterPresence::POWERED_OFF: + event_handler_.Run(Event::CANCELLED, ""); + break; + case AdapterPresence::POWERED_ON: + break; + } +} + +void BluetoothChooser::ShowDiscoveryState(DiscoveryState state) { + switch (state) { + case DiscoveryState::FAILED_TO_START: + event_handler_.Run(Event::CANCELLED, ""); + break; + case DiscoveryState::IDLE: + if (device_list_.empty()) { + auto event = ++num_retries_ > kMaxScanRetries ? Event::CANCELLED + : Event::RESCAN; + event_handler_.Run(event, ""); + } else { + bool prevent_default = + api_web_contents_->Emit("select-bluetooth-device", + device_list_, + base::Bind(&OnDeviceChosen, + event_handler_)); + if (!prevent_default) { + auto device_id = device_list_[0].device_id; + event_handler_.Run(Event::SELECTED, device_id); + } + } + break; + case DiscoveryState::DISCOVERING: + break; + } +} + +void BluetoothChooser::AddDevice(const std::string& device_id, + const base::string16& device_name) { + DeviceInfo info = {device_id, device_name}; + device_list_.push_back(info); +} + +void BluetoothChooser::RemoveDevice(const std::string& device_id) { + for (auto it = device_list_.begin(); it != device_list_.end(); ++it) { + if (it->device_id == device_id) { + device_list_.erase(it); + return; + } + } +} + +} // namespace atom diff --git a/atom/browser/bluetooth_chooser.h b/atom/browser/bluetooth_chooser.h new file mode 100644 index 000000000000..69617191ba46 --- /dev/null +++ b/atom/browser/bluetooth_chooser.h @@ -0,0 +1,45 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ +#define ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ + +#include +#include + +#include "atom/browser/api/atom_api_web_contents.h" +#include "content/public/browser/bluetooth_chooser.h" + +namespace atom { + +class BluetoothChooser : public content::BluetoothChooser { + public: + struct DeviceInfo { + std::string device_id; + base::string16 device_name; + }; + + explicit BluetoothChooser(api::WebContents* contents, + const EventHandler& handler); + ~BluetoothChooser() override; + + // content::BluetoothChooser: + void SetAdapterPresence(AdapterPresence presence) override; + void ShowDiscoveryState(DiscoveryState state) override; + void AddDevice(const std::string& device_id, + const base::string16& device_name) override; + void RemoveDevice(const std::string& device_id) override; + + private: + std::vector device_list_; + api::WebContents* api_web_contents_; + EventHandler event_handler_; + int num_retries_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothChooser); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ diff --git a/filenames.gypi b/filenames.gypi index ae71164a8ab9..66874efc07d6 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -167,6 +167,8 @@ 'atom/browser/atom_security_state_model_client.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', + 'atom/browser/bluetooth_chooser.cc', + 'atom/browser/bluetooth_chooser.h', 'atom/browser/bridge_task_runner.cc', 'atom/browser/bridge_task_runner.h', 'atom/browser/browser.cc', From 51daf8e194d6d5660c29736f6dd1dc07d2ad24ee Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Tue, 31 May 2016 13:37:45 +0530 Subject: [PATCH 503/510] add docs --- docs/api/web-contents.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 89d7e1245d77..941879b7f746 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -373,6 +373,22 @@ The `editFlags` is an object with the following properties: Emitted when there is a new context menu that needs to be handled. +### Event: 'select-bluetooth-device' + +Returns: + +* `event` Event +* `devices` [Objects] + * `deviceName` String + * `deviceId` String +* `callback` Function + * `deviceId` String + +Emitted when bluetooth device needs to be selected on call to +`navigator.bluetooth.requestDevice`. If `event.preventDefault` is not called, +first available device will be selected. `callback` should be called with `deviceId` +to be selected. + ## Instance Methods The `webContents` object has the following instance methods: From db4dc4757aa85da8c6b46b6c4ea81eff8f9ee895 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 1 Jun 2016 11:17:21 +0530 Subject: [PATCH 504/510] move bluetooth_chooser to atom/browser/lib --- atom/browser/{ => lib}/bluetooth_chooser.cc | 0 atom/browser/{ => lib}/bluetooth_chooser.h | 0 filenames.gypi | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename atom/browser/{ => lib}/bluetooth_chooser.cc (100%) rename atom/browser/{ => lib}/bluetooth_chooser.h (100%) diff --git a/atom/browser/bluetooth_chooser.cc b/atom/browser/lib/bluetooth_chooser.cc similarity index 100% rename from atom/browser/bluetooth_chooser.cc rename to atom/browser/lib/bluetooth_chooser.cc diff --git a/atom/browser/bluetooth_chooser.h b/atom/browser/lib/bluetooth_chooser.h similarity index 100% rename from atom/browser/bluetooth_chooser.h rename to atom/browser/lib/bluetooth_chooser.h diff --git a/filenames.gypi b/filenames.gypi index 66874efc07d6..f66b98134c65 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -167,8 +167,6 @@ 'atom/browser/atom_security_state_model_client.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', - 'atom/browser/bluetooth_chooser.cc', - 'atom/browser/bluetooth_chooser.h', 'atom/browser/bridge_task_runner.cc', 'atom/browser/bridge_task_runner.h', 'atom/browser/browser.cc', @@ -183,6 +181,8 @@ 'atom/browser/common_web_contents_delegate.h', 'atom/browser/javascript_environment.cc', 'atom/browser/javascript_environment.h', + 'atom/browser/lib/bluetooth_chooser.cc', + 'atom/browser/lib/bluetooth_chooser.h', 'atom/browser/login_handler.cc', 'atom/browser/login_handler.h', 'atom/browser/mac/atom_application.h', From de4bff003f82344efa83f0c183c62e09b824c766 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 1 Jun 2016 11:24:41 +0530 Subject: [PATCH 505/510] fix header paths and comments --- atom/browser/api/atom_api_web_contents.cc | 2 +- atom/browser/lib/bluetooth_chooser.cc | 2 +- atom/browser/lib/bluetooth_chooser.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index ab68fafe716d..9d93d980be4a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -14,7 +14,7 @@ #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_security_state_model_client.h" -#include "atom/browser/bluetooth_chooser.h" +#include "atom/browser/lib/bluetooth_chooser.h" #include "atom/browser/native_window.h" #include "atom/browser/net/atom_network_delegate.h" #include "atom/browser/web_contents_permission_helper.h" diff --git a/atom/browser/lib/bluetooth_chooser.cc b/atom/browser/lib/bluetooth_chooser.cc index 37c30a36081a..2ed21bd333fd 100644 --- a/atom/browser/lib/bluetooth_chooser.cc +++ b/atom/browser/lib/bluetooth_chooser.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "atom/browser/bluetooth_chooser.h" +#include "atom/browser/lib/bluetooth_chooser.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "native_mate/dictionary.h" diff --git a/atom/browser/lib/bluetooth_chooser.h b/atom/browser/lib/bluetooth_chooser.h index 69617191ba46..615dfcb8c663 100644 --- a/atom/browser/lib/bluetooth_chooser.h +++ b/atom/browser/lib/bluetooth_chooser.h @@ -2,8 +2,8 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#ifndef ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ -#define ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ +#ifndef ATOM_BROWSER_LIB_BLUETOOTH_CHOOSER_H_ +#define ATOM_BROWSER_LIB_BLUETOOTH_CHOOSER_H_ #include #include @@ -42,4 +42,4 @@ class BluetoothChooser : public content::BluetoothChooser { } // namespace atom -#endif // ATOM_BROWSER_BLUETOOTH_CHOOSER_H_ +#endif // ATOM_BROWSER_LIB_BLUETOOTH_CHOOSER_H_ From 743483846344515aa971be3d786d14e3ba125c82 Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Wed, 1 Jun 2016 11:39:14 +0530 Subject: [PATCH 506/510] fix docs --- docs/api/web-contents.md | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 941879b7f746..2d489c6726a1 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -385,9 +385,29 @@ Returns: * `deviceId` String Emitted when bluetooth device needs to be selected on call to -`navigator.bluetooth.requestDevice`. If `event.preventDefault` is not called, -first available device will be selected. `callback` should be called with `deviceId` -to be selected. +`navigator.bluetooth.requestDevice`. To use `navigator.bluetooth` api +`webBluetooth` should be enabled. If `event.preventDefault` is not called, +first available device will be selected. `callback` should be called with +`deviceId` to be selected, passing empty string to `callback` will +cancel the request. + +```javacript +app.commandLine.appendSwitch('enable-web-bluetooth') + +app.on('ready', () => { + webContents.on('select-bluetooth-device', (event, deviceList, callback) => { + event.preventDefault() + let result = deviceList.find((device) => { + return device.deviceName === 'test' + }) + if (!result) { + callback('') + } else { + callback(result.deviceId) + } + }) +}) +``` ## Instance Methods From 0864d3b1ee7370ece474532ffbeda646c2e5ed5e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:24:53 +0900 Subject: [PATCH 507/510] Cleanup the printToPDF code --- lib/browser/api/web-contents.js | 81 +++++++++++++++++---------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index d7bcdb455b33..ed7bfe0b8bdf 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -15,7 +15,8 @@ const getNextId = function () { return ++nextId } -const PDFPageSize = { +// Stock page sizes +const PDFPageSizes = { A5: { custom_display_name: 'A5', height_microns: 210000, @@ -55,6 +56,31 @@ const PDFPageSize = { } } +// Default printing setting +const defaultPrintingSetting = { + pageRage: [], + mediaSize: {}, + landscape: false, + color: 2, + headerFooterEnabled: false, + marginsType: 0, + isFirstRequest: false, + requestID: getNextId(), + previewModifiable: true, + printToPDF: true, + printWithCloudPrint: false, + printWithPrivet: false, + printWithExtension: false, + deviceName: 'Save as PDF', + generateDraftData: true, + fitToPageEnabled: false, + duplex: 0, + copies: 1, + collate: true, + shouldPrintBackgrounds: false, + shouldPrintSelectionOnly: false +} + // Following methods are mapped to webFrame. const webFrameMethods = [ 'insertText', @@ -158,29 +184,7 @@ const wrapWebContents = function (webContents) { }) webContents.printToPDF = function (options, callback) { - const printingSetting = { - pageRage: [], - mediaSize: {}, - landscape: false, - color: 2, - headerFooterEnabled: false, - marginsType: 0, - isFirstRequest: false, - requestID: getNextId(), - previewModifiable: true, - printToPDF: true, - printWithCloudPrint: false, - printWithPrivet: false, - printWithExtension: false, - deviceName: 'Save as PDF', - generateDraftData: true, - fitToPageEnabled: false, - duplex: 0, - copies: 1, - collate: true, - shouldPrintBackgrounds: false, - shouldPrintSelectionOnly: false - } + const printingSetting = Object.assign({}, defaultPrintingSetting) if (options.landscape) { printingSetting.landscape = options.landscape } @@ -195,30 +199,29 @@ const wrapWebContents = function (webContents) { } if (options.pageSize) { - let height = 0 - let width = 0 - if (typeof options.pageSize === 'object') { + const pageSize = options.pageSize + if (typeof pageSize === 'object') { + if (!pageSize.height || !pageSize.width) { + return callback(new Error('Must define height and width for pageSize')) + } // Dimensions in Microns // 1 meter = 10^6 microns - height = options.pageSize.height ? options.pageSize.height : 0 - width = options.pageSize.width ? options.pageSize.width : 0 - } - - if (height > 0 && width > 0) { printingSetting.mediaSize = { - height_microns: height, name: 'CUSTOM', - width_microns: width, - custom_display_name: 'Custom' + custom_display_name: 'Custom', + height_microns: pageSize.height, + width_microns: pageSize.width } - } else if (PDFPageSize[options.pageSize]) { - printingSetting.mediaSize = PDFPageSize[options.pageSize] + } else if (PDFPageSizes[pageSize]) { + printingSetting.mediaSize = PDFPageSizes[pageSize] } else { - printingSetting.mediaSize = PDFPageSize['A4'] + return callback(new Error(`Does not support pageSize with ${pageSize}`)) } + } else { + printingSetting.mediaSize = PDFPageSizes['A4'] } - return this._printToPDF(printingSetting, callback) + this._printToPDF(printingSetting, callback) } } From 01b10b3b39d3e34f6aedbeaa431d18afdd58d060 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 15:27:17 +0900 Subject: [PATCH 508/510] Slightly improve docs of webContents.printToPDF --- docs/api/web-contents.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 89d7e1245d77..ca9cf43c468f 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -655,7 +655,8 @@ size. * `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`, `Tabloid` or an Object containing `height` & `width` in Microns. + `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` + and `width` in microns. * `printBackground` Boolean - Whether to print CSS backgrounds. * `printSelectionOnly` Boolean - Whether to print selection only. * `landscape` Boolean - `true` for landscape, `false` for portrait. @@ -678,6 +679,8 @@ By default, an empty `options` will be regarded as: } ``` +An example of `webContents.printToPDF`: + ```javascript const {BrowserWindow} = require('electron'); const fs = require('fs'); From 97dd71d79e67a4a5769f65cfa44def05ba16127d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 1 Jun 2016 16:15:53 +0900 Subject: [PATCH 509/510] Bump v1.2.1 --- atom/browser/resources/mac/Info.plist | 4 ++-- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- electron.gyp | 2 +- package.json | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index f1c6b4137061..28eddfa61235 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,9 +17,9 @@ CFBundleIconFile electron.icns CFBundleVersion - 1.2.0 + 1.2.1 CFBundleShortVersionString - 1.2.0 + 1.2.1 LSApplicationCategoryType public.app-category.developer-tools LSMinimumSystemVersion diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 701e6fe29480..7e386d319d9d 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION 1,2,0,0 + FILEVERSION 1,2,1,0 + PRODUCTVERSION 1,2,1,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "1.2.0" + VALUE "FileVersion", "1.2.1" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "1.2.0" + VALUE "ProductVersion", "1.2.1" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index cf2ef14d8ccd..455bfacbfc11 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 1 #define ATOM_MINOR_VERSION 2 -#define ATOM_PATCH_VERSION 0 +#define ATOM_PATCH_VERSION 1 #define ATOM_VERSION_IS_RELEASE 1 diff --git a/electron.gyp b/electron.gyp index c11444121531..055cb0c209ac 100644 --- a/electron.gyp +++ b/electron.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '1.2.0', + 'version%': '1.2.1', }, 'includes': [ 'filenames.gypi', diff --git a/package.json b/package.json index d96ed1cd42ad..6f873786e3f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "electron", - "version": "1.2.0", + "version": "1.2.1", "devDependencies": { "asar": "^0.11.0", "request": "*", From 789a878f07e7a329524859e9cd113aa65086f01b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 1 Jun 2016 13:16:53 -0700 Subject: [PATCH 510/510] Rename atom-shell-frameworks repo name and org --- script/update-external-binaries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/update-external-binaries.py b/script/update-external-binaries.py index c70860707e86..470f735fdb42 100755 --- a/script/update-external-binaries.py +++ b/script/update-external-binaries.py @@ -10,7 +10,7 @@ from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download VERSION = 'v1.0.0' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) -FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \ +FRAMEWORKS_URL = 'http://github.com/electron/electron-frameworks/releases' \ '/download/' + VERSION