Chrome扩展程序未单击每次运行页面操作按钮

时间:2013-10-24 01:50:18

标签: javascript google-chrome google-chrome-extension

我正在创建一个扩展程序,我需要能够在单击页面操作按钮时多次运行内容脚本。我在我的background.js中有这个:

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

这是第一次单击按钮时有效。当第二次点击时,我得到我的弹出窗口“调用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”的警报,而没有其他任何事情发生。为什么我的内容脚本不会多次运行?

1 个答案:

答案 0 :(得分:2)

似乎已经注入了一个脚本,它不再被注入 因此,可行的方法是通过将消息传递给内容脚本来启动您的操作。 (当然,如果尚未注入内容脚本,则需要先注入它。)

我提出的一个解决方案(经过测试证实它工作正常)如下:

  1. pageAction.onClicked上,从背景页面向内容脚本发送消息,要求其执行某些操作(例如,发布成绩)。另外,请求将回复发送回背景页面 [另见 chrome.tabs.sendMessage(...) 。]

  2. 如果已经注入了内容脚本,请让它收到消息,将确认信息发送回后台页面并继续执行某些操作(例如发布成绩)。这个过程可以根据需要进行多次 [另见 chrome.runtime.onMessage 。]

  3. 第一次触发pageAction.onClicked时,将没有内容脚本侦听消息。在这种情况下,将不会有消息确认。而是设置 chrome.runtime.lastError 。在这种情况下,后台页面必须首先注入内容脚本,然后再次发送消息 [另见 chrome.runtime.lastError 。]


  4. 理论上说,应该这样做! 实际上,这是适用于我的示例代码:

    <强>的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();
        }
    });
    

    让我们希望这涵盖它:)