3

私は実際に最初のChrome拡張機能に取り組んでおり、スムーズに実行get()されたとしても、データを取得するために使用している関数から多くのエラーが発生し、コードのセキュリティに関する厄介なエラーが発生しました。

これがコンソールログのスクリーンショットです: コンソールログ

以下に関連するコードがあります:

popup.html

<!doctype html>
<html>
<head>
    <title>NGI Little Helper - Subscribes</title>
    <link rel="stylesheet" href="popup.css">
    <!-- JavaScript and HTML must be in separate files for security. -->
    <script type="text/javascript" src="common/jquery.js"></script>
    <script type="text/javascript" src="popup.js"></script>
</head>

<body>
    <h1>Topics</h1>
    <div id="content">..:: Loading ::..</div>
</body>
</html>

popup.js

このスクリプト$.get()は、リモートWebページへの作成を開始します。変数の内容はここdataにあります

$.get("http://gaming.ngi.it/subscription.php?do=viewsubscription", function(data) {
    var TDs = $('td[id*="td_threadtitle_"]', data);
    $(document).ready(function() {
        $("#content").html("<br/>");
        $.each( TDs, function() {
            //Removes useless elements from the source
            $('img[src="images/misc/tag.png"]', this).remove();
            $('span', this).remove(); //$('span[class="smallfont"]', this).remove();
            $('div[class="smallfont"]', this).remove();
            $('img[src="images/buttons/firstnew.gif"]', this).attr('src', '/img/icons/comment.gif');
            $('a[style="font-weight:bold"]', this).removeAttr("style");
            //Modify the lenght of the strings
            if ($("a[id^='thread_title_']", this).text().length > 35) {
                $("a[id^='thread_title_']", this).text( $("a[id^='thread_title_']", this).text().substring(0, 30) + " [...]" );
            }
            //Modify the URL from relative to absolute and add the target="_newtab"
            $("a[id^='thread_']", this).attr('href', "http://gaming.ngi.it/"+ $("a[id^='thread_']", this).attr('href'));
            $("a[id^='thread_']", this).attr('target', "_newtab");
            //Send the HTML modified to the popup window
            $("#content").html($("#content").html() + $('div', this).wrap("<span></span>").parent().html() +"<br/>" );
        });
    });
});

ここでは、jqueryからすべての操作を行った後のHTMLを見つけることができます。

正直なところ、これらのエラーがなぜ表示されるのか、特にセキュリティに関連するエラーが表示されるのか理解できません。私はpopup.htmlでインラインコードを使用していません。

Manifest.json

{
    "name": "NGI Little Helper",
    "version": "0.8.5",
    "manifest_version": 2,
    "description": "Extension per gli Utenti del forum gaming.ngi.it",
    "options_page": "fancy-settings/source/index.html",
    "background": {
        "page": "background.html"
    },
    "icons": {
        "16": "img/logo16.png",
        "48": "img/logo48.png",
        "128": "img/logo128.png"
    },
    "content_scripts": [{
        "matches": ["*://gaming.ngi.it/*"],
        "js": ["common/jquery.js", "logo_changer/logo_change.js"],
        "run_at": "document_start"
    }],
    "browser_action": {
        "default_icon": "img/icon.png",
        "default_popup": "popup.html",
        "default_title": "Visualizza Subscriptions"
    },
    "permissions": [
        "*://gaming.ngi.it/*"
    ]
}

以下は、すべての操作の後にポップアップウィンドウにレンダリングされるHTMLコードの一部です。すべてdivがこれに似ていますが、URLが変わるだけです。

<div>

            <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_gotonew_555954" target="_newtab"><img class="inlineimg" src="/img/icons/comment.gif" alt="Go to first new post" border="0"></a>




            <a href="http://gaming.ngi.it/showthread.php?goto=newpost&amp;t=555954" id="thread_title_555954" target="_newtab">[All Gamez] [Frozen Synapse] S [...]</a>

        </div>

必要に応じて、完全なソースコードを提供できます。

4

1 に答える 1

9

最も簡単な問題から始めましょう:

インラインスクリプトの実行を拒否した理由...

$('div', this)<div>内のすべての要素を選択します<td>。提供したソースコードには、次のイベントハンドラがあります。

<div class = "smallfont">
    <span style = "cursor:pointer" onclick = "window.open('member.php?u = 47995'、'_self')" > K4raMong </ span>
</ div>

デフォルトのコンテンツセキュリティポリシーでは、これは禁止されています。エラーを取り除くには、ドキュメントに挿入する前に属性を削除するだけです。

element.removeAttribute('onclick'); // in jQuery: $element.removeAttr('onclick');

これらの画像が読み込まれるのはなぜですか?私はそれらを文書に入れませんでした

jQuery / JavaScriptがDOMを操作する前に、まずそれを解析する必要があります。あなたのコードでは、この作業は暗黙的にで行われますvar TDs = $(.., data)。ライン。この構文解析は、ほぼ次のようになります。

var dummy = document.createElement('div'); // Container
dummy.innerHTML = data;

画像のプリロードについて聞いたことがありますか?これは、画像をキャッシュして、必要なときにすぐに使えるようにするための便利な機能です。これは、を使用して実行できます(new Image).src='...';。作成した<img>要素をドキュメントに挿入する必要はありません。

あなたの場合、これらの画像は拡張機能で検索されるため、これは望ましくない動作です。これは、Webページが絶対URLではなく相対URLを使用していることが原因です。相対URLを使用する場合、リソースの予想される場所は、現在のドキュメントの場所によって異なります。

それを修正する方法

jQueryは使用しないでください。Chrome拡張機能を作成しているので、ブラウザ間の互換性について心配する必要はありません。jQueryは、innerHTML前に示したように、失敗したHTMLを解析するためにこのトリックを使用します。

JavaScriptにはDOMParserオブジェクトがあり、Chrome30以降は次のように使用できます。

var doc = (new DOMParser).parseFromString(data, 'text/html');

responseType以下に示すように、プロパティを使用して文字列からドキュメントへの手動変換をスキップできます。

ソリューションに到着

permissionsご存知のとおり、マニフェストファイルのセクションにURLが正しく追加されていれば、Chrome拡張機能でクロスサイトリクエストが可能です。XMLHttpRequestレベル2で導入された機能、つまりresponseType属性を使用します。

// Fetching data
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://gaming.ngi.it/subscription.php?do=viewsubscription');
xhr.onload = function() {
    var doc = xhr.response;
    // Now, you can use jQuery, since the string has been parsed.
    ...
};
xhr.responseType = 'document'; // Chrome 18+
xhr.send();

jQueryの代わりにネイティブDOMとJavaScriptを使用するようにコードを簡単に書き直すことができます。ほとんどの場合、セレクターエンジンにjQueryを使用しますが、ほとんどの場合、を使用して実装することもできますelement.querySelectorAll。を使用してドキュメントを取得した後var doc = xhr.response;、次の手順を実行します。

var TDs = doc.querySelectorAll('td[id*="td_threadtitle_"]');
var html = '';
[].forEach.call(TDs, function(td) {
    // etc, etc. Do your job
});

見えvar html = '';ますか?jQueryを使用しているかどうかに関係なく、これは良い習慣です。ループで実行しelement.innerHTML += ...;たり、さらに悪化させたりしないでください。$element.html($element.html() + ...);ブラウザは何度も何度もレンダリングするのに苦労し、ユーザーとしてはパフォーマンスの低下に気づきます。

于 2012-08-23T22:34:41.487 に答える