1

ページ アクション ボタンをクリックしたときに、コンテンツ スクリプトを複数回実行する機能が必要な拡張機能を作成しています。私は私のbackground.jsにこれを持っています:

chrome.pageAction.onClicked.addListener(function(tab) {
    alert('calling content_script');
    chrome.tabs.executeScript(null, {
        file: 'content_script.js'
    },function(){alert("success");});
});

これは、ボタンが初めてクリックされたときに機能します。もう一度クリックすると、「calling content_script」というポップアップが表示されますが、コンテンツ スクリプトは実行されません。どうしてこれなの?

バックグラウンド スクリプト全体を次に示します。

function checkForValidUrl(tabId, ChangeInfo, tab){
    if(tab.url.indexOf("tiger.armstrong")> -1){
        chrome.pageAction.show(tabId);
        if(tab.url.indexOf("tiger.armstrong") == 0){
            chrome.pageAction.hide(tabId);
        }
    }
}

chrome.tabs.onUpdated.addListener(checkForValidUrl);

chrome.pageAction.onClicked.addListener(function(tab) {
    alert('calling content_script');
    chrome.tabs.executeScript(null, {
        file: 'content_script.js'
    },function(){alert("success");});
});

マニフェストは次のとおりです。

{
  "name": "LiveLab Post Grades",
  "version": "2.0",
  "permissions": [
    "activeTab","tabs","http://*/*","https://*/*"
  ],
  "background": {
    "scripts": ["jquery.min.js","background3.js"],
    "persistent": false
  },
  "page_action": {
    "default_icon": {
      "19": "GIcon.png"
  },
    "default_title": "LiveLab Tools"
  },
   "content_scripts": [ {
    "js": [ "jquery.min.js" ],
    "matches": [ "http://*/*", "https://*/*"],
    "run_at": "document_end"
  }],
  "manifest_version": 2
}

コンテンツ スクリプトは次のとおりです。

var livelabtools = {
    /**
     * this function is like window.open, but it can POST (rather than GET) from js
     * source: http://canop.org/blog/?p=426
     */
    canop_open: function (verb, url, data, target) {
        var form = document.createElement("form");
        form.action = url;
        form.method = verb;
        form.target = target || "_self";

        if (data) {
            //for (var key in data) {
                var input = document.createElement("input");
                input.name = 'data';
                input.value = data;//typeof data[key] === "object" ? JSON.stringify(data[key]) : data[key];
                form.appendChild(input);
                //console.log(form);
            //}
        }
        // these two lines are only needed for ie
        //form.style.display = 'none';
        //document.body.appendChild(form);
        form.submit();
        console.log("form submit ===  " + form);
        form.remove();
    },
    post_grades: function () {
        alert('in post grades!!!!');
        var str, exercise,
        i = 0;
        grades = {};
        do {
            ex_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc3:st3";
            lname_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc1:st1";
            grade_str = "form1:tabSet1:tabInstr:lp2:tabSet4:tabp:lpProgress:ts1:tab7:lp7:table3:rg3:" + i + ":tc7:st7_field";
            exercise = document.getElementById(ex_str);
            lname = document.getElementById(lname_str);
            grade = document.getElementById(grade_str);
            if (exercise != null) {
                if (grades[lname.innerHTML] === undefined)
                    grades[lname.innerHTML] = {};
                    console.log(lname.innerHTML + ", " + exercise.innerHTML + ", " + grade.innerHTML);
                if (grade.value != null && grade.value != '')
                    grades[lname.innerHTML][exercise.innerHTML] = grade.value;
                else
                    grades[lname.innerHTML][exercise.innerHTML] = "0";
            }
            i++;
        } while (exercise != null);
       // console.log(JSON.stringify(grades));
       // console.log(JSON.stringify(grades).length)
        //window.open("http://aspen2.cscofc.info/jsontocsv.php?data="+JSON.stringify(grades));
        console.log('posting...' + "\n JSON.String... = "+ JSON.stringify(grades));
        livelabtools.canop_open("post", "http://aspen2.cscofc.info/jsontocsv.php", JSON.stringify(grades));        
        console.log('done');
        return "function end";
    }
}

console.log(livelabtools.post_grades());

尋ねられない限り、詳細には触れませんが、注意すべき重要な部分は、return ステートメントとコンソール ログです。ページアクションボタンが最初にクリックされたときにすべてが完全に正常に実行され、終了すると、コンソールに「機能終了」が出力されます。ただし、最初の実行後、ページ アクション ボタンをクリックするたびに、「content_script を呼び出しています」というアラートが表示され、他に何も起こりません。コンテンツ スクリプトが複数回実行されないのはなぜですか?

