3

Working on a Youtube extension and will like to bring some of it into Facebook,
I'm able to modify the Youtube iframe inside Facebook posts, but the issue is that it's modify it in every site and not only on Facebook.
So I would like to know how can I set the specific parent window please?

I hope there is a way to set it simply in the manifest file,
otherwise I can just use JS to check for location.href as in Facebook it returns:

https://s-static.ak.facebook.com/common/referer_frame.php

Currently in my manifest file:

"content_scripts": [
    {
        "matches": [
            "*://*.facebook.com/*",
            "*://*.youtube.com/embed/*"
        ],
        "css": ["styles/facebook.css"],
        "all_frames": true
    }
]
Gil Goldshlager
  • 651
  • 1
  • 8
  • 22

2 Answers2

3

You can easily find the domain of the parent frame via location.ancestorOrigins, even across different domains. E.g, use the following manifest file:

"content_scripts": [{
    "matches": [
        "*://*.youtube.com/embed/*"
    ],
    "js": ["js/facebook.js"],
    "all_frames": true
}],
"web_accessible_resources": ["styles/facebook.css"],

and the following JS:

// Note: parentOrigin could be `undefined` in the top-level frame.
var parentOrigin = location.ancestorOrigins[0];

if (parentOrigin === 'https://facebook.com' ||
    parentOrigin === 'http://facebook.com') {

    var style = document.createElement('link');
    style.rel = 'stylesheet';
    // NOTE: This only works because the file is declared at the
    // web_accessible_resources list in manifest.json
    style.href = chrome.runtime.getURL('styles/facebook.css');
    (document.head || document.documentElement).appendChild(style);
}

If the YouTube video is embedded via the Iframe API, you could also try to insert the style in the frame by matching the URL. E.g., without any JavaScript, the style can be loaded in the YouTube frame using:

"content_scripts": [{
    "matches": [
        "*://*.youtube.com/embed/*origin=https://facebook.com/*",
        "*://*.youtube.com/embed/*origin=http://facebook.com/*"
    ],
    "css": ["styles/facebook.css"],
    "all_frames": true
}]
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Thanks the JS works good, unfortunately the manifest ver isn't but it is great to know about that "origin" thing. In my JS I'm using `location.ancestorOrigins[0].indexOf('facebook.com')` as it shorter but is it any good? – Gil Goldshlager Apr 14 '15 at 10:50
  • 1
    @GilGoldshlager Your change is not great, because 1) If the code is executed in the top-level frame, it will fail, because `location.ancestorOrigins[0] === undefined`. 2) It also matches non-Facebook sites, such as `http://thisisnotfacebook.com`. If you prefer a shorter notation, you could use a Regex: `if (/^https?:\/\/facebook\.com$/.test(location.ancestorOrigins[0])) { ... }`. – Rob W Apr 14 '15 at 10:52
  • Thanks, I probably will never know how to read Regex LOL! (must learn and remember the syntax already one day) but this one is simple, and for anyone else there is also `www.` in what `location.ancestorOrigins[0]` returns so you need to add it otherwise it will fail. – Gil Goldshlager Apr 14 '15 at 11:07
0

If you inject a content script both into the iframe and the parent frame, you can (using the background page as a message "router") ask the outer script.

Of use: content scripts can learn their place in the frame hierarchy.

So, the logic would be:

  1. Youtube content script checks its hierarchy, obtaining its "index" on the tree, and computes the index of its parent.
  2. CS messages the background with the index of its parent, requesting a check.
  3. Background page gets the tab ID from the message, and messages all frames in the target tab with the request and parent index.
  4. All content scripts that receive the message check their index. If it matches the parent frame, the content script checks its URL and reports back.
  5. The background page routes the answer back to the original content script.

Tell me if you need help with any of those steps.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206
  • That sounds unnecessarily complex. Did you know that you can simply get the origin of any parent frame using `location.ancestorOrigins`? E.g. `location.ancestorOrigins[0]` could be `https://facebook.com` . – Rob W Apr 14 '15 at 10:22
  • Obviously, I did not. Please make that into an answer. – Xan Apr 14 '15 at 10:23