ElectronでWebviewの簡易ブラウザをつくってみたメモ

Electronの基本的な挙動が知りたかったので、HTML/CSS/JavaScriptを使ってElectronで簡易ブラウザをつくってみました。

# 1. 制作物

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/c582a146-48b4-ce03-0824-32abc20f5d35.png)

* URLを入力するとWebviewでロードしてくれる
    * ただしボタンを押さないとロードしてくれないしょぼい仕様!!
* Open Dev Toolを押すと、Webview内のDeveloper Toolが開く

## セットアップ

npm installの仕組みとかnpm initしてプロジェクトをつくるができる方であれば
セットアップは3分ぐらいで終わると思います。簡単!!

[参考 : ElectronとHTML/CSS/JavaScriptでデスクトップアプリを作ろう【入門編】](http://liginc.co.jp/web/html-css/177611)

## ファイル構成

Ligさんのサンプルコードを改造する形で3ファイルでつくりました。

```
- package.json
- index.js
- index.html
- style.css
```

```js:index.js
var app = require('app');
var BrowserWindow = require('browser-window');
require('crash-reporter').start();
var mainWindow = null;
app.on('window-all-closed', function () {
    //if (process.platform != 'darwin')
        app.quit();
});
app.on('ready', function () {
    // ブラウザ(Chromium)の起動, 初期画面のロード
    mainWindow = new BrowserWindow({
        width: 1000,
        height: 600
    });
    mainWindow.loadUrl('file://' + __dirname + '/index.html');
    mainWindow.on('closed', function () {
        mainWindow = null;
    });
});
```

```html:index.html
<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>DemoApp</title>
 <meta name="description" content="">
 <meta name="keywords" content=""/>
 <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0">
 <meta http-equiv="X-UA-Compatible" content="IE=edge">
 <link rel="stylesheet" href="style.css">
</head>
<body ng-app="app" ng-controller="RootCtrl as root">
 <div id="menu-bar">
   <input type="text" id="url" value="http://electron.atom.io/"></input>
   <button onclick="load();">Load</button>
   <button onclick="opendev();">Open Dev Tool</button>
 </div>
 <div id="webview_wrapper">
 </div>
</body>
<script>
"use strict";
function load(){
 // reset_webview_wrapper
 var webview_wrapper = document.getElementById("webview_wrapper");
 webview_wrapper.removeChild(webview_wrapper.lastChild);

 // get url
 var url = document.getElementById("url").value;

 // create_new_webview_instanse
 var newWebview = document.createElement("webview");
 newWebview.id = "foo";
 newWebview.setAttribute("src",url);
 // append new_webview
 webview_wrapper.appendChild(newWebview);
}
function opendev(){
 var webview = document.getElementById("foo");
 webview.openDevTools();
}
</script>
</html>
```

```css:style.css
html{
 width:100%;
 height:100%;
}
body{
 margin:0;padding:0;
 height:100%;
}

#menu-bar{
 width:100%;
 padding:5px;
 max-height:30px;
 background-color:#EFF0EE;
 color:#959595;
 display:block;
 white-space: nowrap;
}
#menu-bar input{
 width:80%;
 min-height:20px;
 font-size:14px;
}
#menu-bar button{
 font-size:14px;
 min-height:20px;
}
#webview_wrapper{
 height:100%;
}
```

# 2. メモ

## 1. アプリケーションのWindow表示

アプリケーションのWindow操作は非常に簡単です。
index.js内を1~2行変えるだけでやりたいことができます。

### URLを取得する

index.js内で、mainWindowの読み込み先をファイルではなくURLにすると、指定されたURLを読み込むアプリケーションになります。

```js:urlを取得する
mainWindow.loadUrl('http://electron.atom.io/'); 
```

### Windowサイズを変える

縦長アプリケーションをつくる際にはこんな感じ。

```js:サイズを変える
mainWindow = new BrowserWindow({width: 300,height: 1200});
```

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/4bf4c0e3-b81d-d1a0-4d16-c2318dbd9fb2.png)

### frameをなくす

frameをなくしたい場合はこんな感じで。
※ただ、frameをなくすとWindowの移動ができなくなります。

```js:アプリケーションのframeless
mainWindow = new BrowserWindow({width: 1000,height: 600,flame: false});
```

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/db68375a-5a09-411d-05b2-7943dfa8a2f3.png)

### 透過

```js:アプリケーションの透過
mainWindow = new BrowserWindow({width: 1000,height: 600,transparent: true});
```

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/9902f241-054f-be50-89aa-4acf77fcadbe.png)

### 他に利用できそうなもの

```js:中央寄せ
mainWindow = new BrowserWindow({width: 1000,height: 600,center: true});
```

