Chrome拡張とGASを連携させる例

この記事が古くなってしまったので、[Chrome拡張とGASを連携させる例\(改\) \- Qiita](https://qiita.com/sakaimo/items/f1b2b8353da1e7de6e3d) を参照してください！(2021/05/18)


-------------------------


[【エンジニア交流会】Google Apps Script 活用ミートアップ \#4 \- connpass](https://gaiax.connpass.com/event/128186/)

で発表したこれ↓

[Google Apps Script 活用ミートアップ\#4 発表資料](https://www.slideshare.net/takayoshisakaino/google-apps-script-4-146986621)

の中で **Chrome拡張とGASで連携させる例** を紹介したのですが、質疑応答のときに「ソースコードが見たい！」というリクエストをもらいました。時間の都合と、懇親会で酔ってたので、改めてこの場で紹介します。

Chrome拡張(エクステンション)とGASを使ってこんなことができるよ、という例です。
活用方法はいろいろあると思うので、いいネタがあったら教えてほしいです！


# 例題として

「Qiitaを見ていて「この記事いいな」って思ったら、そのタイトルとURLをスプレッドシートに記録しておきたい」
※今回は例として紹介していますので、本来ならQiitaにある「ストック」機能を使ってくださいねw

↓ こんなイメージ
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/423d51c8-0f22-d38e-7b47-0fc8930d89cb.png)



# 必要なスキル

- Chrome拡張が作れること
- GASでスプレッドシート操作ができること
- GASで「ウェブアプリケーションとして導入」ができること


# 処理の流れ

- Chrome拡張で、Qiitaの画面にボタンを挿入する
- ボタンを押したらURLとタイトルをGASに送信する
- GASが doPost()で受け取って、スプレッドシートに書き出す

(追記:190602)
「画面の中にボタンを挿入」しなくても、`Browser Action` (Chrome右上のアイコンを押したときに発動するやつ)で実装するほうがより実践的だと思うのですが、特にChrome拡張を知らない人に「こんなこと(画面内に要素を追加できちゃう)ができるのか！」というのを知ってもらうため、わざわざこうしてみました。

----

# GASのコード

今回はスタンドアロンのスクリプトでリクエストを受けて、そこからスプレッドシートに書き込んでいます。
スプレッドシートにバインドされてるスクリプトで受けてもOKです。


```js
function doPost(e) {
  // エクステンションから送信されたデータを取り出す
  const params = JSON.parse(e.postData.getDataAsString());
  const title  = params.title;
  const url    = params.url;

  // スプレッドシートの最終行に書き出す
  const sheet = SpreadsheetApp.openById('xxxxxxxxxxxxxxx').getSheetByName("xxxxx");
  sheet.appendRow([title, url]);
  
  // エクステンションにレスポンスを返す
  var output = ContentService.createTextOutput();
  output.setMimeType(ContentService.MimeType.JSON);
  output.setContent(JSON.stringify( { sucsess: true }));
  return output;
}
```

スクリプトエディタから、
「公開」→「ウェブアプリケーションとして導入」してURLを取得する。
そのURLをエクステンションに記載。



## おまけ情報(ログの確認)

GASの中で 

```js
console.log("あああ"); // Logger.log() じゃなくて
```

て書いておくと、ログを `Apps Script ダッシュボード` で確認できます。
「表示」→「Stackdriver Logging」から見えます。(現時点では)

# Chrome拡張のコード

## ファイル構成

JQueryはダウンロードしておいてください。→ [Download jQuery](https://jquery.com/download/)


```
Qiitaで実験
 └ content.js
 └ jquery-3.4.0.min.js
 └ manifest.json
```

## manifest.json


```json:manifest.json
{
  "manifest_version":2,
  "name":"QiitaのタイトルとURLをスプレッドシートに書き出す君",
  "version":"1.0",
  "permissions": [
    "https://script.google.com/*",
    "https://script.googleusercontent.com/*"
  ],
  "content_scripts":[
    {
      "matches":[
        "https://qiita.com/*"
      ],
      "js":[
        "jquery-3.4.0.min.js",
        "content.js"
      ]
    }
  ]
}
```

## content.js

↓ 私、最近のJSについていけてないので、書き方おかしかったらゴメンナサイ。

```js:content.js
// 「Webアプリケーションとして導入」しているGASのURL
const gasUrl = "https://script.google.com/a/xxxxxxxxxxxxxxxxxx/exec";

$(function() {
  // 画面にボタンを挿入する
  $('#main').prepend('<input type="button" id="postBtn" value="リストに保存">');

  // ボタンがクリックされたときの処理
  $('#postBtn').on('click', function() {
    const url   = location.href;
    const title = $('.it-Header_title').text();
    post2GAS(url, title);
  });
});

function post2GAS(url, title){
  const data = {
    url: url,
    title: title
  }

  $.ajax({
    type: 'POST',
    url: gasUrl,
    data: JSON.stringify(data)
  })
  .done( function(data) {
    console.log("成功");
  })
  .fail( function(jqXHR, textStatus, errorThrown) {
    console.log("失敗");
    console.log("XMLHttpRequest : " + jqXHR.status);
    console.log("textStatus : " + textStatus);
    console.log("errorThrown : " + errorThrown);
  })
  .always( (data) => {
    console.log("処理終了");
  });
}
```

# 実行してみる

- エクステンションをインストール
- Qiitaの記事にアクセス
- ボタンを押す

↓ エラーがあったら`Console`に何か出ると思います。

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/863c44b8-74b2-3582-0609-7f0a71e15d4f.gif)



# 注意点

(というか教えてほしいこと)

## Googleのアクセス権限

弊社はG Suiteを導入しているので、自社のGoogleアカウント内で公開しているGASに対して、社内アカウント以外からはアクセスできなくなっています。「ウェブアプリケーションとして導入」のときも「自分だけ」あるいは「社内ドメインの全員」しか選べません。(匿名が選べない)

そのため、Chrome拡張を動かすChromeが、自社アカウントでGoogleログインしていることが必要。
(ここらへん、本当にそうなのか確信が持ててないのだけれど、どなたか情報ありましたら教えてほしい)

(追記:190602)
実験したところ、「Chromeブラウザで、自社アカウントから **ログアウト** した状態」でボタンを押すと下記のようにエラーになります。つまり「会社のGoogleアカウントを持っていない人がこのエクステンションをインストールしたとしてもGASにはアクセスできない」となります。

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8612/1af90774-e839-04fe-5140-c070832026bc.png)


## CORS対応

```json:manicest.json
  "permissions": [
    "https://script.google.com/*",
    "https://script.googleusercontent.com/*"
  ],
```

実験しているうちに上記の2つのURLでエラーが出るパターンがあったのでこれを追加しているのですが、
正直、CORSについて「完全に理解した」とは言えない状態なので何か間違ってたら教えてほしい。


## エクステンション機能追加

(追記:190602)
仮にこのエクステンションを他の人に配布すると、利用者全員の「リストに保存する」が、一つのスプレッドシートに書き出されることになります。実用的にするには、エクステンションに「設定画面」を用意して「ユーザーごとに保存先を指定できる」機能をつけるカッコイイと思います。


# 最後に

今回は「Chrome拡張からGASにPOSTする」でしたが、「Chrome拡張がGAS(スプレッドシートとか)が持っている情報をGETして、それを元にブラウザ上の表示や挙動を制御する」みたいなこともできます。

ブラウザを使ってお仕事している人はいっぱいいると思うので、これを活用したらいろいろ「業務効率化」できるのでは！？