4

I'm trying to inline-load a Google Chrome extension using the chrome.webstore.install( link, success, fail) function.

Here's the link from within my page's <head> stanza.

<link rel="chrome-webstore-item" 
     href="https://chrome.google.com/webstore/detail/oafp--redacted--ffencd" />

Here's the button.

<input type="button" class="btn btn-default" onclick="getExtension();">Go</input>

Here's the Javascript, which appears right before the closing </body> tag.

 <script type="text/javascript">

    function getExtension() {

      function extensionFailed(reason) {
        console.log("extension Install Failed:", reason);
      }

      function extensionInstalled() {
        console.log("installed");
      };

      console.log("calling install");
      chrome.webstore.install(undefined, extensionInstalled(), extensionFailed());
      console.log("install returned");

    };

  </script>

Clicking the button that calls getExtension gets me this sequence of events, delivered one after the other immediately.

  1. "calling install" (right before call to chrome.webstore.install())
  2. "installed" (in success callback)
  3. "extension Install failed, undefined" (in failure callback)
  4. "install returned." (after return from call to chrome.webstore.install())

Somewhere in the middle of that, asynchronously, I get the inline installation popup and accept it.

I thought...

  1. the failure callback should only get called on failure.
  2. the failure reason should be something meaningful, not undefined.
  3. the success callback should be deferred until the user accepts the installation.

I must be doing something wrong. ...

O. Jones
  • 81,279
  • 15
  • 96
  • 133

1 Answers1

4

Answer:

In this line of code:

chrome.webstore.install(undefined, extensionInstalled(), extensionFailed());

You're actually executing the functions by having the () in extensionInstalled() and extensionFailed(). If you want to pass them in as callbacks, you can actually pass in the functions themselves as you would a var:

chrome.webstore.install(undefined, extensionInstalled, extensionFailed);


Functions as variables:

Note: This does not apply to your code because you define your functions before you call them, which is good practice.

You can also define variables as functions, which IMO only makes things more confusing. Take for example, these 2 function definitions:

var myfunctionVar = function() {
    console.log('hello, world');
}

function myfunction() {
    console.log('hello, world');
}

You would call these functions in a normal way (i.e. myfunctionVar() and myfunction()).

The key difference between these 2 definitions is that myfunctionVar will only become available once the definition itself is executed whereas myfunction is immediately available in the scope of the parent function that defines it (or once your script file is executed if there is no parent function). This is due to "hoisting", which only makes things more complicated.

In this example, you would not be able to call myfunctionVar() before you assign it. However, this would not be the case for calling myfunction(), and you can call it anywhere in the parent function.

See this answer for a more information.

Functions are a bit more complicated (and powerful!) in Javascript than in other languages, so hopefully this answer clears a few things up for you. You can read about hoisting from W3Schools, here.

Community
  • 1
  • 1
Kenny Worden
  • 3,720
  • 8
  • 31
  • 58
  • 2
    Correct. The `()` executes both callback functions immediately, even before the `.install(...)` method is invoked. Removing these brackets ensures that you're passing a _reference_ to the function as parameter. To give a little more information; the `install` method puts `()`'s behind the callback _references_ internally to execute one of them as a function when one of these callbacks needs to be invoked. This is done using `success();` when for example, the success callback is called. – Tim Visée Aug 12 '16 at 18:49
  • 2
    *(smacks forehead)* Thanks! – O. Jones Aug 12 '16 at 19:00