Monitoring chrome.storage throttle limits - google-chrome-extension

I'm using chrome.storage in an extension and would like to avoid triggering runtime errors due to exceeding one of the documented throttles for either the sync or local stores. (things like QUOTA_BYTES, QUOTA_BYTES_PER_ITEM)
My first choice would be to intercept these errors prior to a runtime error being generated; alternatively I could track usage on the extension side and try to avoid triggering them.
This feels like an issue that someone must have addressed, but I can't seem to find any solutions - any suggestions appreciated.

Here's a sample of the solution I'm going with (using Angular, so there are promises in here), although having to regex the chrome.runtime.lastError value is pretty ugly IMO:
var service = {
error: function(lastError) {
if((lastError) && (lastError.message)) {
var errorString = lastError.message;
if(/QUOTA_BYTES/.test(errorString)) {
return true;
} else if(/QUOTA_BYTES_PER_ITEM/.test(errorString)) {
return true;
} else if(/MAX_ITEMS/.test(errorString)) {
return true;
} else if(/MAX_WRITE_OPERATIONS_PER_HOUR/.test(errorString)) {
return true;
} else if(/MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE/.test(errorString)) {
return true;
}
return false;
} else {
return false;
}
},
write: function(key, value) {
var deferred = $q.defer();
var data = {};
data[key] = value;
chrome.storage.sync.set(data, function() {
if(service.error(chrome.runtime.lastError)) {
deferred.reject('Write operation failed: '
+ chrome.runtime.lastError.message);
} else {
deferred.resolve();
}
});
return deferred.promise;
}
};
return service;

Related

NodeJS: call func from inside another func in same file

I have NodeJS program.
In one class, I have various utility methods. One function, safeGithubPush, calls safeString, another func in the same class
module.exports = {
safeString(stringToCheck) {
console.log(validator.isAscii(stringToCheck), validator.matches(stringToCheck, /^((\w)*[-.]?(\w)*)*$/))
return (
validator.isAscii(stringToCheck) &&
validator.matches(stringToCheck, /^((\w)*[-.]?(\w)*)*$/)
);
},
safeGithubPush(currentJob) {
if (
!currentJob ||
!currentJob.payload ||
!currentJob.payload.repoName ||
!currentJob.payload.repoOwner ||
!currentJob.payload.branchName
) {
this.logIn(
currentJob,
`${' (sanitize)'.padEnd(15)}failed due to insufficient job definition`
);
throw invalidJobDef;
}
if (
this.safeString(currentJob.payload.repoName) &&
this.safeString(currentJob.payload.repoOwner) &&
this.safeString(currentJob.payload.branchName)
) {
return true;
}
throw invalidJobDef;
},
}
While this.logIn(), another func in the utility class, works just fine, I get the error for safeString:
Error caught by first catch: TypeError: this.safeString is not a function
I followed a solution offer by another SO post:
safeString: function(stringToCheck){
...
}
safeGithubPush(currentJob) {
...
if (
this.safeString(currentJob.payload.repoName) &&
this.safeString(currentJob.payload.repoOwner) &&
this.safeString(currentJob.payload.branchName)
) {
return true;
}
}
But this also gets a, TypeError: this.safeString is not a function.
I'm not using arrow functions, which is the explanation for this error on a different SO post
I don't think the reason is determinable with the code you are currently presenting. It likely has something to do with how you are calling safeGithubPush. If you do something that would change the this binding the this.safeString is going to fail.
const foo = {
fizz() {
console.log("fizz");
},
buzz() {
this.fizz();
}
};
// "this" is correct
foo.buzz();
// "this" has no fizz to call
const myFizz = foo.buzz;
myFizz();
Considering you are attaching these to module.exports I am going to guess that you pull these functions off in a require call and then try to use them bare which makes the problem obvious after looking at my example above:
// Ignore these 2 lines, they let this look like node
const module = {};
const require = () => module.exports;
// Ignore above 2 lines, they let this look like node
// Your module "some.js"
module.exports = {
safeString(str) {
return true;
},
safeGithubPush(currentJob) {
if (!this.safeString("some")) {
throw new Error("Not safe");
}
return true;
}
};
try {
// Some consumer module that doesn't work
const {safeGithubPush} = require("./some.js");
const isItSafe = safeGithubPush();
console.log(`Safe? ${isItSafe}`);
} catch (err) {
console.error("Didn't bind right \"this\"");
}
try {
// Some consumer module that DOES work
const someModule = require("./some.js");
const isItSafe = someModule.safeGithubPush();
console.log(`Safe? ${isItSafe}`);
} catch (err) {
console.error(err);
}
I would restructure this code. You say these are utility functions which makes me think you don't really want to have to structure them with this in mind.
Instead of attaching them all to module.exports at their definition, define them outside and directly reference the functions you want to use, then attach them to exports so other modules can use the functions:
function safeString(stringToCheck) {
return true;
}
function safeGithubPush(currentJob) {
if (!safeString("some")) {
throw new Error("Not safe");
}
return true;
}
module.exports = {
safeString,
safeGithubPush
};

