简体   繁体   中英

Chrome Extension: Changing html of a chrome popup window

I have made a Chrome extension to generate a summary of any document.I added the feature of opening the popup using the browser action icon, and now I want to add the same functionality using a context menu right-click action.

Now, when the popup2.html is opened using windows.create() , the window opens as it is and no message is sent to the popup.js script and in turn the innerHtml of the popup window which I opened in the background.js script is not modified.

I tried to use the chrome.tabs.sendMessage method to send a message to the popup window but am not able to change its html there.

background.js

chrome.runtime.onInstalled.addListener(function() {
  var context = "selection";
  var title = "See the Gist";
  var id = chrome.contextMenus.create({"title": title, "contexts":[context],"id": "context_selection"});  
});

var open_window_ids=[]

function getSummary(selected) {

    var jsonData;

    $.ajax({
        url: 'http://127.0.0.1:5000/api/summarize',
        type: 'POST',
        data: JSON.stringify(selected),
        contentType: 'application/json; charset=utf-8',
        dataType: 'json',
        async: false,
        success: function(data) {
            jsonData = data;
        }
    });

    return jsonData;
}

console.log("Booting");

chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {

    var activeTab = tabs[0];
    chrome.tabs.sendMessage(activeTab.id, {"message": "get_selected_text"}, function(response) {
        console.log('From button');
        if (response.selected_text == "") {
            document.body.innerHTML += "<h3 style='text-align: center'>No text selected! Select text and try again.</h3>";
        }
        else {
            var apiResponse = getSummary(response);
            console.log(apiResponse);
            if (!apiResponse)
            {
                document.getElementById("header").innerHTML += "<h3 class='heading'>API response unavailable.</h3>";
            }
            var summary_final = apiResponse.sentences;
            if (summary_final.length == 0) {
                document.getElementById("header").innerHTML += "<h3 class='heading'>Not enough text selected to generate summary. Select larger block of text and try again.</h3>";
                document.getElementById("footer").innerHTML += "<div style='padding:15px;'>Powered by <a href='http://zippybots.com' target='_blank'><span id='link'>Zippybots</span></a></div>";
            }
            else{
                document.getElementById("header").innerHTML += "<h1 class='heading'>The Gist is.....</h1>";
                var para = "";
                for (var i = 0;i<summary_final.length;i++)
                {
                    para += summary_final[i]+" ";
                    if( i % 3 == 2) 
                    {
                        document.getElementById("summary").innerHTML += "<p class='point'>"+para+"</p>";    
                        para = "";
                    }
                }
                if (para) document.getElementById("summary").innerHTML += "<p class='point'>"+para+"</p>";
                document.getElementById("footer").innerHTML += "<div style='padding:15px;'>Powered by <a href='http://zippybots.com' target='_blank'><span id='link'>Zippybots</span></a></div>";
            }
        }
    });
});


chrome.contextMenus.onClicked.addListener(function(info, tab){
    if (info.menuItemId == "context_selection") {
        for (var i = open_window_ids.length - 1; i >= 0; i--) {
            chrome.windows.remove(open_window_ids[i],function(){});
            open_window_ids.pop();
        }   
            // window.document.body.innerHTML += doc;
        var activeTab;
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            activeTab = tabs[0];
            chrome.windows.create({url: 'popup2.html',focused:true,type:'popup'},function(win){
                open_window_ids.push(win.id);
                displayCurrent(open_window_ids[0],activeTab.id,win);
            });
        });
    }
});

function displayCurrent(id,activeTabId,popupwindow){
    console.log("Got selection tab id :"+activeTabId);
    var popupTabId = popupwindow.tabs[0].id;
    console.log("Got popup tab id :"+popupTabId);

    chrome.tabs.sendMessage(activeTabId, {"message": "get_selected_text"}, function(response) {

        console.log("Resp:"+response.selected_text);
        if (response.selected_text == "") {
            console.log("Selected text is null");
            chrome.tabs.sendMessage(popupTabId,{"message":"no_text_selected"},function (response){});
        }
        else {
            var apiResponse = getSummary(response);
            if (!apiResponse)
            {
                document.getElementById("header").innerHTML += "<h3 class='heading'>API response unavailable.</h3>";
            }
            var summary_final = apiResponse.sentences;
            if (summary_final.length == 0) {
                console.log("Summary length 0");
                chrome.tabs.sendMessage(popupTabId,{"message":"not_enough_text"},function (response){});
            }
            else {
                console.log("Summary there");
                chrome.tabs.sendMessage(popupTabId,{"message":"summary","data":summary_final},function (response){});   
            }
        }   
    });
}

