2019年10月29日火曜日

Chrome のプラグインを作る! その5 ひとまず完成!

読書の秋です。
電子書籍が普及しているようですが、私は活字が好きです。
紙媒体だと鉛筆で線を引くことができるし、精密機器ではないので気楽にとり回せる。
そして何より、デジタルよりも物質的な温もりがある。

***

先週から思い付きで拡張機能を作り始め、本日、完成した。
「ブログを一週間更新していないと叱ってくれるプラグイン」だ。

ポイント


  • 今回開発したプラグインの概要
  • backgroundで本ブログのフィードを取得する
  • content_scriptsではクロスドメインリクエストができない点でハマった
 

今回開発したプラグインの概要

プラグインとして、以下の処理を実装した
①ブラウザの起動時に本ブログのフィードをJSON形式で取得する
②フィードを解読し、直近の投稿の投稿日時を得る
③現在時刻が直近の投稿の投稿日時よりも一週間以上経過していた場合、アラートで警告を出す

backgroundで本ブログのフィードを取得する

Chrome拡張ではバックグラウンドページで動作するスクリプトで様々な処理ができる[1]。
今回作ったプラグインでは、バックグラウンドページの起動時に本ブログのフィードを取得し、経過時刻の判定を行う。
ブラウザを立ち上げるたびに判定が行われ、嫌でもブログの更新を催促される仕組みだ。

content_scriptsではクロスドメインリクエストができない点でハマった

これは昔はできたらしいが、今ではChromeの仕様変更でできなくなったという[2][3]。
昨日の私はこのことを知らなかったため、content_scriptsでXMLHttpRequestを使ったフィードの取得を試みて失敗し、大いにハマった。


開発・実行環境

ブラウザ Google Chrome
バージョン: 78.0.3904.70(Official Build) (64 ビット)
起動時オプション:
--flag-switches-begin --flag-switches-end

PC
プロセッサ: Intel(R) Core(TM) i5-5200U CPU @2.20GHz
メモリ: 8.00 GB
OS: Windows 8.1 (64bit)
compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.00.24215.1 for x86

フォルダ構成

.
├── background.js
├── icon
│   └── icon.png
├── manifest.json
├── popup.html
└── popup.js
popup.html、popup.js、icon.pngは先日[4]と同じだ。
今回新たにbackground.jsが加わった。

コード

manifest.json

{
  "name": "Blogger alarm",
  "description" : "Blogger alarm",
  "manifest_version": 2,
  "version": "1.0",
  "permissions": [
    "http://*/*", "https://*/*"
  ],
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
    "default_popup": "popup.html"
  },
  "icons": {
    "16": "icon/icon.png",
    "32": "icon/icon.png",
    "48": "icon/icon.png",
    "128": "icon/icon.png"
  }
}
先日[4]のマニフェストに以下の三行を追加した。
  "background": {
    "scripts": ["background.js"]
  },
background.jsが今回新たに実装したスクリプトだ。

background.js

window.onload = function() {
  var xhr = createXMLHttpRequest();
  var url = 'https://mamorunoblog.blogspot.com/feeds/posts/default?alt=json&orderby=published';
  xhr.onreadystatechange = function() {
    switch (xhr.readyState) {
      case 4:  // DONE
        if (xhr.status != 200) {
          return;
        }
        // Parsing JSON.
        var data = JSON.parse(xhr.responseText);
        var limitDays = 7;
        if (data.feed.entry.length > 0) {
          var lastPost = new Date(data.feed.entry[0].published.$t);
          var now = new Date()
          let diff = now.getTime() - lastPost.getTime();
          diff = diff/(1000*60*60*24);
          if (diff > limitDays) {
            alert(`Your blog is not updated for ${limitDays} days!\nlast post: ${lastPost}`);
          }
        }
        break;
      default:
        // none.
        break;
    }
  }
  xhr.open('GET', url);
  xhr.send();
}

