Chrome Extension - Injected Iframe not accessing C

2019-04-14 04:57发布

I have a chrome extension that toggles a sidebar with the browser action click. The sidebar contains an iframe with a local (chrome extension) source. I thought the page within the iframe would be considered a local chrome extension file with open access to the chrome APIs and etc. However, I keep getting the following errors in the web console:

Uncaught TypeError: Cannot read property 'onClicked' of undefined <-- background.js

TypeError: Cannot read property 'query' of undefined <-- sidebar.js

How do I get it so that the iframe injected with a context script has access to the local chrome environment?

Code below:

sidebar.js:

var myApp = angular.module('PlaceMates', []);


myApp.service('pageInfoService', function() {
    this.getInfo = function(callback) {
        var model = {};

        chrome.tabs.query({
            'active': true,               // Select active tabs
            lastFocusedWindow: true     // In the current window
        },
        function (tabs) {
            if (tabs.length > 0)
            {
                model.title = tabs[0].title;
                model.url = tabs[0].url;

                chrome.tabs.sendMessage(tabs[0].id, { 'action': 'PageInfo' }, function (response) {
                    model.pageInfos = response;
                    console.log("popup js: " + model.pageInfos);
                    callback(model);
                });
            }

        });
    };
});

myApp.controller("PageController", function ($scope, pageInfoService) {
    $scope.message = "This extension identifies the photos on this page!";

    pageInfoService.getInfo(function (info) {
        $scope.title = info.title;
        $scope.url = info.url;
        $scope.pageInfos = info.pageInfos;
        $scope.place_name = info.place_name;
        $scope.$apply();
    });
});

background.js

console.log( 'Background.html starting!' );

// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
    // No tabs or host permissions needed!
    console.log('Toggling sidebar on ' + tab.url);

    // send message to current tab when clicked
    var tabId = tab.id;
    console.log("tab.id: " + tabId);
    chrome.tabs.query({active: true, currentWindow: true}, function(tab) {

        chrome.tabs.sendMessage(
            //Selected tab id
            tabId,
            //Params inside a object data
            {callFunction: "toggleSidebar"}, 
            //Optional callback function
            function(response) {
                console.log(response);
            }
        );
    });


    console.log('Done toggling sidebar!');

});

chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    if(request.cmd == "read_file") {
        $.ajax({
            url: chrome.extension.getURL("sidebar.html"),
            dataType: "html",
            success: sendResponse
        });
    }
})

chrome.runtime.onMessage.addListener(
    function(msg, sender, sendResponse) {
        console.log(sender.tab ?
                    "from a content script:" + sender.tab.url :
                    "from the extension");
        if (msg.command == "read_info"){
            console.log(JSON.parse(JSON.stringify(msg.myInfo)));
            sendResponse({command: "done"});
        }
    }
);

console.log( 'Background.html done.' );

1条回答
ゆ 、 Hurt°
2楼-- · 2019-04-14 05:08

The only pages that have access to all chrome.* extension API are pages that are run at the extension's origin and within the Chrome extension process.

When an extension page is embedded in an iframe, its extension runtime is equivalent to a content script: The page can only use cross-origin XMLHttpRequest and some of the extension APIs (messaging and some other methods in the chrome.runtime / chrome.extension namespace).

If you wish to make the functionality of the other Chrome APIs available to your iframe, then you have to call these APIs from the background page, and use the messaging API to proxy requests from the iframe to the background page and back. Luckily, most of the Chrome extension API is asynchronous by design, so it will not be difficult to change your code to use these proxies.

查看更多
登录 后发表回答