popup2.html

<html>
    <head>
        <meta charset="utf-8">
        <link href="bootstrap.min.css" rel="stylesheet">
        <script src="jquery-3.1.1.min.js"></script>
        <script src="bootstrap.min.js"></script>
        <!-- <script src="api-keys.js"/></script> -->
        <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
        <script type="text/javascript" src="popup.js"></script>
        <script type="text/javascript" src="background.js"></script>
        <style>
            body{
                min-width: 750px;
                font-family: 'Ubuntu', sans-serif;
                background: #f1f1f1;
                /*background: #2c001e;*/
            }
            #header{
                /*background: #dd4814;*/
                background: #2c001e;
                /*color: #dd4814;*/
                color: #fff;
                text-align: center;
                padding: 1px;
            }
            #footer{
                /*background: #dd4814;*/
                background: #2c001e;
                color: #fff;
                text-align: right;
                min-height: 50px; 
            }
            #link{
                /*color: #fff;              */
                color: #dd4814;
            }
            .point{
                color: #333;                
                /*background: #2c001e;*/
                background: #f1f1f1;
                text-align: justify;
                padding: 5px;
            }
            #summary{
                background: #f1f1f1;
                /*background: #2c001e;*/
                max-width: 720px;
                font-weight: 300;   
                font-size:15px;
                font-family: Ubuntu, Arial, "libra sans", sans-serif;
                padding-left: 30px;
            }
            .heading{
                margin-top: 10px;
                margin-bottom: 10px;
            }
        </style>
    </head>
    <body>
            <div id="header"></div>
            <!-- This will be populated when extension button is clicked -->
            <div id="summary"><br></div>
            <div id="footer">

            </div>
    </body>
</html>

content.js

console.log("Content file loaded");
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
    if (request.message == "get_selected_text") {
        var selectedText = document.getSelection().toString();
        sendResponse({selected_text: selectedText});
        return true;
    }
});

manifest.json

{
  "manifest_version": 2,
  "name": "Selection Summarizer",
  "description": "A chrome extension that allows users to get a summary of a news article or large block of text.",
  "version": "1.0",
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],

      "js": ["jquery-3.1.1.min.js", "content.js","popup.js"]

    }
  ],

  "background": {
        "scripts": ["background.js"],
        "persistent" :false
    },


  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html",
    "default_title": "Summarize!"
  },

  "icons": { "16": "icons/icon16.png",
           "48": "icons/icon48.png",
          "128": "icons/icon128.png" },

  "permissions": ["activeTab", "tabs","contextMenus",
    "http://127.0.0.1:5000/*","https://en.wikipedia.org/*"]
}

popup.js

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
    if (request.message == "no_text_selected") {
        console.log("no_text_selected");
        document.body.innerHTML += "<h3 style='text-align: center'>No text selected! Select text and try again.</h3>";
    }

    else if (request.message == "not_enough_text") {
        console.log("not enough text");
        document.getElementById("header").innerHTML += "<h3 class='heading'>Not enough text selected to generate summary. Select larger block of text and try again.</h3>";
        document.getElementById("footer").innerHTML += "<div style='padding:15px;'>Powered by <a href='http://zippybots.com' target='_blank'><span id='link'>Zippybots</span></a></div>";
    }

    else if (request.message == "summary") {
        console.log("Summary printing");
        var summary_final = request.data;
        console.log(summary_final);
        document.getElementById("header").innerHTML += "<h1 class='heading'>Summary</h1>";
        var para = "";
        for (var i = 0;i<summary_final.length;i++)
        {
            para += summary_final[i]+" ";
            if( i % 3 == 2) 
            {
                document.getElementById("summary").innerHTML += "<p class='point'>"+para+"</p>";    
                para = "";
            }
        }
        if (para) document.getElementById("summary").innerHTML += "<p class='point'>"+para+"</p>";
        document.getElementById("footer").innerHTML += "<div style='padding:15px;'>Powered by <a href='http://zippybots.com' target='_blank'><span id='link'>Zippybots</span></a></div>";
    }
    return true;
});

