content_scriptsの中でdocument.write();をする方法

761 views
Skip to first unread message

Fushihara Gengoro

unread,
Jan 26, 2013, 8:28:47 PM1/26/13
to chrome-api-d...@googlegroups.com
1.質問
拡張のcontent_scripts中のjsで、任意の外部jsファイルを読み込んで、そのjsファイルの中で任意のテキストをdocument.write();させるにはどうしたらよいでしょうか。

もう少し具体的に言うと、content_scriptsの中から外部のhttp://~/~.jsという外部jsを読み込ませたいのですが
その外部jsにdocument.write();が使われてしまっています。
元々、htmlの中にベタ書きする事を想定したブログパーツの様なもので、第三者が作られているので手を加える事が出来ません。

確かにhtmlの中に<script src="~~"></script>と書いておけばdocument.write();で何の問題も無いのですが
content_scriptsですとjavascriptから追加する必要があります。


manifest.json のcontent_scripts.run_atの値で実行されるタイミングが変わるので、もしかしてdocument.write();が効くタイミングがあるかも
と値document_idle、document_start,document_endにしてみたり
外部jsを呼び出す方法を
script = document.createElement("script");script.src = "http://~";document.body.appendChild(script);と
document.write('<script src="~"><'+'/script>');
の両方で試したのですが
タイミングが早いとdocument.bodyが無くてappendChildが成功しなかったり
タイミングが遅いとdocument.write();を実行した途端ページ内容がクリアされたりとどうもうまくいきません。

2.バグ発見?
また、content_scripts.run_atにdocument_startと指定して
実行させるcontentScriptに
document.write('from contentScript');
console.log("contentScriptが呼び出し",Math.random());
と指定すると、contentScriptは一度しか呼び出されないはずなのに
contentScriptが呼び出し 0.38785913377068937 contentScript.js:2
contentScriptが呼び出し 0.6574389105662704 contentScript.js:2
contentScriptが呼び出し 0.7338545499369502 contentScript.js:2
contentScriptが呼び出し 0.6709329732693732 contentScript.js:2
contentScriptが呼び出し 0.9620644422248006 contentScript.js:2
contentScriptが呼び出し 0.7930269243661314 contentScript.js:2
contentScriptが呼び出し 0.20299813826568425 contentScript.js:2
contentScriptが呼び出し 0.9966204478405416 contentScript.js:2
・・・と、何度もcontentScriptが呼び出されていまい
デベロッパーツールのelementsタブが
<html></html>
<html></html>
<html></html>
<html></html>
<html></html>
<html></html>
・・・とDOMが壊れてしまっています。
そもそもdocument_startでdocument.writeするなという事かもしれませんが・・・。

以上です。

Yoichiro Tanaka

unread,
Jan 30, 2013, 9:27:46 PM1/30/13
to chrome-api-d...@googlegroups.com
よういちろう です。

いろいろと試してみました。結果は以下です。

1. createElement("script")な方法

結果はNG。読み込まれる外部jsとして document.write("Hello!"); だけするものを準備し、
それを読み込んでみるも、run_atにいかなる値を指定しても、document.write() が評価
されても何も起きなかったです。エラーにならず、その次の行もちゃんと評価が続く
んですけど、write() だけがスルーされてる状況でした。

2. content-script内でdocument.write("<script ...")する方法

結果はOK。ちゃんと読み込まれる外部JSで行われる document.write("Hello!");が正しく
評価されました。run_atの値全てにおいて大丈夫です。

試した外部jsは、http://www.eisbahn.jp/test/document_write.js で、content scriptで差し
込むjsファイルに以下を書いています。

document.write('<script src="http://www.eisbahn.jp/test/document_write.js"></scr' + 'ipt>');

というわけで、簡単な拡張機能を作った結果は、write() で外部jsを読み込んであれば
大丈夫そう、ってことに手元ではなりました。ちなみに、Chrome 24.0.1312.56、OSは
Ubuntuです。

試したコード一式を以下に載せます。やってみてください。
ご参考になれば幸いです。ではでは。

[manifest.json]
{
    "manifest_version": 2,
    "name": "Test extension",
    "version": "0.0.3",
    "permissions": [
        "http://*/*",
        "tabs"
    ],
    "content_scripts": [
        {
            "matches": ["http://*/*"],
            "js": ["content_script.js"],
            "run_at": "document_idle"
        }
    ]
}

[content_script.js]
console.log("content-script.js: start");
//    var script = document.createElement("script");
//    document.body.appendChild(script);
document.write('<script src="http://www.eisbahn.jp/test/document_write.js"></scr' + 'ipt>');
console.log("content-script.js: end");


2013/1/27 Fushihara Gengoro <fushih...@gmail.com>

--
--
このメールは Google グループのグループ「Chrome API Developers JP」の登録者に送られています。
このグループに投稿するには、chrome-api-d...@googlegroups.com にメールを送信してください。
このグループから退会するには、chrome-api-develop...@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/chrome-api-developers-jp?hl=ja からこのグループにアクセスしてください。
 
 
 



--
Yoichiro Tanaka
Email: yoic...@eisbahn.jp
Blog: http://www.eisbahn.jp/yoichiro

Fushihara Gengoro

unread,
Jan 31, 2013, 7:19:44 AM1/31/13
to chrome-api-d...@googlegroups.com
御返事ありがとうございます。

document.writeする方法ですが、やはりページ内容がクリアされてしまいます。
content-script関係なく、表示したページでデベロッパーツールを開きdocument.write("");をコンソールから実行しますと、ページ内容がクリアされますし
MDNでも"新しい内容では、古い内容は削除されます"と書かれています。
こちらのバージョンは 24.0.1312.56 m windows7 64bit ですが、Ubuntuではクリアされないのかな?

document.body.parentNode.outerHTMLを取って全部書きなおしちゃえばいいやとも思ったのですが
ページによっては不安定でとても拡張機能には組み込めませんでした。

このようなページもありますし、document.writeはなかなかクセが強いようです。
HTML5でdocument.writeは使ってはいけない? | 3streamer blog


2013年1月31日木曜日 11時27分46秒 UTC+9 Yoichiro Tanaka:

2013/1/27 Fushihara Gengoro <fushih...@gmail.com>
このグループに投稿するには、chrome-api-develo...@googlegroups.com にメールを送信してください。
このグループから退会するには、chrome-api-developers-jp+unsubscribe@googlegroups.com にメールを送信してください。
詳細については、http://groups.google.com/group/chrome-api-developers-jp?hl=ja からこのグループにアクセスしてください。
 
 
 
Message has been deleted

Shogo Ohta

unread,
Jan 31, 2013, 11:21:08 AM1/31/13
to chrome-api-d...@googlegroups.com
こんにちは、太田です。

document.write は単なる関数なので、上書きしてしまうというテクニックもあります。
次の記事などが参考になるかと思います。

Chrome拡張の場合、content_scriptsの中で上書きするのではなく、
その外部JSファイルと同じコンテキスト上のdocument.writeを上書きする点がポイントになります。

かなり技巧的な手法ですが、歴史は結構古く( http://la.ma.la/blog/diary_200612061928.htm など)、
実際に使われている事例はいくつかみたことがあります。

参考になれば幸いです。

2013年1月31日木曜日 21時19分44秒 UTC+9 Fushihara Gengoro:
Reply all
Reply to author
Forward
0 new messages