GASで作ったWebアプリがあって、安定稼働していたので(特に文句が出なかったので)油断して放置していたのだが、ある日急にバグってると言われた。
Chromeの仕様変更によるものだが、半年も放置していたので、副次的に色んなトラブルが起こってハマった。
徒然なるままに書くので暇な人だけ読んでね。
概要
以下の現象が起こっていた。
- Chromeの最新版でCORSが禁じられたのでGASではないJavaScriptのalert()とwindow.confirm()が動かなくなった。それを出しているSUBMITボタンが効かなくなった
- Chromeにオプションをつけて制限をゆるめれば動くという話もあったけど、今回はダメだった。
- 単純にalert()とwindow.confirm()関数を削除するとSUBMITが効くようになった
- 話は変わるが、しばらく使っていないGASのWebアプリを使ったり、しばらくそのアプリを使っていないアカウントから使おうとすると「その操作を実行するには承認が必要です」と言われる。スクリプトエディターからデプロイをやり直すと動く
- 削除したalert()とwindow.confirm()の代替案はまだやってない。JSONPというのを使うらしい? そのうちやるかも
ある日動かなくなった
GAS+clasp+TypeScript+WSLでWebアプリを書いている。
ファイルをアップロードしたりGスプレッドシートを書き換えたりするというもの。
難しいことはしてません。
開発が終わって半年余。
特に文句は出なかったので油断しきっていた。
開発環境もテストアカウントも触っていなかったのである。
そんなある日、動かなくなったとユーザーから言われた。
SUBMITボタンをクリックすると、ファビコンがクルクル回って更新が起こるはずだが、起きないという話。
自分の環境では通常に動作していたので「Chromeのキャッシュを削除したり、Windowsを再起動したり、Chromeを最新版にしたり、キャッシュをクリアしたりしてみてください」と言ったが、「そのへんのことは全部やりました」そりゃそうだね。
放っておいたら同様のレポートが続々と届き、対策することになった。
iPhoneでやったら動く
なぜかiPhone版のChromeだと動くので、それでしのいでもらった。
でも承認ボタンを押すぐらいならそれで済むけど、メッセージを書いたりファイルをアップロードしたりさせるのは気が重い。
対策に乗り出した。
開発版アプリが動かない
いちおうアプリを開発版と本番用で分けているので、開発版で駆動してみた。
だが、ボタンが押せないどころか、「その操作を実行するには承認が必要です」と言われて真っ白な画面になる。
このメッセージでググると、たいてい下の対策を勧められるが、解決しなかった。
- トリガーを追加したり、削除して再作成したりしてください<=そもそもなかった
- Developer Hubから、Google Apps Scriptをオンにしてください<=もともとオンだった
万事休す。
アカウントの問題だろうと思って、アカウント=>セキュリティ=>サードパーティアプリというところで? くだんのアプリを見つけた。
本番用はあるけど、開発版がない。
なんとなく本番用を削除してみたら、さっきまで使えていた本番用も同じメッセージが出て使えなくなった。
ヒエー🥺
開発環境がリニューアルされている
ようやく本腰を入れて対応する気になって、スクリプトエディターを開いてみた。
なんか様子が違う。
この半年の間に、Googleによってリニューアルされているのだ。
そのうち使ってみたいとは思うけど、こういう切羽詰まった時に状況を複雑にするものではないと思ってレガシー版に戻した。
「リニューアル版の何がお気に召さなかったでしょうか」みたいなアンケート画面が出てくる。
うっせーわ。
とりあえずクローズさせてもらう。
レガシー版に戻しても、「新しいエディタを使用」ボタンが表示されてる。
ま、そのうちな。
デプロイ(公開)をやり直した
何がなんだか分からないのだが、とりあえずコードは1文字も変えずにデプロイだけやり直してみた。
デプロイ、それは開発したアプリを配布することで、スクリプトエディターからは公開=>ウェブアプリケーションとして導入で行う。
これをやってみたのだ。
(バージョン番号が1つ上がる)
なぜ上記の行為に出たか、自分でも分からないのだが、なんとなく、それだけのことで、「その操作を実行するには承認が必要です」の問題が解決した。
あと、開発用アカウントからアクセスしても、同じメッセージが出て困っていたが、さらにもう1回デプロイしてみたらなんとなく治った。
こういう感じのようだ。
- しばらく使っていないウェブアプリケーションを起動すると「その操作を実行するには承認が必要です」と言われることがある。デプロイをやり直すと治る
- しばらく使っていないアカウントからウェブアプリケーションを起動すると「その操作を実行するには承認が必要です」と言われることがある。デプロイをやり直すと治る
フワッフワした話ですみませんが、どうもこういうことのようだ。
新しいChromeからだとダメ
それにしてもなぜ自分では再現できないのだろうか。
開発者は、孫を抱くように優しく自分のアプリを扱うし、ついつい危ない操作は避けるので、開発者がテストするとバグが出せないのはあるあるだけど、やっかいな現象だ。
ふと気づくと、Chromeの右上に「更新」というボタンが表示されている。
なんと驚きなされ。
ユーザーのみなさんには「最新版のChromeを使っていますか」と言っていた開発者が、なんと自分は古いバージョンのChromeを使っていたのである!!
これは問題やろう。
具体的に言うと、91.0.4472.124では動作していたアプリが、92.0.4515.107では動作しなくなった。
ひどいな俺。
iPhoneのChromeはバージョンが古いんだろう。(※2021-07-30追記:本件コメントいただきました)
問題はCORS
ということで、晴れて問題が出るようになった。
具体的に言うとSUBMITしても何も起きない。
この瞬間にCtrl+Shift+Iを押下して、検証(Inspection)ペインを表示させると、以下のエラーが表示された。
exec:1 A different origin subframe tried to create a JavaScript dialog. This is no longer allowed and was blocked. See https://www.chromestatus.com/feature/5148698084376576 for more details.
ということで、JavaScriptのダイアログを表示しようとしていますがこれはcloss originなのでもう許せませんみたいな感じ。
GAS、alert、クロスオリジンでググると、これはCORSという問題であると分かった。
SUBMITボタンをクリックすると「本当にサブミットしていいですか[OK][キャンセル]」みたいな確認ダイアログを表示したいという局面があった。
これを、ぼくはサーバーサイドのGAS(ファイル名はCode.jsにしている)ではなくて、クライアントサイドのJavaScript(おなじくjs.js)にwindow.confirm()で書いていた。なぜそうする必要があったかは諸事情で書けない。
あと、必要な項目を入れずにSUBMITした場合も「xxxを入れてからSUBMITしてください[OK]」みたいなエラーダイアログを表示していたが、これもjs.jsでalert()を出していた。
上のURL先の文章によると、これがクロスオリジンiframeだからそういう関数を取れという。
取れ、と言われても機能性が変わってしまうのだが、今回は時間がなかったので全部取ってみた。具体的に言うと
let ok = window.confirm("いいんですか?");
if (ok) {
いいときの処理...
みたいなコードを見つけては
//let ok = window.confirm("いいんですか?");
let ok = true;
if (ok) {
いいときの処理...
にしたり、
alert ("ダメですよ");
を見つけては
//alert ("ダメですよ");
にするみたいな簡単なお仕事だ。
必要ないんだからブチ消してもいい気がするけど、あとでもっとちゃんと対応するつもりなので、あえてこういう傷跡を残す編集にしておいた。
claspの操作で多少戸惑ったが、自分のQiitaの過去記事で多少役立った。
だからクソ記事でも書いておいた方がいいよ。
Web記事は役に立たないこともある
話が前後するが「CORS Chrome 動かない」でググると、Chromeにオプションを渡して、制限を緩めてやればいい、という記事に当たる。
年々厳しくなってるらしくて、昔の記事のオプションではダメだったけど、こういう風に変えたら動いた、みたいな記事もある。
ということで、制限は日々きつくなっている。
現状は、Chromeにオプションを渡す方法では、今回のエラーは回避できなかった。
今後
ということで、操作性が変わってしまった。
いぜんはSUBMITを押してもワンクッションあったのだが、今回はいきなり実行される。
それでいいかどうかは分からない。
あと、エラーメッセージが出ないのは不親切だから、そのうち対応したい。
対応したいところではあるんだけど、どうしたらいいんだろうね。
JSONPというのを使えばいい? のかな?
まあ、そのうちな。
教訓としては、とりあえず安定稼働したシステムでも月1ぐらいは「糠床をかき回す」ぐらいのことをしておいたほうがいいかもしれないということだ。
GASが本業ではないので、放っていたが、クラウドあるあるで、Google様の事情で急に変わっていて、あわてて対応しようとすると必要以上に苦労する。
今後気をつけます。
追記(2021-08-04)
結局アプリの設計を見直して、GASだけの機能で警告、確認を行うフローにしたので、alert()、window.confirm()の代替は必要なくなったっぽい。
なお、本記事をリンクしてくださった下記事に、もっとズバリの代替策を書いている気がするので、参考までにリンク。
https://qiita.com/basictomonokai/items/928ca76bd1f985dd067d#_reference-8b8fd384eb0662af2649
(この項終わり)