4

1 に答える 1

2

スクリプトが既に注入されている場合、再度注入されないようです。
そのため、コンテンツ スクリプトにメッセージを渡してアクションを開始する方法があります。(もちろん、コンテンツ スクリプトがまだ挿入されていない場合は、最初に挿入する必要があります。)

私が思いついた解決策の 1 つ (テスト後、正常に動作することを確認した後) は次のとおりです。

  1. バックpageAction.onClickedグラウンド ページからコンテンツ スクリプトにメッセージを送信し、何かを実行するように依頼します (成績の投稿など)。また、バックグラウンド ページに返信するように要求します。
    [ chrome.tabs.sendMessage(...)も参照してください。]

  2. コンテンツ スクリプトが既に挿入されている場合は、メッセージを受信し、バックグラウンド ページに確認を送り返し、何かを実行します (成績の投稿など)。このプロセスは、何度でも実行できます。
    [ chrome.runtime.onMessageも参照してください。]

  3. が初めて起動されたとき、pageAction.onClickedメッセージをリッスンするコンテンツ スクリプトはありません。その場合、メッセージの確認はありません。代わりにchrome.runtime.lastErrorが設定されます。その場合、バックグラウンド ページは最初にコンテンツ スクリプトを挿入してから、メッセージを再度送信する必要があります。
    [ chrome.runtime.lastErrorも参照してください。]


理論的に言えば、それでうまくいくはずです!
実際には、これは私のために働いたサンプルコードです:

manifest.json : (注: アクセスする必要があるページに関してより具体的な要件がある場合は、それらをマニフェストに組み込み、一部のアクセス許可を取り除くことができます。)

{
    ...
    "background": {
        "persistent": false,
        "scripts": ["background.js"]
    },

    "page_action": {
        "default_title": "Test Extension"
    },

    "permissions": [
        "tabs",
        "http://*/*",
        "https://*/*"
    ]
    ...
}

background.js:

function checkForValidURL(tabId, info, tab) {
    var idx = tab.url.indexOf("tiger.armstrong");
    if (idx > 0) {
        chrome.pageAction.show(tabId);
    } else {
        chrome.pageAction.hide(tabId);
    }
}
chrome.tabs.onUpdated.addListener(checkForValidURL);

function onPageActionClicked(tab) {
    // Send message to content script, asking to post grades
    alert("Calling content_script...");
    chrome.tabs.sendMessage(tab.id, { action: "postGrades" }, function() {
        if (chrome.runtime.lastError) {
            // The error indicates that the content script
            // has not been injected yet. Inject it and...
            chrome.tabs.executeScript(tab.id, {
                file: "content.js"
            }, function() {
                if (!chrome.runtime.lastError) {
                    // ...if injected successfully, send the message anew
                    onPageActionClicked(tab);
                }
            });
        } else {
            // The content script called our response callback,
            // confirming that it is there and got our message
            alert("Message got through !");
        }
    });
};
chrome.pageAction.onClicked.addListener(onPageActionClicked);

content.js:

var livelabtools = {
    /**
     * This function is like window.open, but it can POST (rather than GET) from
     * JS source: http://canop.org/blog/?p=426
     */
    canop_open: function (method, url, data, target) {
        var form = document.createElement("form");
        form.action = url;
        form.method = method;
        form.target = target || "_self";

        // 'data' is an object with key-value pairs
        // of fields to be sent
        if (data) {
            for (var key in data) {
                var input = document.createElement("input");
                input.name = key;
                input.value = (typeof(data[key]) === "object")
                        ? JSON.stringify(data[key]) : data[key];
                form.appendChild(input);
            }
        }

        form.submit();
        form.remove();
    },
    post_grades: function () {
        console.log("Posting some grades...");
        livelabtools.canop_open("POST",
                "http://aspen2.cscofc.info/jsontocsv.php", 
                "{}");
        console.log("Grades sent !");
    }
}

// Listen for messages from the background page
// (It actually listens for messages from anyone in the context,
//  but the background page is the one that interrests us)
chrome.runtime.onMessage.addListener(function(msg, sender, response) {
    // If we've been asked to post grades...
    if (msg.action && (msg.action == "postGrades")) {
        // ...confirm we got the message and...
        response();
        // ...do what we do best: post grades !
        livelabtools.post_grades();
    }
});

これがそれをカバーすることを望みましょう:)

于 2013-10-28T17:01:44.197 に答える