web素人がChrome拡張機能を作ってみた

# 自己紹介
- C#でデスクトップアプリ開発2年目
- HTMLとかweb系は全く触ったことなし

# 何を作ったか
YouTubeの視聴時間を記録し、確認できるChrome拡張機能

# なぜ作ったか
1. 何か自分の手で作ってみたかった。せっかくなので公開できる系のやつ
1. YouTubeにどれだけ時間を吸われているか見えるようになれば、ダラダラする時間を減らせるんじゃないかと考えました。

# 作ったもの
## 概要
(作成時はこんな感じにメモ書いて考えてました。)
![メモ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497764/08856430-e620-227c-a9c6-c56ed4b594cf.png)


## 機能
1.　**URLの監視**
background.jsにてURLを一定周期で取得し、”youtube”を利用しいていれば視聴時間にカウントする。

2.　**視聴情報の保存＆取得**
Chrome拡張機能専用のストレージを利用して情報を保存する。
時間帯と視聴時間をセットで保存している。

3.　**視聴情報のグラフ化**
Chart.jsなる便利なものに頼りっきり。
しいていうなら、情報の取得はbackground.js、情報の利用はbrowserAction.jsなのでそのやり取りが複雑だった。



## URLの監視と視聴時間の保存
background.jsの主要機能。
別の関数から一定の周期で呼ばれる。

```Javascript:background.js

//URLの監視と視聴時間の保存
//1. URLを確認
//2. 視聴時間を計算（watchingCountをインクリメント）
//3. 視聴時間を保存
function MonitorURL(label) {
    //tab情報を取得
    chrome.tabs.getSelected(tab => {  // 現在のタブを取得
        tabData.URL = tab.url;    // URL取得

        if (tabData.URL.indexOf("youtube") != -1) {
            watchingCount++;

            //保存
            chrome.storage.local.set({ [label]: watchingCount }, function () {
               console.log("TIMEBOX : " + label + ", " + "COUNT : " + watchingCount);
            });

            monitoredFlag = 1;

        }
        else {
            console.log("not watching");
        }
    });
}
```

chrome.tabs.getSelectedで現在選択中のタブ情報が取得できる。
URLに"youtube"の文字列が含まれていれば視聴時間のカウントをインクリメントする。

```Javascript:監視処理
    chrome.tabs.getSelected(tab => {  // 現在のタブを取得
        tabData.URL = tab.url;    // URL取得

        if (tabData.URL.indexOf("youtube") != -1) {
            watchingCount++;
```

chrome.storage.local.setで変数をストレージに保存可能。
保存形式はdictionary型。
今回はKeyを時間帯、Valueを視聴時間のカウントとしている。

```Javascript:保存処理
            chrome.storage.local.set({ [label]: watchingCount }, function () {
```

## 視聴時間の取得と保存

browserActionからbackgroundの下の関数を呼び出す。
下の関数内でbrowserActionへ情報を送信する。


```Javascript:background.js
//browserActionから呼ばれる
//現在の日時と対応する視聴時間を返す
function backgroundFunction() {
    //視聴時間を一度も取得していなければ何もしない
    if (monitoredFlag == 1) {
        //すべてのkeyの視聴時間を表示する
        chrome.storage.local.get(null, function (items) {
            var allDates = Object.keys(items);
            allDates.forEach(function (timeBox) {
                chrome.storage.local.get([timeBox], function (value) {
                    if (monitoredFlag == 1) {
                        chrome.runtime.sendMessage({ key: timeBox });
                        chrome.runtime.sendMessage({ value: value[timeBox] });
                    }
                    else {
                        chrome.runtime.sendMessage({ key: timeBox });
                        chrome.runtime.sendMessage({ value: 0 });
                        console.log("not monitored ");
                    }
                });
            });
        });
    }
    return true;
}
```
ストレージに保存されている時間帯を取得する

```Javascript:background.js
        chrome.storage.local.get(null, function (items) {
            var allDates = Object.keys(items);
            allDates.forEach(function (timeBox) {
                chrome.storage.local.get([timeBox], function (value) {
```

 chrome.runtime.sendMessageを使ってbrowserActionに情報を送信する。

```Javascript:background.js
      chrome.storage.local.get([timeBox], function (value) {
                    if (monitoredFlag == 1) {
                        chrome.runtime.sendMessage({ key: timeBox });
                        chrome.runtime.sendMessage({ value: value[timeBox] });
                    }
```

視聴情報の受け取り側。browserActionの主要機能。
送られてきた時間帯と視聴時間のセットをまとめて、グラフ化する。
グラフ化はChart.jsに丸投げ。

```Javascript:browserAction.js
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
    if (message.key) {
        labels.push(message.key);
    }
    else if (message.value) {
        data.push(message.value);
    }
    //描画用にデータを成型
    CreateData(labels, data);
    //Chart.jsでグラフ化して描画
    DrawGraph(labels, data);

    return true;
});

```


# 課題
・sendとlistenの概念がまだまだ分かってない
・意図せず非同期処理されてる箇所があってハマった
・HTML側でcanvasの作成ができなかった

# 感想
モチベーション優先でとりあえず「作りたいものを作る」と決めって作ってみました。
それはいいもののあまりにもJavascriptやHTMLの知識不足している感が否めませんでした。

良かった点としては、終始モチベーション高く取り組めて挫折しなかったことかなと思います。
悪かった点としては。基礎がわかっていないので「時間が余計にかかってしまう」＆「あまり知識として定着していない」あたりでしょうか。

つぎはもう少し基礎を固めてから何か作りたいですね。


# 参考文献
javascript系
- https://qiita.com/a01sa01to/items/bd7b18b4ec3dc6c46b32
- https://qiita.com/Haruka-Ogawa/items/59facd24f2a8bdb6d369
- https://ferret-plus.com/5884

Chrome拡張機能系
- http://var.blog.jp/archives/52377390.html
- https://www.eisbahn.jp/yoichiro/2012/11/chrome_extension_basic_structure.html
- https://dev.classmethod.jp/articles/google-chrome-extension-1/