content.js

console.log("Content file loaded");
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
    if (request.message == "get_selected_text") {
        var selectedText = document.getSelection().toString();
        sendResponse({selected_text: selectedText});
        return true;
    }
});

popup.html

<html>
    <head>
        <meta charset="utf-8">
        <link href="bootstrap.min.css" rel="stylesheet">
        <script src="jquery-3.1.1.min.js"></script>
        <script src="bootstrap.min.js"></script>
        <!-- <script src="api-keys.js"/></script> -->
        <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
        <script type="text/javascript" src="content.js"></script>
        <script type="text/javascript" src="background.js"></script>
        <style>
            body{
                min-width: 550px;
                font-family: 'Ubuntu', sans-serif;
                background: #f1f1f1;
                /*background: #2c001e;*/
            }
            #header{
                /*background: #dd4814;*/
                background: #2c001e;
                /*color: #dd4814;*/
                color: #fff;
                text-align: center;
                padding: 1px;
            }
            #footer{
                /*background: #dd4814;*/
                background: #2c001e;
                color: #fff;
                text-align: right;
                min-height: 50px; 
            }
            #link{
                /*color: #fff;              */
                color: #dd4814;
            }
            .point{
                color: #333;                
                /*background: #2c001e;*/
                background: #f1f1f1;
                text-align: justify;
                padding: 5px;
            }
            #summary{
                background: #f1f1f1;
                /*background: #2c001e;*/
                max-width: 720px;
                font-weight: 300;   
                font-size:15px;
                font-family: Ubuntu, Arial, "libra sans", sans-serif;
                padding-left: 30px;
            }
            .heading{
                margin-top: 10px;
                margin-bottom: 10px;
            }
        </style>
    </head>
    <body>
            <div id="header"></div>
            <!-- This will be populated when extension button is clicked -->
            <div id="summary"><br></div>
            <div id="footer">

            </div>
    </body>
</html>

You have two problems:

First problem

You are using tabs.sendMessage() when attempting to communicate with the script which is in the popup you have opened. As an HTML page contained within your extension, the scripts in that page run in the background context. Thus, tabs.sendMessage() will not work to communicate to that script. If you are wanting to send messages of that type, you need to use runtime.sendMessage() . There are multiple ways you can communicate between scripts in the background context. For a more detailed discussion, please see Communicate between scripts in the background context (background script, browser action, page action, options page, etc.)

Second problem

You are trying to send a message to the popup.js script in the window you just opened immediately within the callback of windows.create() . At the time that callback is run, the window has begun to be created and a windowId has been assigned, but the content of the window does not yet exist (ie the DOM has not been built and the code in popup.js has not yet been run). Thus, there is no listener active, which results in the message not being received.

Solutions

The easy ways to solve these issues are:

  1. Store the data in storage.local prior to the call to windows.open() and let the popup.js code get it from storage.local when it first runs, or
  2. Initiate the transfer of the data from popup.js by sending a message from the popup.js code to your background.js (using runtime.sendMessage() ) requesting the data. Your background.js can then send the data back using the sendResponse function provided by runtime.onMessage() .
  3. Store the data in a variable in your background.js which is accessible from it's global scope. Your popup.js code can then directly access the variable in that scope after obtaining the background's window object with chrome.extension.getBackgroundPage() .

It's also possible to wait to send the message from background.js until after popup.js has run, but that is any of: A) more complex, B) effectively the same as having the runtime.sendMessage() initiated from the popup, or C) not guranteed to actually be after the popup.js runs (eg just using a setTimeout() ).

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