1

I'm trying to send some data from a Chrome extension content script to a background script to my local python file. It goes from the content script to the background script fine, but when I try to send it to the python file, I just get "POST http://localhost:5000/bootstrap 400 (BAD REQUEST)." Can't figure out what's going on. I'm new to this. Many thanks!

background.js

// Sending messages from background / event page
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete') {
        chrome.tabs.query({ active: true }, function(tabs) {
            const msg = "Hello from background ";
            chrome.tabs.sendMessage(tabs[0].id, { "message": msg });
        })
    }
});

// Listening to messages page
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log(request);
    var articleData = request
    // Callback for that request



$.ajax({
    type: 'POST',
    url: 'http://localhost:5000/bootstrap',
    data: articleData,
    success: function (newArticle){
       alert('success');
    }
    })


    sendResponse({ message: "Background has received that message " });
});

relevant part of fakenews.py

@app.route('/bootstrap', methods=['GET', 'POST'])
def bootstrap():
    posted = 1
    print ("bootstrap")
    global article
    if request.method == 'POST':
        if not request.form['title'] or not request.form['url'] or not request.form['image_url'] or not request.form['snippet']:
            flash('Please enter all the fields', 'error')
        else:
            article = Article(request.form['title'], request.form['url'], request.form['image_url'],
                               request.form['snippet'])

            db.session.add(article)
            try:
                db.session.commit()
            except exc.SQLAlchemyError:
               flash('Article url already exists, failed to post new article')
               posted = 0
               #return render_template('/error.html', article_url=article.url)

            article_list = Article.query.filter_by(url=article.url)
            if posted == 1:
                flash('Record was successfully added')
            else:
                db.session.rollback()
                article_list = Article.query.filter_by(url=article.url)
                article=article_list[0]

            print ("article.id=" + str(article.id))

            vote_choices = VoteChoice.getVoteChoiceList()

            return render_template('/votefor.html', article_id=article.id,
                                   article_title=article.title,
                                   article_url=article.url, vote_choices=vote_choices
                                   )

relevant part of content.js

chrome.runtime.sendMessage({ message: [title, image, url] }, function(response) {
    console.log(response);
});

// Listening to messages in Context Script
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    console.log(request);
    // Callback
    sendResponse({ message: 'Content script has received that message ⚡' })
})


});

manifest.json

  {
    "manifest_version": 2,
    "name": "OrangeBox",
    "version": "1.0",
    "permissions": ["http://localhost/" ,"tabs"],

    "content_scripts": [
        {
            "matches": ["<all_urls>"],
            "js": ["contentScript.js"]
        }
    ],
    "background": { "scripts": ["jquery-3.4.1.js", "background.js"],  "persistent": false },


    "content_scripts": [
  {
    "matches": [
      "<all_urls>"
    ],
    "js": ["jquery-3.4.1.js", "waitForKeyElements.js", "content.js"]
  }
]

}
codi6
  • 516
  • 1
  • 3
  • 18
  • If you have `http://localhost/` in "permissions" field of manifest.json then it's something in the python code. – wOxxOm Jan 24 '20 at 04:45
  • I do have that in the manifest ... So hm, wonder what it is. The same python code works fine when I submit the information through a form on a webpage I built (though one also on http://localhost, unlike this extension). – codi6 Jan 24 '20 at 05:35
  • Add your manifest.json to the question, maybe there's something else wrong. – wOxxOm Jan 24 '20 at 07:19
  • Added! Thanks for taking a look – codi6 Jan 24 '20 at 16:55
  • The manifest looks fine. Try inspecting the request's body and headers in the [background page devtools](https://stackoverflow.com/a/10258029) network panel. The content script fragment in the question is probably incomplete so I can only guess it may be retrieving incorrect data from the page. – wOxxOm Jan 24 '20 at 17:00
  • It's definitely getting the right data (it logs the right info. in the background console). Although maybe it's in the wrong format? It's in an array, is that the wrong format for the python? – codi6 Jan 24 '20 at 17:05
  • See [Sending array data with jquery and flask](//stackoverflow.com/a/23889195) and also inspect the actual request in devtools network panel. – wOxxOm Jan 24 '20 at 17:16
  • Hm, tried but can't figure it out --- my code looks the same as the example as far as I can tell, but I'm pretty new so I'm probably missing something – codi6 Jan 24 '20 at 23:09

1 Answers1

1

Problem

In content.js you're sending

message: [title, image, url]

The background.js is just passing this on to fakenews.py, and this is where things break...

fakenews.py is expecting a request object that looks like

{
  title: <some time>,
  url: <some url>,
  image_url: <...>,
  snippet: <...>
}

but what it's getting looks like

{
   message: [
     <some title>,
     <some image>,
     <some url>
   ]
}

Fix

The quick fix is changing the content.js line to be

chrome.runtime.sendMessage({"title": title, "image_url": image, "url": url, "snippet": "test"}, function(response) {

Note I'm putting a placeholder for snippet because the backend is expecting a value for it

Alter
  • 3,332
  • 4
  • 31
  • 56