1

Issue opening a new tab from within the context of a new tab.

I have an issue opening a new tab from within my popup after a button press. My testing so far has shown that I can open a new tab once the button is pressed, but once I try doing so from within the .then() of my call to browser.tabs.query(), the same code no longer works.

This is a highlight of the relevant section of code (from popup/menu.js below):

    // Getting the currently active tab
    var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
    gettingActiveTab.then((tabs) => {
        // Open desired tab. This fails for some reason?
        var creating = browser.tabs.create({
            url:"https://stackoverflow.com/users/641534/antonchanning"
        });
        creating.then(onCreated, onError);
    });
    //test to show we can actually open a tab successfully. This works...
    var creating = browser.tabs.create({
        url:"https://stackexchange.com/users/322227/antonchanning"
    });
    creating.then(onCreated, onError);

Ultimately I plan to get the URL of the currently active tab and this will alter the destination of the new tab that is opened. The plan eventually is for an add-on that can switch between mirror websites that have the same content, even if the current site is down (due to high traffic).

Full code for context

manifest.json:

{
    "manifest_version": 2,
    "name": "New tab test",
    "version": "1.0",

    "description": "Demonstrating an issue getting a new tab to open from a certain context.",

    "icons": {
        "48": "icons/newtab_48.png"
    },

    "permissions": [
    "activeTab"
    ],

    "browser_action": {
        "default_icon": "icons/newtab_32.png",
        "default_title": "New tab test",
        "default_popup": "popup/menu.html"
    }
}

popup/menu.html:

<!doctype html>
<html lang="en">
    <head>
    <title>New tab example</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width" initial-scale="1.0">
    <link rel="stylesheet" type="text/css" href="menu.css">
    </head>
    <body>
        <div>
        <h1>Example</h1>
        <h2><strong>Open:</strong></h2>
        <div>
            <span href="https://stackexchange.com" title="steemdb" class="opennewtab"><img src="/icons/wrench-go.png" title="steemdb" class="flowLeft">New tab 1</span>
            <span href="https://stackoverflow.com" title="steemd" class="opennewtab"><img src="/icons/wrench-go.png" title="steemd" class=flowLeft>New tab 2</span>
        </div>
        </div>
        <script language="javascript" src="menu.js"></script>
    </body>
</html>

popup/menu.css:

html div{
    background-color: #FAFAFA;
    width: 160px;
    margin: auto;
    border-style: solid;
    border-color:#EFF2FB;
    border-width: 1px;
    border-radius:5px;
    padding: 0.5em;
    align-content: center;
}
h1{
    line-height: 2em;
    font: 100% Verdana, Geneva, sans-seriff;
    font-style: normal;
    color:#58ACFA;
    margin-bottom: 0.5em;
    text-align: center;
    text-transform: uppercase;
}
h2{
    line-height: 1em;
    font: 100% Verdana, Geneva, sans-seriff;
    font-style: normal;
    color:#A4A4A4;
    margin-bottom: 0.5em;
    text-indent: 1em;
    clear:right;
}
.opennewtab{
    color: #045FB4;
    font:0.9em Verdana, Geneva, sans-seriff;
    display:block;
    text-indent: 2em;
    text-decoration:none;
    margin-bottom: 0.5em;
    background-color: #EFF2FB;
    border:1px solid #A9BCF5;
    padding: 0.5em;
    border-radius: 3px;
}
.opennewtab:hover{
    color: #136;
    background: #def;
}
ul{
    list-style-type:none;
}

img{
    margin-right: 5px;
}
img.logo{
    float: right;
    margin-left:0.2em;
   }
hr{
    border-style:solid;
    border-color:#F0F0F0;
}

popup/menu.js:

function onCreated(tab) {
  console.log(`Created new tab: ${tab.id}`)
}

function onError(error) {
  console.log(`Error: ${error}`);
}

document.addEventListener("click", (e) => {
    if (e.target.classList.contains("opennewtab")) {
        var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
        gettingActiveTab.then((tabs) => {
            // Open desired tab. This fails for some reason?
            var creating = browser.tabs.create({
                url:"https://stackoverflow.com/users/641534/antonchanning"
            });
            creating.then(onCreated, onError);
        });
        //test to show we can actually open a tab successfully
        var creating = browser.tabs.create({
            url:"https://stackexchange.com/users/322227/antonchanning"
        });
        creating.then(onCreated, onError);
    }
    window.close();
});

Note

To download the full code of the test case, including icons, download the ZIP from this GitHub repository and add as a temporary add-on via the about:debugging tab.

Makyen
  • 31,849
  • 12
  • 86
  • 121
