I have run into what I think is a hard maximum of 4 chrome.commands allowed, based on the following error I get in Google Chrome when trying to add 5 or more in the manifest.json file:
"Could not load extension from '[Extension Path]'. Too many commands specified for 'commands': The maximum is 4."
Is there any particular reason for this limit, or any way to get around it?
For context: I'm currently working on an extension that adds the current page as a bookmark to a specific folder based on a specific hotkey, currently along the lines of ctrl+alt+0, ctrl+alt+1, up to ctrl+alt+9.
I have looked at source code and figured out following lines of code.
constant declared for error message in extension_manifest_constants.cc
const char kInvalidKeyBindingTooMany[] =
"Too many commands specified for 'commands': The maximum is *.";
constant declared for maximum number of commands in extension.cc
// The maximum number of commands (including page action/browser actions) an
// extension can have.
const size_t kMaxCommandsPerExtension = 4;
and validation code in extension.cc looks for following check
if (commands - > size() > kMaxCommandsPerExtension) {
* error = ErrorUtils::FormatErrorMessageUTF16(
errors::kInvalidKeyBindingTooMany,
base::IntToString(kMaxCommandsPerExtension));
return false;
}
Google developers marked constant to 4, so you can not add more than 4 commands for now.
Work Around:
Star this issue and look for developers response, if you really want to go with commands, you have to create multiple extensions with commands set of 4 for each.
Let me know if you need more information.
This is a very old question but I had a hard time finding information anywhere and this question was the top google search result for a few of my searches, so I'll add some info here.
Despite the wordage of the error, you can have as many commands as you want. This error actually refers to the number of "suggested_key" objects you can have. Chrome's documents specify the following:
An extension can have many commands but only 4 suggested keys can be specified.
So in your manifest, while you can specify additional commands, you can only give 4 of them the "suggested_key" object
"commands": {
"contains-suggested-key": {
"suggested_key": {
"default": "Ctrl+Shift+Y",
"mac": "Command+Shift+Y"
},
"description": "Toggle feature foo"
},
"NO-suggested-key": {
"description": "user must specify shortcut keys for this from the extensions page"
}
}
Related
I have this client script which copies the line number entered in Copy line# and creates new lines from number of lines entered in Copy #Times.
This thing takes time when you increase the number of lines you require to copy. So can we give any processing animation till all the lines are set so user dont have to worry?
I have tried giving dialog.create but it didnt work. I want the animation to stay until script is executing and after that stop.
var options = {
title: 'Alert',
message: 'Processing. Please wait.',
buttons: [{
label: 'OKK...',
value: 1
},
]
};
dialog.create(options).then(success)
return (true);
success is a function I am calling.
The N/ui/dialog module is intended for showing dismissable messages, and won't really work for progress bars as you cannot hide the buttons, nor close it via code. I would recommend looking at a third party library. A very popular one is SweetAlert2, and there is some sample code on the NetSuite Professionals site for using it with NetSuite.
If you just want a quick hack, you could just used the Ext.js library that NetSuite includes by default on all pages. However I would highly recommend not doing so for any production code because NetSuite could update or remove it at any time in a future upgrade.
var messageBox = Ext.MessageBox.show({
title: 'Lines are being copied...',
msg: 'This may take a couple minutes',
wait: true,
width: 250
});
// your work here
messageBox.hide()
I am writing an application in nodeJS - a Facebook messenger app.
My application contains a module called strings.js, which is basically used to store common strings. Any time I need to print a greeting or whatever I pull it from the strings.js file. Strings.js looks like this:
/*
* This module exports common strings.
* */
'use strict';
module.exports = {
// Quick replies for user to choose age range
ageReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// Quick replies for user to choose gender
genderReplies:[
{
//Option 1 CODE
},
{
//Option 2 CODE
},
{
//Option 3 CODE
}],
// 'greetingButtons' is used to create the buttons sent to a registered
// user during the greeting
greetingButtons: [
{
//BUTTON 1 CODE
},
{
//BUTTON 2 CODE
},
{
//BUTTON 3 CODE
}],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
};
The first two"objects" (if that's what we can call them), "ageReplies" and "GenderReplies" are used for generating quick replies in Facebook messenger when asking user for gender and age (during user profile creation).
The next is "greetingButtons", which is used for creating buttons, which are sent to a previously registered user with a "What would you like to do next?" message.
Finally I have a number of strings for greeting the user, prompting them to enter gender and age, and so on. There will be more of these as I add them.
I have been considering putting these individual strings in an object, for example as follows:
stringData: {
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Is there any benefit to doing this? Is there any point?
Another question is, if I DID use an object like this, is it possible to put my buttons and quick replies into the same object, for example as below:
stringData: {
ageReplies:[ /* Age reply code */ ],
genderReplies: [ /* Gender reply code */ ],
greetingButtons: [ /* Button code */ ],
userAgeString: "How old are you?",
userGenderString: "What's your gender?",
userInitialGreetingString: "Hello there! I don't believe we've spoken before. You'll need to create a user profile, so let's do that now.",
userNamePromptString: "What would you like me to call you?",
userPrefNamePromptString: "Ok, what would you like me to call you instead? Type it below:",
userWelcomeGreetingString: "Welcome back! I am ready and willing to serve, as always!",
},
Would this work?
EDIT: Just to clarify, I'm not talking about having an object within my main code. The object I'm talking about would be within strings.js
Generally when writing a program that involves displaying text of some sort, I store all of my copy (text eventually sent to a user) in it's own file. These blocks of text have a variable name like you've made, and that allows me to refer to them around the system.
Why do I do this? Internationalisation (commonly shortened to i18n).
It's quite common practice to pull apart text displayed to uses from the rest of your application so that you can easily create multiple files for text and load from the correct one depending on the users language settings (or locale).
In that instance, you'd have a strings file per spoken language, where variable names are all the same. You then select from the specific file depending on settings / locale.
For this reason alone, I keep all my text separate from the rest of the application. This doesn't quite work when it's HTML based projects and such, but with things like nodejs server side error messages, it works perfectly.
Personally when I've built bots, the number of options (buttons) does not relate to the text I use in anyway. So my code to create varying options happens elsewhere, but will use the strings provided by my i18n module. This way text and buttons are decoupled nicely. Often button creation happens in a function that takes some sort of array of objects which represents the options for each button, I'll then pull in the text, when creating the final button markup, from my i18n files.
On a side note: I also don't label things like a "string" prefix or suffix, referring to something as i18n.welcomeGreeting or just welcomeGreeting and I find that's more than explicit enough for this stuff.
Tl;dr
It won't make a huge difference either way right now, but decoupling your text from your button creation can render useful benefits if your application is likely to grow in the future. It can also often make it easier to work with, and separates buttons from text. After all, you don't always use the two together in chat bots, so they should probably be separate concerns.
The examples for generating tests in the testflow create stop_bins. However there were no examples of how to generate the 93k multi_bin node. Does this feature exist in the current origen-sdk?
output node looks like this in 93k .tf file
if #FLAG then
{
multi_bin;
}
else
{
}
There is currently no direct support for creating multi_bin nodes, though in time I do expect that it will be added as a result of this effort to add support for limits tables.
In the meantime though, there is the ability to render any text and this can be used to generate what you want.
To generate the above example you could do:
if_flag :flag do
render 'multi_bin;'
end
This will also work with in-line conditions, this is the same:
render 'multi_bin;', if_flag: :flag
Additionally, on_pass and on_fail will accept a render option:
func :my_test, on_fail: { render: 'multi_bin;' }
Obviously that is creating something that will not be able to translate to other tester platforms, so the advice is to use render sparingly and only as a get out of jail card when you really need it.
Also note that for these examples to work you need at least OrigenTesters 0.11.1.
I have a nodejs app which has the new relic module installed.
Everything is set up but I don't know how to exclude a route from the new relic tracker.
I have this script at http://www.website.com/match/findMatch which usually takes at least 4 seconds and I want to add it to the exclusion list.
The rest of the scripts usually take 0.1s but this one makes my ApDex give out alerts which aren't correct.
I already have this in my conf file because I use websockets:
rules : {
ignore : [
'^\/socket\.io\/.*\/xhr-polling',
'^\/socket\.io\/.*\/websocket',
]
}
I've read the docs here 3 times but still don't understand how to do it.
You'll want to add a new ignore rule that matches requests to http://www.website.com/match/findMatch.
Rules can be strings or regular expressions (like the socket.io examples). If the request you want to ignore is always http://www.website.com/match/findMatch (not, for example, http://www.website.com/match/findMatch?q=foo, you can do this:
rules : {
ignore : [
'^\/socket\.io\/.*\/xhr-polling',
'^\/socket\.io\/.*\/websocket',
'http://www.website.com/match/findMatch'
]
}
I love what chrome offers me through its extension API.
But I always find myself lost in the jungle of what API is supported by which chrome version and when did the last chrome.experimental feature make it into the supported extensions.
The Chrome extension page gives me a nice overview what is supported, but without mentioning since what version. The same is true for the experimental API overview. Is that specific API still experimental or is it already supported in canary, for example.
If I try a sample from the chrome Samples website I usually have to change some API calls from chrome.experimental.foo to chrome.foo or find out that it is not supported at all. (What happened to chrome.experimental.alarm?) That usually means to just use the trial and error approach to eliminate all errors, until the sample works.
tldr;
So, I'm wondering is there an overview page which tells me since what version, what API is supported or when it was decided to drop an experimental API. And if there is no such page, what is the recommended way or your personal approach to deal with this situation?
On this page, the process of generating the official documentation (automatically from the Chrome repository) is described. On the same page, you can also read how to retrieve documentation for older branches. Note that the documentation is somehow incomplete: Deprecated APIs are included immediately, although they're still existent (such as onRequest).
What's New in Extensions is a brief list of API changes and updates (excluding most of the experimental APIs). It has to be manually edited, so it's not always up-to-date. For example, the current stable version is 20, but the page's last entry is 19.
If you really need a single page containing all API changes, the following approach can be used:
First, install all Chrome versions. This is not time consuming when done automatically: I've written a script which automates the installation of Chrome, which duplicates a previous profile: see this answer.
Testing for the existence of the feature:
Write a manifest file which includes all permissions (unrecognised permissions are always ignored).
Chrome 18+: Duplicate the extension with manifest version 1 and 2. Some APIs are disabled in manifest version 1 (example).
Testing whether a feature is implemented and behaving as expected is very time-consuming. For this reason, you'd better test for the existence of an API.
A reasonable manner to do this is to recursively loop through the properties of chrome, and log the results (displayed to user / posted to a server).
The process of testing. Use one of the following methods:
Use a single Chrome profile, and start testing at the lowest version.
Use a separate profile for each Chrome version, so that you can test multiple Chrome versions side-by-side.
Post-processing: Interpret the results.
Example code to get information:
/**
* Returns a JSON-serializable object which shows all defined methods
* #param root Root, eg. chrome
* #param results Object, the result will look like {tabs:{get:'function'}}
*/
function getInfo(root, results) {
if (root == null) return results;
var keys = Object.keys(root), i, key;
results = results || {};
for (i=0; i<keys.length; i++) {
key = keys[i];
switch (typeof root[key]) {
case "function":
results[key] = 'function';
break;
case "object":
if (subtree instanceof Array) break; // Exclude arrays
var subtree = results[key] = {};
getInfo(root[key], subtree); // Recursion
break;
default:
/* Do you really want to know about primitives?
* ( Such as chrome.windows.WINDOW_ID_NONE ) */
}
}
return results;
}
/* Example: Get data, so that it can be saved for later use */
var dataToPostForLaterComparision = JSON.stringify(getInfo(chrome, {}));
// ...