Issues with ActiveXObject in Angular 7

I am developing a small page/router component on a website using Angular 7 and its CLI. At one point I need to check if the user has allowed flash, I do this by doing so:
checkFlash() {
var hasFlash = false;
try {
hasFlash = Boolean(new ActiveXObject("ShockwaveFlash.ShockwaveFlash"));
} catch (exception) {
hasFlash = "undefined" != typeof navigator.mimeTypes["application/x-shockwave-flash"];
}
return hasFlash;
}
I found this off here, and it works great, but now as I am cleaning up my application I am noticing that Angular doesn't seem to like this, in fact, it says that ActiveXObject isn't defined, yet it still works.
Super confused...
I tried linking an actual flash object like so $('embed[type="application/x-shockwave-flash"]') or $('embed[type="application/x-shockwave-flash"]')[0] but had no luck, it always returned true.
I tried installing extra npm(s) including ones like activex-support and activex-data-support as well as their #types cousins. After setting them up I found out that they did nothing to help my case.
Here are the exact errors the CLI & VScode-Intellisense gave me:
VScode:
[ts] 'ActiveXObject' only refers to a type, but is being used as a value here. [2693]
any
CLI:
ERROR in src/app/games/games.component.ts(51,30): error TS2304: Cannot find name 'ActiveXObject'.
It doesn't throw this error when ran inside plain JS, but I've looked around and can't seem to figure out how to run pure JS inside Angular 2 (7). Also looked here with no luck.
Please help, completely lost here.
EDIT: Found the fix -->
The answer was here listed inside the comments (will need to make minor changes)(shown below)
change from:
checkFlash() {
var hasFlash = false;
try {
hasFlash = Boolean(new ActiveXObject("ShockwaveFlash.ShockwaveFlash"));
} catch (exception) {
hasFlash = "undefined" != typeof navigator.mimeTypes["application/x-
shockwave-flash"];
}
return hasFlash;
}
to:
function checkFlash() {
var hasFlash = false;
try {
var flash =
navigator.mimeTypes &&
navigator.mimeTypes["application/x-shockwave-flash"]
? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin
: 0;
if (flash) hasFlash = true;
} catch (e) {
if (navigator.mimeTypes["application/x-shockwave-flash"] != undefined)
hasFlash = true;
}
return hasFlash;
}
This issue with ActiveXObject can be solve as shown below:
Goto your tsconfig.json file and add the 'scripthost' library.
Then recompile your application.
"lib": [
"es2017",
"dom",
"scripthost"
]
The answer was here listed inside the comments (will need to make minor changes)(shown below)
change from:
checkFlash() {
var hasFlash = false;
try {
hasFlash = Boolean(new ActiveXObject("ShockwaveFlash.ShockwaveFlash"));
} catch (exception) {
hasFlash = "undefined" != typeof navigator.mimeTypes["application/x-
shockwave-flash"];
}
return hasFlash;
}
to:
function checkFlash() {
var hasFlash = false;
try {
var flash =
navigator.mimeTypes &&
navigator.mimeTypes["application/x-shockwave-flash"]
? navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin
: 0;
if (flash) hasFlash = true;
} catch (e) {
if (navigator.mimeTypes["application/x-shockwave-flash"] != undefined)
hasFlash = true;
}
return hasFlash;
}

NodeJS Error Encapsulation

I am currently trying to handle exceptions and errors in a NodeJS app which will be used for critical information. I need a clean error management !
I've been wondering if there is something similar to Java Exceptions encapsulation.
I'm explaning.
In Java you can do something like that :
try {
// something that throws Exception
} catch (Throwable t) {
throw new Exception("My message", t);
}
That allows you to decide when to log your exception and you get the whole stack trace and call path !
I would like to know if there is a way to do the same in NodeJS because logging at every step seems not to be the right way of doing things.
Thank you.
You should look at this module :
https://www.npmjs.com/package/verror
Joyent quote it on his error management best pratices : https://www.joyent.com/developers/node/design/errors
At Joyent, we use the verror module to wrap errors since it's
syntactically concise. As of this writing, it doesn't quite do all of
this yet, but it will be extended to do so.
It allow you to get details on error message. And tracking the step of the error.
And also hide details to the client with wrapped error : WError() who returns only the last error message.
I answer my own question to explain what i finaly did to have the wanted encapsulation.
I used https://www.npmjs.com/package/verror as Sachacr suggested.
Then I extended it that way :
my_error.js :
var VError = require('verror');
var _ = require('lodash');
function MyError() {
var args = [];
var httpErrorCode;
var cause;
if (arguments.length > 0) {
var lastArgumentIndex = [arguments.length];
cause = manageCause(lastArgumentIndex, arguments);
httpErrorCode = manageHttpCode(lastArgumentIndex, arguments);
for (var i = 0; i < lastArgumentIndex; i++) {
args[i] = arguments[i];
}
}
this.__proto__.__proto__.constructor.apply(this, args);
if (cause) {
if (this.stack) {
this.stack += '\n' + cause.stack;
} else {
this.stack = cause.stack;
}
}
this.httpErrorCode = httpErrorCode;
}
MyError.prototype.__proto__ = VError.prototype;
function manageCause(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& arguments[lastArgumentIndex[0] - 1] instanceof Error) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
function manageHttpCode(lastArgumentIndex, arguments) {
if (lastArgumentIndex[0] > 0
&& _.isNumber(arguments[lastArgumentIndex[0] - 1])) {
lastArgumentIndex[0]--;
return arguments[lastArgumentIndex[0]];
}
}
module.exports = MyError;
It allows me to use it easily in my code :
var MyError = require('./my_error.js');
function withErrors() {
try {
// something with errors
} catch (err) {
// This is the same pattern as VError
return new MyError("My message", err, 401);
}
}
function somethingToDo(req, res) {
var result = withErrors();
if (result instanceof MyError) {
logger.warn(result);
res.status(result.httpErrorCode).send(result.message).end();
return
}
}
That way, i hace a nice stack trace with call path and every line involved in error/exception.
Hope it will help people, cause i searched a looooong time :)
EDIT : I modified my MyError class to add HTTP Error codes and clean arguments management.
You should be able to do something like:
funtion exception(message, error) {
this.message = message;
this.stacktrace = error.stack;
}
try {
if(someData == false)
throw new exception("something went wrong!", new Error());
}
catch(ex) {
console.log(ex.message);
console.log(ex.stacktrace);
}
You can then throw your own custom exception instance containing whatever debugging info you need.
EDIT: added stack trace to exception object

Making an asynchronous function synchronous for the Node.js REPL

I have a library that connects to a remote API:
class Client(access_token) {
void put(key, value, callback);
void get(key, callback);
}
I want to set up a Node.js REPL to make it easy to try things out:
var repl = require('repl');
var r = repl.start('> ');
r.context.client = new Client(...);
The problem is that an asynchronous API is not convenient for a REPL. I'd prefer a synchronous one that yields the result via the return value and signals an error with an exception. Something like:
class ReplClient(access_token) {
void put(key, value); // throws NetworkError
string get(key); // throws NetworkError
}
Is there a way to implement ReplClient using Client? I'd prefer to avoid any dependencies other than the standard Node.js packages.
You can synchronously wait for stuff with the magic of wait-for-stuff.
Based on your example specification:
const wait = require('wait-for-stuff')
class ReplClient {
constructor(access_token) {
this.client = new Client(access_token)
}
put(key, value) {
return checkErr(wait.for.promise(this.client.put(key, value)))
}
get(key) {
return checkErr(wait.for.promise(this.client.get(key)))
}
}
const checkErr = (maybeErr) => {
if (maybeErr instanceof Error) {
throw maybeErr
} else {
return maybeErr
}
}

Huge Web App With Memory Leak in IE 6

I have a huge web app that is having issues with memory leak in IE 6.
Fixing a memory leak in a 5 line code sample that demonstrates the problem is easy.
But if I have a very huge application, where should a start from?
Check out Drip. That usually takes the guesswork out of IE memory leaks.
If for some reason Drip doesn't find it, take a close look at any JavaScript code that works with events. That is almost always the source of any significant memory leak in a browser.
Destroying a DOM element with handlers attached to it, without removing those handlers first, will prevent the memory associated with those handlers from being recovered.
Does the application use a lot of JavaScript?
If it does, then one thing I've found that helps for avoiding memory leaks is to make sure you're using a JavaScript framework such as Prototype or jQuery because they have tried and tested event-handling code that doesn't leak memory.
IE6 can also leak memory if you have circular references to DOM objects
Also try this JavaScript Memory Leak Detector and see if you can diagnose where the problem is
Here is how I solved the memory leak problem in IE7. The idea is to dispose/set to null all expando-properties on all DOM nodes at unloading the page. This worked for me. You may find it useful.
<!--[if lt IE 8]>
<script type="text/javascript">
function disposeAll() {
if (window.document.all) {
for (var index = 0; index < window.document.all.length; index++) {
try { dispose(window.document.all[index], []); } catch (e) { debugger; }
}
}
dispose(window.document.body, []);
dispose(window.document, []);
dispose(window, []);
window.disposeAll = null;
window.dispose = null;
window.onunload = null;
}
function dispose(something, map) {
if (something == null) return;
if (something.dispose && typeof (something.dispose) == 'function') {
try { something.dispose(); } catch (e) { debugger; }
}
map.push(something);
for (var key in something) {
var value = null;
try { value = something[key]; } catch (e) { };
if (value == null || value == dispose || value == disposeAll) continue;
var processed = null;
for (var index = 0; index < map.length; index++) {
if (map[index] === value) {
processed = value;
break;
}
}
if (processed != null) continue;
var constructor = value.constructor;
if (constructor == Object || constructor == Array) {
try { dispose(value, map); } catch (e) { debugger; }
}
if (constructor == Object || constructor == Array || constructor == Function) {
try { something[key] = null; } catch (e) { debugger; }
}
}
map.pop();
}
(function() {
var previousUnloadHandler = window.onunload;
if (previousUnloadHandler == null) {
window.onunload = disposeAll;
} else {
window.onunload = function() {
previousUnloadHandler.apply(this, arguments); // <== HERE YOU MAY WANT TO HAVE AN "IF" TO MAKE SURE THE ORIGINAL UNLOAD EVENT WASN'T CANCELLED
disposeAll();
previousUnloadHandler = null;
};
}
}());
</script>
<![endif]-->
You may want to remove all "debugger;" statements if you don't feel like dealing with some occasional exceptions.

Resources