AntonChanning
  • 509
  • 2
  • 13
  • 37
  • @Makyen Sorry. It can be hard to strike the right balance of too much/too little code. Have edited it to include missing html (copy paste error probably) and explain it the top bit of code is an extract from the full context. Is that clearer? – AntonChanning Oct 24 '17 at 20:13
  • Yes, that is clearer. I've edited a bit too. Feel free to revert my edit if you have a problem with it.Thanks for the additional information. – Makyen Oct 24 '17 at 20:38
  • 1
    BTW: It appears there's at least three people with a similar issue at about the same point in time. Is this a group project? Something associated with school? There's nothing wrong with that. This is a fine question. I'm just wondering due to the similarity in code and interest by multiple people in a relatively low-traffic tag. – Makyen Oct 24 '17 at 21:15
  • No, I'm not at school. I'm developing an open source project called [SteemSwitch](https://github.com/miblodge/steemswitch) for the blockchain based social network, that will allow users to switch between mirrors and analysis website views of the same tag, post or user. Currently it just inserts the links at the top of the page, which is ugly and messes with page layout. Wanted to move it to a taskbar menu. In fact a url bar menu might be even better, but I didn't think of that until now. Maybe the others are part of a school project, I don't know. – AntonChanning Oct 24 '17 at 22:31
  • Cool. Sounds interesting. Good luck. Note that WebExtension/Chrome extensions have [vastly less capability to modify the browser UI than legacy extensions](https://stackoverflow.com/a/41891320/3773011). There's no ability to add anything to the browser's urlbar other than a single standard sized icon, which is a `page_action`. – Makyen Oct 24 '17 at 23:04
  • I wonder if the ending of legacy extensions explains the sudden upsurge in webextension questions you mentioned. So long as the icon in the urlbar can open a menu onclick it will serve my purposes. I only need the icon to appear on mirror/analysis sites, whereas in the taskbar it appears everywhere. – AntonChanning Oct 25 '17 at 08:21
  • 1
    Possible, there has been a steady increase over the last year+, and a surge over the last while. For my thinking there was a confluance of interest, it's probably a sampling bias on my part. Part of it was probably compressing the time-frame in which I saw the question you edited to include the Firefox add-on tags. The question was actually posted some time ago, but I only saw it today. The other was the other person commenting on that problem that they had the same problem. – Makyen Oct 25 '17 at 08:42
  • 1
    Yes, a `page_action` button is within the urlbar. It can be hidden/shown on a per-tab basis. A `browser_action` button shows in the toolbar. It can't be *actually* hidden, but you could use a icon which shows as a blank area. It should be noted that people don't see `pageAction` buttons as readily as `browserAction` buttons. Thus, you may have to inform people where the button is. Unfortunately, there's no automatic way to have the page action button show on a specific URLs, which, IMO, is a significant feature missing from a API which is supposed to be all about showing only on certain pages. – Makyen Oct 25 '17 at 08:44

1 Answers1

1

It doesn't work because you window.close() your popup prior to executing the browser.tabs.create() in the .then() for browser.tabs.query(). browser.tabs.query() is asynchronous. The .then() is not executed immediately. When you close the popup, the context is destroyed, and execution stops. Thus, the .then() doesn't exist to be called.

If you are wanting to close the popup after you create the tab, then the window.close() needs to execute after you open the tab.

That would be something like:

function onCreated(tab) {
    console.log(`Created new tab: ${tab.id}`)
    window.close();
}

function onError(error) {
    console.log(`Error: ${error}`);
    window.close();
}

document.addEventListener("click", (e) => {
    if (e.target.classList.contains("opennewtab")) {
        browser.tabs.query({active: true, currentWindow: true}).then((tabs) => {
            browser.tabs.create({
                url:"https://stackoverflow.com/users/641534/antonchanning"
            }).then(onCreated, onError);
        });
    }
});
Makyen
  • 31,849
  • 12
  • 86
  • 121
  • Thanks, I'll check this solution out tomorrow. Too late for me tonight... – AntonChanning Oct 24 '17 at 22:32
  • Excellent. This fixed it. I didn't realise `browser.tabs.query` was asynchronous. Good to know. – AntonChanning Oct 25 '17 at 17:39
  • 1
    @AntonChanning Almost all of the calls to WebExtension APIs are asynchronous. In general, you should assume that if something is using [Promises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) (i.e. using a `.then()` method), then it's asynchronous. While it's possible to use Promises to do things which are synchronous, and they are sometimes used that way, mostly to fit in with semantics which are using them for some other thing that's async, they exist primarily to provide a different set of semantics for doing asynchronous tasks. – Makyen Oct 25 '17 at 17:51