0

i want to pass value to chrome.storage.sync.get() function.

chrome.storage.sync.get('privateKey', function(data, e) {
  if (data.privateKey) {
    var decrypt = new JSEncrypt();
    decrypt.setPrivateKey(data.privateKey);
    var uncrypted = decrypt.decrypt(e.detail.encryptedVal)
    alert(uncrypted);
  } else {
    alert("key is not set");
  }
 });

but e.detail.encryptedVal is showing me as undefined.

hu7sy
  • 983
  • 1
  • 13
  • 47
  • I do not understand your question. `get` callback should have only one parameter ( `data` ) and in it stored retrieved object. What do you expect it to do? – Transcendental Jun 23 '16 at 11:46
  • because for decryption i need it encrypted value with private key as well , although i have also separate the logic to get sync storage value but it return nothing.. – hu7sy Jun 23 '16 at 11:49
  • So let me get this straight: You'd like if you could pass `e` to the `get` callback in order to decrypt the value? – Transcendental Jun 23 '16 at 11:53
  • yes, if you have any other solution please suggest i am new to js. – hu7sy Jun 23 '16 at 11:56
  • Writing an in-depth answer. – Xan Jun 23 '16 at 12:04

2 Answers2

2

The callback of .get() expects exactly 1 parameter.

By passing a function that takes 2 parameters (i.e. function(data, e) {...}), you do the following:

  1. The function is called with one parameter. It is assigned to a callback-local variable data.
  2. The second parameter stays undefined. It is assigned to a callback-local variable e.
  3. If there was a variable e in the outer scope, it is no longer accessible.

I assume the part 3 is exactly your problem. You had a variable e in the scope where you called .get(), but you made it inaccessible.

Generally, due to the concept called closures, you don't actually need to pass e inside the scope - you just use the variable from the outer scope, and it will be retained in memory until the function executes. Think of it as a "locally global" variable, if that makes any sense. If it doesn't, there are better explanations.

With that in mind:

chrome.storage.sync.get('privateKey', function(data) { // just don't mention e here
  /* ... */
    // Just use e inside if it comes from outer scope
    var uncrypted = decrypt.decrypt(e.detail.encryptedVal);
  /* ... */
});

Better yet, let's make that into a function:

function decryptValue(value, callback) {
  chrome.storage.sync.get('privateKey', function(data) {
    var decrypt = new JSEncrypt();
    decrypt.setPrivateKey(data.privateKey);
    var decrypted = decrypt.decrypt(value);
    callback(decrypted);
  }
}

/* ... */
decryptValue(e.detail.encryptedVal, function(decrypted) {
  // Do something
});
/* ... */

Note that callback variable? While you can use decrypted inside the callback of .get(), due to the fact it's asynchronous you can't use it outside. There is a very good overview of the problem, and another one here. Basically, .get() is asynchronous so you HAVE to use a callback.

/* ... */
decryptValue(e.detail.encryptedVal, function(decrypted) {
  // Do something with decrypted
});
// Here, decrypted is not yet computed
/* ... */

Most of Chrome API is asynchronous. I would recommend to read You Don't Know JS book on the topic.

Community
  • 1
  • 1
Xan
  • 74,770
  • 16
  • 179
  • 206
  • thanks your answers works for me but i have only problem document.addEventListener("encrypt", function(e) { var encryptedVal = e.detail.encryptedVal; console.info("encrypted value is: ", e.detail.encryptedVal); decrypt(encryptedVal); }); without console.info value is not passess to decrypt function – hu7sy Jun 23 '16 at 12:45
  • How do you know that? You need a callback to do anything with the value. – Xan Jun 23 '16 at 12:46
  • i have follow your way and it works but in listener without console.info(e.detail.encryptedVal) value is neither showing nor send to decrypt function. – hu7sy Jun 23 '16 at 12:49
  • How do you know it's not sent? `decryptValue(something)` on itself will not show anything. You need to pass a second argument (callback) to use the decrypted value (for example, to show it). – Xan Jun 23 '16 at 12:50
1

So, from the comments bellow, I suppose you'd like to pass the value to get callback in order to user it in the callback. Unfortunately, this can't be done the way you want it to be done. But, what you can do is write a decrypt function that will take the encryptedVal as an argument, and simply use it

function decrypt(encryptedVal) {
    chrome.storage.sync.get('privateKey', function (data) {
        if (data.privateKey) {
            var decrypt = new JSEncrypt();
            decrypt.setPrivateKey(data.privateKey);
            var uncrypted = decrypt.decrypt(encryptedVal)
                alert(uncrypted);
        } else {
            alert("key is not set");
        }
    });
}

Do note that this function uses asynchronous code and you may not return from it as you'd expect.

Transcendental
  • 983
  • 2
  • 11
  • 27
  • 1
    Well, ninja'd by seconds. – Xan Jun 23 '16 at 12:16
  • thanks your answer works for me but i have only problem document.addEventListener("encrypt", function(e) { var encryptedVal = e.detail.encryptedVal; console.info("encrypted value is: ", e.detail.encryptedVal); decrypt(encryptedVal); }); without console.info value is not passess to decrypt function – hu7sy Jun 23 '16 at 12:44