Refused to frame 'https://api.xxx.jp/' because it violates the following Content Security Policy directive: "frame-src 'self'

Josimar Lopes picture Josimar Lopes · Jan 24, 2018 · Viewed 12.6k times · Source

Here we go: I am new to google's chrome extension development, so please bear with me.

I have an extension which is giving me the following error:

Refused to frame 'https://api.xxx.jp/' because it violates the following Content Security Policy directive: "frame-src 'self' https://staticxx.facebook.com https://twitter.com https://*.twimg.com https://5415703.fls.doubleclick.net https://player.vimeo.com https://pay.twitter.com https://www.facebook.com https://ton.twitter.com https://syndication.twitter.com https://vine.co twitter: https://www.youtube.com https://platform.twitter.com https://upload.twitter.com https://s-static.ak.facebook.com https://4337974.fls.doubleclick.net https://8122179.fls.doubleclick.net https://donate.twitter.com".

My manifest.json file has the following settings regarding Content Security Policy:

{
   "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'",
   "manifest_version": 2,
}

In my content.js file, I'm calling an api through inside an iframe tag:

<iframe src="'+url+'" name="xxxExtensionsFrame" width="380" height="' + (heightBase - 5) + '" border="0" frameborder="0" scrolling="no"></iframe>

The api's url is always in https form.

  • This extension works for most websites but in some websites like https://twitter.com/?lang=en, it displays a gray pop up box with the error message described above.

Gray pop up box Please help me find the solution to this issue.

Here is an example of my extension at work:

Any help is welcome.

Answer

Usama Ejaz picture Usama Ejaz · Mar 6, 2018

Twitter uses Content-Security-Policy header. The only solution to your problem is to modify response headers using the chrome.webRequest API in your background script.

Here is an example:

chrome.webRequest.onHeadersReceived.addListener(info => {
    const headers = info.responseHeaders; // original headers
    for (let i=headers.length-1; i>=0; --i) {
        let header = headers[i].name.toLowerCase();
        if (header === "content-security-policy") { // csp header is found
            // modify frame-src here
            headers[i].value = headers[i].value.replace("frame-src", "frame-src https://domain-you-want-to-iframe.com/");
        }
    }
    // return modified headers
    return {responseHeaders: headers};
}, {
    urls: [ "<all_urls>" ], // match all pages
    types: [ "sub_frame" ] // for framing only
}, ["blocking", "responseHeaders"]);

Example is extracted from my blog post here.