2

EDIT: I have added the response from OMDB

{Response: "False", Error: "Invalid API key!"}
Error: "Invalid API key!"
Response: "False"

I am new to web development and I am trying to build a chrome extension that displays imdb scores on netflix. I am using the OMDB API to do this. At first I got the following error:

"Mixed Content: The page at '' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint ''. This request has been blocked; the content must be served over HTTPS.",

however I just changed the "http" in the url to "https" and it went away. However, now I am getting a 401 error, which I think means my access is being denied. This is a picture of the full error

Here is the code for the extension

Manifest file:

{
  "manifest_version": 2,
  "name": "1_ratings_netflix",
  "version": "0.1",
  "description": "Display imdb ratings on netflix",
  "content_scripts": [
  {
    "matches": [
      "https://www.netflix.com/*", "https://www.omdbapi.com/*"
    ],
    "js": ["content.js"]
  }
  ],
  "icons": { "16": "icon16.png", "48":"icon48.png"},
  "permissions": [
    "https://www.netflix.com/*", "https://www.omdbapi.com/*"
  ]
}

Content File:

    function fetchMovieNameYear() {
    var synopsis = document.querySelectorAll('.jawBone .jawbone-title-link');
    if (synopsis === null) {
        return;
    }

    var logoElement = document.querySelectorAll('.jawBone .jawbone-title-link .title');

    if (logoElement.length === 0)
        return;

    logoElement = logoElement[logoElement.length - 1];

    var title = logoElement.textContent;

    if (title === "")
        title = logoElement.querySelector(".logo").getAttribute("alt");

    var titleElement = document.querySelectorAll('.jawBone .jawbone-title-link .title .text').textContent;

    var yearElement = document.querySelectorAll('.jawBone .jawbone-overview-info .meta .year');
    if (yearElement.length === 0)
        return;
    var year = yearElement[yearElement.length - 1].textContent;

    var divId = getDivId(title, year);
    var divEl = document.getElementById(divId);
    if (divEl && (divEl.offsetWidth || divEl.offsetHeight || divEl.getClientRects().length)) {
        return;
    }

    var existingImdbRating = window.sessionStorage.getItem(title + ":" + year);
    if ((existingImdbRating !== "undefined") && (existingImdbRating !== null)) {
        addIMDBRating(existingImdbRating, title, year);
    } else {
        makeRequestAndAddRating(title, year)
    }
};

function addIMDBRating(imdbMetaData, name, year) {
    var divId = getDivId(name, year);

    var divEl = document.getElementById(divId);
    if (divEl && (divEl.offsetWidth || divEl.offsetHeight || divEl.getClientRects().length)) {
        return;
    }

    var synopsises = document.querySelectorAll('.jawBone .synopsis');
    if (synopsises.length) {
        var synopsis = synopsises[synopsises.length - 1];
        var div = document.createElement('div');

        var imdbRatingPresent = imdbMetaData && (imdbMetaData !== 'undefined') && (imdbMetaData !== "N/A");
        var imdbVoteCount = null;
        var imdbRating = null;
        var imdbId = null;
        if (imdbRatingPresent) {
            var imdbMetaDataArr = imdbMetaData.split(":");
            imdbRating = imdbMetaDataArr[0];
            imdbVoteCount = imdbMetaDataArr[1];
            imdbId = imdbMetaDataArr[2];
        }
        var imdbHtml = 'IMDb rating : ' + (imdbRatingPresent ? imdbRating : "N/A") + (imdbVoteCount ? ", Vote Count : " + imdbVoteCount : "");

        if (imdbId !== null) {
            imdbHtml = "<a target='_blank' href='https://www.imdb.com/title/" + imdbId + "'>" + imdbHtml + "</a>";
        }

        div.innerHTML = imdbHtml;
        div.className = 'imdbRating';
        div.id = divId;
        synopsis.parentNode.insertBefore(div, synopsis);
    }
}

function getDivId(name, year) {
    name = name.replace(/[^a-z0-9\s]/gi, '');
    name = name.replace(/ /g, '');
    return "aaa" + name + "_" + year;
}

function makeRequestAndAddRating(name, year) {

    var url = "https://www.omdbapi.com/?i=tt3896198&apikey=**{API_KEY}**" + encodeURI(name)
        + "&y=" + year + "tomatoes=true";

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url);
    xhr.withCredentials = true;
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.onload = function () {
        if (xhr.status === 200) {
            var apiResponse = JSON.parse(xhr.responseText);
            var imdbRating = apiResponse["imdbRating"];
            var imdbVoteCount = apiResponse["imdbVotes"];
            var imdbId = apiResponse["imdbID"];
            var imdbMetaData = imdbRating + ":" + imdbVoteCount + ":" + imdbId;
            window.sessionStorage.setItem(name + ":" + year, imdbMetaData);
            window.sessionStorage.setItem("metaScore:" + name + ":" + year, metaScore)
            window.sessionStorage.setItem("rotten:" + name + ":" + year, rottenRating);
            addIMDBRating(imdbMetaData, name, year);
            addRottenRating(rottenRating, name, year);
            addMetaScore(metaScore, name, year);
        }
    };
    xhr.send();
}