function createXMLHttpRequest() {
  if (window.XMLHttpRequest) {
    return new XMLHttpRequest();
  }
  if (window.ActiveXObject) {
    try {
      return new ActiveXObject('Msxml2.XMLHTTP.6.0');
    } catch (e) {
      // none.
    }
    try {
      return new ActiveXObject('Msxml2.XMLHTTP.3.0');
    } catch (e) {
      // none.
    }
    try {
      return new ActiveXObject('Microsoft.XMLHTTP');
    } catch (e) {
      // none.
    }
  }
  return false;
}

diffに直近の投稿の投稿日時から現在時刻までに経過した時間(日)を計算して代入する。
limitDaysは投稿間隔の閾値(日)である。
diffがlimitDaysを超えていた場合、投稿していないことを叱ってくれる。

実行結果



画像は、拡張機能をリロードしたところだ。
こんな感じでアラームを出して叱ってくれる。

ここ一週間は連日投稿しており叱られないですむ道理ではあるが、動作確認のために limitDays=1 と厳しく設定し、自ら進んで叱られてみた。
画像はリロードのタイミングでのアラームの表示だが、ブラウザのウィンドウを新しく開いた際にもアラートが出る。

今後の課題


  • Blogger API なるものがあるらしい
    あまり調べられてないが、専用のAPIがあるようだ。
    BloggerがAPIを用意しているのであれば、導入を検討する必要がありそうだ。
    使用すべき状況にあるか、ライセンス的にどうかが気になる。
     
  • 拡張機能の設定画面を実装して、閾値となる日数を設定できるようにしたい
    忙しさが変われば、目標とする投稿頻度も変わるだろう。
    そのため、limitDays を固定ではなく、任意に設定できるようにしたい。
    設定画面の実装方法の習得ができる点も魅力だ。
     
  • アイコンクリックで表示されるポップアップの表示を最適化したい
    デバッグのためアイコンクリックのポップアップに投稿一覧を表示したところ、割といい感じの一覧が出たので、正式な機能にしたい。
    表示しなくてもよい項目(例えばauthor)を削り、UIを洗練したい。
    また、タイトルをクリックすると投稿のページにジャンプするなど、実用的な機能がほしい。
     
  • 前例などを調査して、アプリストアに出したい(発展)
    あまり下調べしていないので、似たようなプラグインが既にあるかもしれない。
    そうであれば、そちらを導入する、コントリビューションを考えるなど、このプラグインを改良しアプリストアに出す以外に取るべき行動があるはずだ。
    しかし、もし似たようなプラグインが存在しないか、しても違った方向性で発展させられるのであれば、将来性がある。
    今の私はJavaScriptとChrome拡張の両方の初心者なので、アンチパターンの地雷原を駆け抜けている可能性がある。
    もうちょっとモノ作りながらJavaScriptの常識を身に着けてから深く考えたい。


感想

スピード感のある開発だった。
非常に荒削りなプラグインなので、使いながら研ぎ澄ましたい。

思ったのが、横着しないできちんと調べるのが基本だということ。
contents_scriptでクロスドメインリクエストができない問題なんかは特にそうだ。
XMLHttpRequestが動くことは先日調べてあるので、「なぜ動かないんだっ」てコードとにらめっこしてばかりいたから、ハマったのだ。
ハマった状態から抜け出すには、一度頭をリセットし、目の付け所を移す必要がある。

付録

特になし。

参考文献

  1. Chrome拡張の開発方法まとめ その1:概念編
  2. Chrome拡張のContent ScriptsからCross-Origin Read Blocking (CORB)を回避して外部のAPIと通信する
  3. Changes to Cross-Origin Requests in Chrome Extension Content Scripts
  4. Chrome のプラグインを作る! その4 本ブログのフィードを取得する

0 件のコメント:

コメントを投稿

コメント表示は承認制に設定しています