运行tabs.executeScript时未经检查的runtime.lastError?

时间:2014-10-22 22:10:37

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

我设法构建了Ripple Emulator开源(https://github.com/apache/incubator-ripple)。

我根据说明(Jake版本)构建了它,它创建了Chrome扩展程序目标,允许我根据https://github.com/apache/incubator-ripple/blob/master/doc/chrome_extension.md的内置Chrome扩展程序测试我的网络应用程序。

我成功地将解压缩的扩展程序加载到chrome上,但是当我启用它时没有任何反应,虽然页面重新加载扩展程序不起作用,而是我得到2个错误:

  1. 未捕获的ReferenceError:未定义webkitNotifications

    webkitNotifications.createHTMLNotification('/views/update.html').show();
    
  2. 运行tabs.executeScript时未经检查的runtime.lastError:无法访问chrome:// URL

    chrome.tabs.executeScript(tabId, {
    
  3. 如何解决这个问题?


    完整的background.js:

    if (!window.tinyHippos) {
    window.tinyHippos = {};
    }
    
    tinyHippos.Background = (function () {
    var _wasJustInstalled = false,
        _self;
    
    function isLocalRequest(uri) {
        return !!uri.match(/^https?:\/\/(127\.0\.0\.1|localhost)|^file:\/\//);
    }
    
    function initialize() {
        // check version info for showing welcome/update views
        var version = window.localStorage["ripple-version"],
            xhr = new window.XMLHttpRequest(),
            userAgent,
            requestUri = chrome.extension.getURL("manifest.json");
    
        _self.bindContextMenu();
    
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                var manifest = JSON.parse(xhr.responseText),
                    currentVersion = manifest.version;
    
                if (!version) {
                    _wasJustInstalled = true;
                }
    
                if (version !== currentVersion) {
                    webkitNotifications.createHTMLNotification('/views/update.html').show();
                }
    
                window.localStorage["ripple-version"] = currentVersion;
            }
        };
    
        xhr.open("GET", requestUri, true);
    
        xhr.send();
    
        chrome.extension.onRequest.addListener(function (request, sender, sendResponse) {
            switch (request.action) {
            case "isEnabled":
                console.log("isEnabled? ==> " + request.tabURL);
                sendResponse({"enabled": tinyHippos.Background.isEnabled(request.tabURL)});
                break;
            case "enable":
                console.log("enabling ==> " + request.tabURL);
                tinyHippos.Background.enable();
                sendResponse();
                break;
            case "version":
                sendResponse({"version": version});
                break;
            case "xhr":
                var xhr = new XMLHttpRequest(),
                    postData = new FormData(),
                    data = JSON.parse(request.data);
    
                console.log("xhr ==> " + data.url);
    
                $.ajax({
                    type: data.method,
                    url: data.url,
                    async: true,
                    data: data.data,
                    success: function (data, status) {
                        sendResponse({
                            code: 200,
                            data: data
                        });
                    },
                    error: function (xhr, status, errorMessage) {
                        sendResponse({
                            code: xhr.status,
                            data: status
                        });
                    }
                });
                break;
            case "userAgent":
            case "lag":
            case "network":
                // methods to be implemented at a later date
                break;
            default:
                throw {name: "MethodNotImplemented", message: "Requested action is not supported!"};
                break;
            };
        });
    
        chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
            if (tinyHippos.Background.isEnabled(tab.url)) {
                chrome.tabs.executeScript(tabId, {
                    code: "rippleExtensionId = '" + chrome.extension.getURL('') + "';",
                    allFrames: false
                }, function () {
                    chrome.tabs.executeScript(tabId, {
                        file: "bootstrap.js",
                        allFrames: false
                    });
                });
            }
        });
    }
    
    function _getEnabledURIs() {
        var parsed = localStorage["tinyhippos-enabled-uri"];
        return parsed ? JSON.parse(parsed) : {};
    }
    
    function _persistEnabled(url) {
        var jsonObject = _getEnabledURIs();
        jsonObject[url.replace(/.[^\/]*$/, "")] = "widget";
        localStorage["tinyhippos-enabled-uri"] = JSON.stringify(jsonObject);
    }
    
    _self = {
        metaData: function () {
            return {
                justInstalled: _wasJustInstalled,
                version: window.localStorage["ripple-version"]
            };
        },
    
        bindContextMenu: function () {
            var id = chrome.contextMenus.create({
                "type": "normal",
                "title": "Emulator"
            });
    
            // TODO: hack for now (since opened tab is assumed to be page context was called from
            // eventually will be able to pass in data.pageUrl to enable/disable when persistence     refactor is done
            chrome.contextMenus.create({
                "type": "normal",
                "title": "Enable",
                "contexts": ["page"],
                "parentId": id,
                "onclick": function (data) {
                        _self.enable();
                    }
            });
    
            chrome.contextMenus.create({
                "type": "normal",
                "title": "Disable",
                "contexts": ["page"],
                "parentId": id,
                "onclick": function (data) {
                        _self.disable();
                    }
            });
        },
    
        enable: function () {
            chrome.tabs.getSelected(null, function (tab) {
                console.log("enable ==> " + tab.url);
                _persistEnabled(tab.url);
                chrome.tabs.sendRequest(tab.id, {"action": "enable", "mode": "widget", "tabURL": tab.url });
            });
        },
    
        disable: function () {
            chrome.tabs.getSelected(null, function (tab) {
                console.log("disable ==> " + tab.url);
    
                var jsonObject = _getEnabledURIs(),
                    url = tab.url;
    
                while (url && url.length > 0) {
                    url = url.replace(/.[^\/]*$/, "");
                    if (jsonObject[url]) {
                        delete jsonObject[url];
                        break;
                    }
                }
    
                localStorage["tinyhippos-enabled-uri"] = JSON.stringify(jsonObject);
    
                chrome.tabs.sendRequest(tab.id, {"action": "disable", "tabURL": tab.url });
            });
        },
    
        isEnabled: function (url, enabledURIs) {
            if (url.match(/enableripple=/i)) {
                _persistEnabled(url);
                return true;
            }
    
                // HACK: I'm sure there's a WAY better way to do this regex
            if ((url.match(/^file:\/\/\//) && url.match(/\/+$/)) || url.match(/(.*?)\.        (jpg|jpeg|png|gif|css|js)$/)) {
                return false;
            }
    
            enabledURIs = enabledURIs || _getEnabledURIs();
    
            if (url.length === 0) {
                return false;
            }
            else if (enabledURIs[url]) {
                return true;
            }
    
              return tinyHippos.Background.isEnabled(url.replace(/.[^\/]*$/, ""), enabledURIs);
        }
       };
    
        initialize();
    
        return _self;
    }());
    

    完整的manifest.json:

    {
    "version": "1",
    "manifest_version": 2,
    "name": "Ripple Emulator (Beta)",
    "background": {
        "page": "views/background.html"
    },
    "web_accessible_resources": [],
    "icons":{
        "16":"images/Icon_16x16.png",
        "128":"images/Icon_128x128.png",
        "48":"images/Icon_48x48.png"
    },
    "browser_action":{
        "default_popup":"views/popup.html",
        "default_icon":"images/Icon_48x48.png",
        "default_title":"Ripple"
    },
    "content_scripts":[{
        "run_at": "document_start",
        "js": ["controllers/Insertion.js"],
        "matches": ["http://*/*","https://*/*","file://*"]
    },
    {
        "run_at": "document_start",
        "js": ["controllers/frame.js"],
        "matches": ["http://*/*","https://*/*","file://*"],
        "all_frames": true
    }],
    "permissions": ["tabs", "unlimitedStorage", "notifications", "contextMenus", "webRequest", "<all_urls>"],
    "description": "A browser based html5 mobile application development and testing tool"
    }
    

2 个答案:

答案 0 :(得分:7)

通过在回调中“读取”来“检查”runtime.lastError

<小时/>

代码

chrome.tabs.executeScript(tabId, {
  //..
}, _=>chrome.runtime.lastError /* "check" error */)

例如

通过..显示它。

chrome.tabs.executeScript(tabId, {
  //..
}, _=>{
  let e = chrome.runtime.lastError;
  if(e !== undefined){
    console.log(tabId, _, e);
  }
});

答案 1 :(得分:2)

这两个错误都很好地解释了这个问题:

&#34; webkitNotifications未定义&#34; - 这是因为webkitNotifications已被删除。我找到Chrome webkitNotification not found : api missing来解释发生了什么。

&#34;无法访问chrome:// URL&#34; - 您必须尝试在chrome:// URL(如chrome:// settings,chrome:// extensions)上执行脚本,这是非法的。为了避免像这样的错误打印,你也可以 - 检查chrome.runtime.lastError - 确保不要注入chrome:// pages。