if (window.sessionStorage !== "undefined") {
    var target = document.body;
    // create an observer instance
    var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
            window.setTimeout(fetchMovieNameYear, 5);
        });
    });
    // configuration of the observer:
    var config = {
        attributes: true,
        childList: true,
        characterData: true
    };
    observer.observe(target, config);
}
BrownBoii333
  • 85
  • 1
  • 8
  • Modern Chrome disallows cross-origin requests in content scripts. Do it in the [background script](https://developer.chrome.com/extensions/background_pages) and use messaging for communication with the content script if necessary. – wOxxOm May 10 '20 at 18:45
  • Sorry, but in my manifest I have asked for permissions on netflix and omdbapi, so shouldn't that be enough to circumvent this? https://developer.chrome.com/extensions/xhr says that google disallows it unless you request permission. – BrownBoii333 May 10 '20 at 19:54
  • As you can see in the first paragraph of that article, content scripts have been subject to CORB since Chrome 73 and CORS since Chrome 83. So even if your code works now it'll break soon. – wOxxOm May 11 '20 at 04:18
  • So then doing the requests in the background script will fix this? I am confused by this a little, because my understanding of background scripts is that they are used when you need something to happen always, outside of the webpage. So I would need to be constantly sending requests to the api with the background script? – BrownBoii333 May 11 '20 at 15:35
  • Only for cross-origin requests. And the background script doesn't have to run at all times, it's loaded on demand using a message, see examples in the official [CORB explainer](https://www.chromium.org/Home/chromium-security/extension-content-script-fetches). – wOxxOm May 11 '20 at 15:38

1 Answers1

1

It would be helpful for you to post the request and response for OMDB (you can find them in the "Network" tab in dev tools).

One thing that triggers CORS (cross-origin requests) errors is specifying a content type other than application/x-www-form-urlencoded, multipart/form-data or text/plain. If I recall correctly, the OMDB API will return a JSON response even without specifying the content type of the request, so you should try removing the line:

xhr.setRequestHeader('Content-Type', 'application/json');

More on "Simple Requests" which do not trigger CORS: https://javascript.info/fetch-crossorigin#simple-requests

You also need to get an API key (https://www.omdbapi.com/apikey.aspx) and replace **{API_KEY}** in your code with the key. You also need to add the t key to your querystring or the title will be appended to your API key.

var url = "https://www.omdbapi.com/?i=tt3896198&apikey=**{API_KEY}**" + "&t="
 + encodeURI(name) + "&y=" + year + "tomatoes=true";
Ed Lucas
  • 5,955
  • 4
  • 30
  • 42
  • Thanks for the reply! I posted an edit and wrote the response in the Network tab. Please let me know if I didn't post what you meant. Also I removed that line and still get the same error – BrownBoii333 May 10 '20 at 21:36
  • Looks like you also need to add your API key to the URL in your request. I've added some links to my answer above that should help. – Ed Lucas May 10 '20 at 21:43
  • 1
    I do have an API Key, I used that link and received one in the email. It was originally included in the post but an answer-er suggested I remove it. also, when I go to this link "http://www.omdbapi.com/?apikey=[yourkey]", but i replaces yourkey with my API key I get : {"Response":"False","Error":"Something went wrong."} as opposed to what I was getting before, or if I don't put in an API Key: {"Response":"False","Error":"Invalid API key!"} – BrownBoii333 May 10 '20 at 21:47
  • Your URL is also missing the `&t=` to correctly pass the title. Without it, the title is being appended to your API key. – Ed Lucas May 10 '20 at 21:52
  • That Worked! no more 401 error. However now I get this error: content.js:99 Uncaught ReferenceError: metaScore is not defined at XMLHttpRequest.xhr.onload (content.js:99) – BrownBoii333 May 10 '20 at 21:59
  • It looks like you're not defining the variable `metaScore` like you are the others. Probably needs something like `var metaScore = apiResponse["metaScore"];` before you write it to session storage. – Ed Lucas May 10 '20 at 22:03
  • That helped! thanks. I am getting some odd errors and a warning, that don't seem to affect the functionality but what do they mean? Chrome says "Unchecked runtime.lastError: The message port closed before a response was received." and it says this 1600 times... I also get the following warning "0998491?jbv=80092926&jbp=2&jbr=0:1 A cookie associated with a cross-site resource at http://omdbapi.com/ was set without the `SameSite` attribute. A future release of Chrome will only deliver cookies with cross-site requests if they are set with `SameSite=None` and `Secure`. – BrownBoii333 May 10 '20 at 22:16
  • Content-Type', 'application/json' Worked! :D – Maz341 Jan 20 '21 at 07:42