```js:leftとtopからの場所指定
mainWindow = new BrowserWindow({width: 1000,height: 600, x: 0, y: 0});
//right,bottomは標準ではできなさそう
```

```js:アイコンクリック等で表示させるため起動時に表示しない
mainWindow = new BrowserWindow({width: 1000,height: 600, show: false});
```

```js:常に全てのWindowの上位に来るようにする
mainWindow = new BrowserWindow({width: 1000,height: 600,"always-on-top": true
});
```

```js:他のアプリケーション操作をさせないkioskモード
mainWindow = new BrowserWindow({width: 1000,height: 600,kiosk: true
});
```

## 2. MenuBar

僕はアプリケーションを利用するときにメニューよりもMenuBarをよく利用するので、MenuBarを作ろうと思いました。MenuBarはhtmlで作ります。

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/8697387b-3d46-d37a-8921-877cc36cd179.png)

Electronのsiteのdocumentaionでは[BrowserActionのsetMenu](http://electron.atom.io/docs/v0.33.0/api/browser-window/)というらしきものがあるので、メニューバーも簡単につくれるのかなと思ったら、エラーが起こりました。調べてみると、[githubでは「Linux Windows」と書かれているという。。。](https://github.com/atom/electron/blob/master/docs/api/browser-window.md)

**Electron Website**
![image](https://qiita-image-store.s3.amazonaws.com/0/32284/74952cb8-33d2-b854-13cf-ff15b251f9b5.png)

**Github Repo**
![image](https://qiita-image-store.s3.amazonaws.com/0/32284/47c48bcb-d620-d96e-efaa-ff556b6f4427.png)

ちなみにMenuBarはChromeに似せるために、サイズと色を調べて

```
height:30px; ※厳密には28~29あたり
padding-top:5px;
padding-bottom:5px;
background-color:#EFF0EE;
```

という感じで実装しました。

# 3.Webviewタグ

起動時にURLをロードする形ではなく、URLを入力したら毎回レンダリングする形にしたかったので、Webviewタグを利用しました。Webviewタグについては、[Real World Electron Development - Qiita](http://qiita.com/mizchi/items/2bf64eb51d2018fa8a6a)でも記載がありますがChromeのWebviewタグを利用しているため、ほぼ一緒です。Documentationの中身もほぼ一緒でした。

* Google ChromeのWebView
    * https://developer.chrome.com/apps/tags/webview
* ElectronのWebview
    * https://github.com/atom/electron/blob/master/docs/api/web-view-tag.md

Electronはアプリケーション上でショートカットコマンドを利用すればDevToolを利用できます。MacUserの場合は `Cmd + Opt + i`で開くことがですかね。

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/164a6340-83e5-6da7-5b72-96e9215c3735.png)

Webviewタグのobject内をinspectしたい場合は、別途DevToolを開くためのスクリプトを用意してあげる必要があります。

```js:index.html内
var webview = document.getElementById("Webviewタグを参照");
webview.openDevTools();
```

とすると、webviewのobjectを対象にしたDevToolを開くことができます。

![image](https://qiita-image-store.s3.amazonaws.com/0/32284/0b9b14d7-b161-6020-e81e-8f34aa0322ce.png)

webviewのオブジェクトで簡易なスクリプトを実行する際には

```js:index.html内
webview.executeJavaScript("document.write('JavaScriptをWebview内で実行することができます。')");
```

といった形でJavaScriptも実行することができます。

ちなみに簡易ブラウザをさらに拡張しようとして、Webview内のDomを取得してアプリケーション上で表示するというDevToolのInspectorを独自で実装してみようと思ったんですが、messageのやり取り等は経験がないことから別の機会にすることにしました。

# 4.外部ライブラリの導入

Electronはnodeを利用しているので、nodeのライブラリであれば何でも利用できます。commonJsでrequireする形ではない形で簡易的にjqueryやd3.jsを導入したい場合は、以下のことに気をつける必要があるみたいでした。

[ElectronでjQueryがundefinedになる - Qiita](http://qiita.com/pirosikick/items/72d11a8578c5c3327069)

# 5.参考資料

- [日本語訳 Electron(旧atom-shell) Quick start - Qiita](http://qiita.com/kitfactory/items/cc153cdfaf3d9fd70044)
    - ElectronのQuickStartの日本語訳です。
- [Real World Electron Development - Qiita](http://qiita.com/mizchi/items/2bf64eb51d2018fa8a6a)
    - Electronのメリットデメリット、現状の仕様の状態について詳しく解説されています。
- [Electron's first meetup - Wagon](https://www.wagonhq.com/blog/electron-meetup)
    - Electron First Meetupの様子です。動画とSpeackerDeckで説明があります。