简体   繁体   中英

Creating a JSONP Callback From Safari Extension

I'm trying to load some data from Reddit via a Safari extension. I'm using a JSONP pattern to create the callback function and attach the new src to the script. However, it looks like there are two window namespaces, and the function that I dynamically create is not available to the context of the dynamically added script.

This link seems to detail the problem for chrome, which I'm guessing is similar to mine in Safari.

JSONP request in chrome extension, callback function doesn't exist?

Here's the code (works outside of extension):

function jsonp(url, callback) {
    var callbackName = 'jsonp_callback_' + Math.round(100000 * Math.random());
    window[callbackName] = function(data) {
        delete window[callbackName];
        callback(data);
    };
    console.log('about to create script');
    var script = document.createElement('script');
    script.src = url + (url.indexOf('?') >= 0 ? '&' : '?') + 'jsonp=' + callbackName;
    document.body.appendChild(script);
    console.log('script should be appended');
}


function getImages(){
    jsonp('http://www.reddit.com/r/cats/.json', function(data) {
        data.data.children.forEach(function(el){
            console.log(el.data.url);
        });
    });    
}

Any ideas, work arounds?

Thanks!

You're right about there being two namespaces in the same window. Injected scripts cannot access a web page's globals, and vice versa. When you initiate JSONP in an injected script, the script of the inserted <script> tag runs in the web page's namespace.

I know of two ways to work around this limitation in a Safari extension.

The probably better way is to use your extension's global page to communicate with the external API through standard XHR or jQuery Ajax methods (which are supported in global page scripts) and use messages to pass the fetched data to an injected script.

The other way is to go ahead and use JSONP from the injected script, but have the JSONP callback function add the fetched data to the page's DOM, which is accessible by the injected script. For example, you could put the data in a hidden <pre> element and then use the element's innerHTML property to retrieve it. Of course, this technique does make the content visible to the page's own scripts, so exercise caution.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM