request for feedback on experimental context menus API

177 views
Skip to first unread message

Antony Sargent

unread,
Mar 24, 2010, 2:35:11 PM3/24/10
to Chromium-extensions
Hello all-

I just landed a first cut of support for an experimental context menu API and would like to get some feedback. 

The design document is here:


A quick example of code you'd put in your background page:


function mycallback(info, tab) {
  console.log("context item clicked: " + JSON.stringify(info) +
              " on tab " + JSON.stringify(tab));
}

chrome.experimental.contextMenu.create({"title": "My Test Item",
                                        "onclick": mycallback});


To try it out, grab one of the latest continuous builds here (Win/Mac slightly more functional than Linux right now):

You need to run with the --enable-experimental-extension-apis command line argument as described here:
(to pass the flag on Mac, unzip the file, in a terminal cd to chrome-mac/Chromium.app/Contents/ and then run ./MacOS/Chromium --enable-experimental-extension-apis)

You might also want to use the --user-data-dir=<some path> command line argument to use a separate profile from your regular install. 


Notes:
-Please make sure to read the "Future Improvements" section of the design doc which addresses some common questions
-On Linux, the current context menu code doesn't support submenus, so for now you're better off playing with it on Windows/Mac
-The current code does not yet show the extension icon in the menu as the UI Design calls for


A few questions:
-Does this give you enough functionality to build something useful?
-Is it enough to let you specify contexts for your items, or have you found that you often wanted finer grain control? (eg I want a context menu item for <img> elements only if their url matches this regex or they appear within a div of a certain class)
-One of the design goals was to keep developers from having to use content scripts unnecessarily, which is why registration/callbacks for context menus happen in your background page. Does this work for use cases you have in mind? If not, I'd like feedback on what those use cases are.


Daniel Kantor

unread,
Mar 24, 2010, 3:23:13 PM3/24/10
to Antony Sargent, Chromium-extensions
Anthony,

Overall this looks great. +1 for getting the actual DOM node clicked. 

I do have a question about contexts. What will VIDEO and AUDIO be? Will these just be the <video> and <audio> tags? Or will you be able to detect when a user clicks on a Flash video? How about an .mp3 link?

For the create method, do you see see putting the code once, say at the bottom of a background script, or is this something that you call each time a right-click event is passed to your extension? If it is the former, can you create two contextMenus? I would like to create one when the context is PAGE and another when the context is AUDIO. 

thanks,
Dan


--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-extensions/?hl=en.

Antony Sargent

unread,
Mar 24, 2010, 4:45:42 PM3/24/10
to Daniel Kantor, Chromium-extensions
I do have a question about contexts. What will VIDEO and AUDIO be? Will these just be the <video> and <audio> tags? Or will you be able to detect when a user clicks on a Flash video? How about an .mp3 link?

 They are for html5 <video> and <audio> tags. Unfortunately plugins like flash render their own context menus as far as I can tell from our code, so we can't provide access to those. For an mp3 link, right now all you could do is create a context menu item that would apply to all links. 

 
For the create method, do you see see putting the code once, say at the bottom of a background script, or is this something that you call each time a right-click event is passed to your extension? If it is the former, can you create two contextMenus? I would like to create one when the context is PAGE and another when the context is AUDIO. 

Typically you'd register items just once in your background page with one call per item. For instance:

function myPageItemCallback(info, tab) { ... }
function myAudioItemCallback(info, tab) { ... }

chrome.experimental.contextMenu.create({
  "title": "My page item", "contexts": ["PAGE"], "onclick": myPageItemCallback});

chrome.experimental.contextMenu.create({
  "title": "My audio item", "contexts": ["AUDIO"], "onclick": myAudioItemCallback});


Daniel Kantor

unread,
Mar 24, 2010, 6:06:05 PM3/24/10
to Antony Sargent, Chromium-extensions
Ok that makes sense. Do you think getting the DOM node is something that will quickly follow the release of this API? It is certainly very useful in its current state, but I can think of a few things already that I would need to know the node to make use of. If there was also a way to dynamically gray out menu items that would help a lot as well. 

karl

unread,
Mar 24, 2010, 6:32:33 PM3/24/10
to Chromium-extensions
I'd also like to +1 for getting the actual DOM node clicked.

> Some people have asked for a onBeforeShow() event to fire before the menu items are displayed, but this may be infeasible
> given chrome's multiprocess architecture and desire to keep the UI very responsive.

I understand you don't want the user to wait for a context menu to
show, and this is to be applauded. Also the "only one top level menu
per extension" should hopefully alleviate the context menu bloat we
get in Firefox, so bonus points for that too.

I have one specific user cases where the context menu items will take
some time to create:

Lazarus: Form Recovery (https://chrome.google.com/extensions/detail/
loljledaigphbcpfhfmgopdkppkifgno/). The submenu will be a list of
items that the user can restore into the textarea that the user has
right clicked on. The list is generated by looking up the items in a
local html5 database (on the background page), which is relatively
speedy and doesn't pose a problem. However we are encrypting each
item, and as such decrypting the items can take a small amount of time
(~100ms on an older machine). But when showing the first 10 or so
items this will cause up to a 1 second delay.

If we can't have an onBeforeShow event, can we have an onShow event
instead. That way developers can show a loading menu item
("loading..." or a loading image inside the menu), retrieve the
required data to build the menu, and then add the menu items
dynamically when the data is ready?

It would therefore be useful to have a onHide event so we could remove
the items when the menu closes (otherwise the previous items would
appear in the menu momentarily before we had a chance to replace them
with the loading menuitem, the second time the menu was opened).

karl

unread,
Mar 24, 2010, 6:34:55 PM3/24/10
to Chromium-extensions
Can we set tooltip text for menu item?

It would be useful to be able to show additional/help information when
the one line description isn't enough.

PhistucK

unread,
Mar 25, 2010, 7:22:40 AM3/25/10
to karl, Chromium-extensions
I am not sure this is at all possible. This is really not the standard user experience (at least on Windows).

☆PhistucK


Antony Sargent

unread,
Mar 25, 2010, 1:14:53 PM3/25/10
to Daniel Kantor, Chromium-extensions
Ok that makes sense. Do you think getting the DOM node is something that will quickly follow the release of this API? It is certainly very useful in its current state, but I can think of a few things already that I would need to know the node to make use of. If there was also a way to dynamically gray out menu items that would help a lot as well. 

Yep, I'm working on getting a way to access the DOM node right now. It's possible we'll delay moving this out from experimental until we have that, since it seems so important.

By "dynamically gray out menu items", do you mean just in general after they have been created? I'm working on adding a chrome.experimental.contextMenu.update(id, properties) method that would let you change any of the properties of an item you had previously added, including setting the enabledContexts property to [] so that the item would appear but be greyed out. This will be very straightforward to add. However, making this API call dynamically update any currently visible context menus (as opposed to the *next* context menu that gets brought up after your API call) may be a bit more difficult.

Antony Sargent

unread,
Mar 25, 2010, 1:20:49 PM3/25/10
to karl, Chromium-extensions
If we can't have an onBeforeShow event, can we have an onShow event
instead. That way developers can show a loading menu item
("loading..." or a loading image inside the menu), retrieve the
required data to build the menu, and then add the menu items
dynamically when the data is ready?

This is an interesting use case and great feedback to have. One compromise idea I've been thinking about is letting you create a parent item that would display immediately whose sub-menu can be filled in dynamically. That way a user would always see the top-level context menu immediately, but if they moused down to an extensions item and it was a little slow to load up the submenu they'd feel like it was the extension that was slow, and not chrome itself. Perhaps if the extension hasn't responded within 200ms we'd put up a little dummy submenu with a greyed out item that says "loading..." or something like that. 

 
It would therefore be useful to have a onHide event so we could remove
the items when the menu closes (otherwise the previous items would
appear in the menu momentarily before we had a chance to replace them
with the loading menuitem, the second time the menu was opened).

Adding onHide should be straightforward. I'll add that to the todo list.


Daniel Kantor

unread,
Mar 25, 2010, 1:20:58 PM3/25/10
to Antony Sargent, Chromium-extensions
The way you have it is what I am thinking. I don't need to grey out any items that are already showing.  

karl

unread,
Mar 26, 2010, 6:02:34 PM3/26/10
to Chromium-extensions
> Perhaps if the extension hasn't responded within 200ms we'd put up a
> little dummy submenu with a greyed out item that says "loading..." or
> something like that.

I'm not so sure about that. In my case there will be items that are
always there (eg options, login/logout) and others that will take a
while to load (restore text items).
So if could specify a loading menu item myself, that would be more
flexible than having chrome decide for me.

> Adding onHide should be straightforward. I'll add that to the todo list.

Awesome thanks.
Karl

karl

unread,
Mar 28, 2010, 10:24:56 PM3/28/10
to Chromium-extensions
It would be really nice to have for my user case:
* user wants to restore text into a textbox so they right click on it
and open the Lazarus submenu
* menu lists the first line of the last 10 things they types into
textboxes on this domain
* when the mouse hovers over the menuitem, a tooltip shows up with the
first ~250 characters of the text they can restore (so they can be
sure this is the one they want, if more than one entry has the same
starting text).

If this is not easily achievable then don't worry about it, but if
it's a simple addition to the OS functions then I, for one, would find
it really useful.

Karl


On Mar 26, 12:22 am, PhistucK <phist...@gmail.com> wrote:
> I am not sure this is at all possible. This is really not the standard user
> experience (at least on Windows).
>
> ☆PhistucK
>
>
>
> On Thu, Mar 25, 2010 at 00:34, karl <k...@interclue.com> wrote:
> > Can we set tooltip text for menu item?
>
> > It would be useful to be able to show additional/help information when
> > the one line description isn't enough.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Chromium-extensions" group.

> > To post to this group, send email to chromium-extensi...@chromium.org.


> > To unsubscribe from this group, send email to

> > chromium-extensions+unsubscr...@chromium.org<chromium-extensions%2Bunsubscr...@chromium.org>

Mohamed Mansour

unread,
Apr 14, 2010, 9:41:00 PM4/14/10
to Antony Sargent, Chromium-extensions
Hi Antony,

This might be a bug, but is there a reason why the "id" of a contextMenu keeps increasing after each "reload", "disable/enable", and "uninstall/reinstall". But it resets to "1" when I restart the browser?

What I want to do is have an option where the user can enable/disable the context menu. It would be nice if I can specify the "id" of the context menu programmatically so I can refer to it after for removal. I know I can save the "id" as a global variable from the callback, but it would have been nice if we can specify the "id" in the "createProperties".

The context menu's are great!

Thanks!

-
Mohamed Mansour
m...@chromium.org



--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.

Antony Sargent

unread,
Apr 15, 2010, 1:53:15 PM4/15/10
to Mohamed Mansour, Chromium-extensions
I needed some kind of globally unique id in the browser process to associate with each extension context menu item, so the simplest thing to do was use an in-memory integer that is incremented each time an item is created (by any extension). Your code shouldn't really make any assumptions about the id's.

Being able to enable/disable should get a lot easier though when I land support for an update() function which will let you modify an existing item. I have the code mostly written and should be getting it reviewed and checked in soon.

Mohamed Mansour

unread,
Apr 15, 2010, 4:05:14 PM4/15/10
to Antony Sargent, Chromium-extensions
Ah I see, thats great! How would we refer to an "existing" item?

I was hoping there was a "quick" way to refer a context menu so I could mark it for removal or for update (after you land your change). For example, say I am creating 10 context menus, and its customizable by user. The only way to do this, is to programmatically keeping track of the "id" of each context menu creation and storing the value somewhere globally. If there was a way to iterate the available context menu's installed in my extension, that would make the API easier to deal with, not saying creating global variables is hard :)

Thanks!

-
Mohamed Mansour
m...@chromium.org

Jeff Timanus

unread,
Apr 15, 2010, 4:19:31 PM4/15/10
to Mohamed Mansour, Antony Sargent, Chromium-extensions
Hi All,

I just got caught-up on the contents of this thread, and I wanted to make sure that everyone is aware of another experimental API that can be used to implement context-menu-like functionality.  There is an experimental popup Chrome extension API that has been implemented for Windows that allows for display of a single top-level window hosting an extension view.  There is not explicit support for menu items, but since it is hosting a render-view, any context-menu system could be implemented via it.

The implementation is mostly in browser\extensions\extension_popup_api.cc.  Also, see the current API declaration in chrome\common\extensions\api\extension_api.json.

Note that this API is also still in a very experimental state and may not end up in Chromium.

I hope that this does not overlap too much with your efforts, Antony.

Jeff

Antony Sargent

unread,
Apr 15, 2010, 5:28:44 PM4/15/10
to Mohamed Mansour, Chromium-extensions
On Thu, Apr 15, 2010 at 1:05 PM, Mohamed Mansour <m0.inte...@gmail.com> wrote:
Ah I see, thats great! How would we refer to an "existing" item?

You'll refer to existing items by the id assigned by the create function. So you'd do:

// Create an item
var item_id;
chrome.experimental.contextMenu.create({ ... properties ... }, function(id) {
  item_id = id;
});

// Later on, update the item
chrome.experimental.contextMenu.update(item_id, { ... new properties ... });

I was hoping there was a "quick" way to refer a context menu so I could mark it for removal or for update (after you land your change). For example, say I am creating 10 context menus, and its customizable by user. The only way to do this, is to programmatically keeping track of the "id" of each context menu creation and storing the value somewhere globally. If there was a way to iterate the available context menu's installed in my extension, that would make the API easier to deal with, not saying creating global variables is hard :)


At the moment the easiest way to do this might be to just delete all your items and recreate them with the new properties. Something like this:

var item_ids = [];

function removeItems() {
  for (var i in item_ids) {
    chrome.experimental.contextMenu.remove(item_ids[i]);
  }
}

function createItems(items_to_create) {
  removeItems();
  for (var i in items_to_create) {
    var item = items_to_create[i];
    chrome.experimental.conextMenu.create(item, function(id) {
      item_ids.push(id);
    });
  }
}


In the future if people think it would be useful we could also add a "getItems" method that returns back to you the items you've created, including their id's. 

Antony Sargent

unread,
Apr 15, 2010, 5:31:32 PM4/15/10
to Jeff Timanus, Mohamed Mansour, Chromium-extensions
On Thu, Apr 15, 2010 at 1:19 PM, Jeff Timanus <jeff.t...@gmail.com> wrote:
Hi All,

I just got caught-up on the contents of this thread, and I wanted to make sure that everyone is aware of another experimental API that can be used to implement context-menu-like functionality.  There is an experimental popup Chrome extension API that has been implemented for Windows that allows for display of a single top-level window hosting an extension view.  There is not explicit support for menu items, but since it is hosting a render-view, any context-menu system could be implemented via it.

The implementation is mostly in browser\extensions\extension_popup_api.cc.  Also, see the current API declaration in chrome\common\extensions\api\extension_api.json.

Note that this API is also still in a very experimental state and may not end up in Chromium.

I hope that this does not overlap too much with your efforts, Antony.

No problem, this is a cool looking API that could nicely complement context menus and infobars. If you'd like to get more feedback from the list I'd encourage you to start a new thread, and perhaps include a simple sample or two that uses the API.

PhistucK

unread,
Apr 16, 2010, 9:10:44 AM4/16/10
to Jeff Timanus, Mohamed Mansour, Antony Sargent, Chromium-extensions
Well, the fact that it is Windows only kind of makes it not so usable, I would say...
When will this be implemented for other platforms?

☆PhistucK

Zach Williams

unread,
May 3, 2010, 12:10:34 AM5/3/10
to Chromium-extensions

I have another suggestion / question.

When trying to use the context menu API within a loop, I run into a
'counting' problem.

// creates a temporary array of item names
var myArray = new Array('item 1', 'item 2', 'item 3');

// starts the loop for the length of myArray
for(i=0;i<ltsar.length;i++) {
// gets the correct item title from the array and sets it to a
variable
var titleThis = ltsar[i];

//creates the context menu item with the correct title
chrome.experimental.contextMenu.create({
"title": titleThis,
"contexts": ["EDITABLE"]
}, function(menuItemId) {
console.log('menuItemId = ' + menuItemId + ' + titleThis = ' +
titleThis)});
// outputs :
// menuItemId = 252 + titleThis = item 6
// menuItemId = 253 + titleThis = item 6
// menuItemId = 254 + titleThis = item 6
//
// should output:
// menuItemId = 252 + titleThis = item 1
// menuItemId = 253 + titleThis = item 2
// menuItemId = 254 + titleThis = item 3
}

Why is it doing this?

ALSO, there should be a way to get the title of the context menu
title.

for example:
function contextMenuItemCallback (info, tab) {
console.log("The context menu item's title is: " +
info.menuItemTitle)

PhistucK

unread,
May 3, 2010, 12:19:14 AM5/3/10
to Zach Williams, Chromium-extensions
I believe this is happening because the "chrome.experimental.contextMenu.create" function is asynchronous.
It probably gets executed after the for(...) has already completed.
Also, the callback function is surely asynchronous.
 
☆PhistucK

Coolio

unread,
May 10, 2010, 3:00:02 AM5/10/10
to Chromium-extensions
Hi Antony

Great API!

Is there any chance that menu items doesnt appear on Extensions
Manager (chrome://extensions/) nor Extensions Options?
Currently I am using "contexts": ['PAGE'] and menu items appears on
those pages, but can't be used, so it will be much better if they
simple doesn't appear at all.

Thanks!

On Mar 24, 3:35 pm, Antony Sargent <asarg...@chromium.org> wrote:
> Hello all-
>
> I just landed a first cut of support for an experimental context menu API
> and would like to get some feedback.
>
> The design document is here:http://dev.chromium.org/developers/design-documents/extensions/contex...

Antony Sargent

unread,
May 17, 2010, 11:50:51 PM5/17/10
to Coolio, Chromium-extensions
Yes, eventually we'll be adding a way to limit where an item will show up, possibly by either tabid or url match pattern or both.

twinsen

unread,
Jun 18, 2010, 11:02:33 AM6/18/10
to Chromium-extensions
I had a similar problem.
It happens because you don't know when function(menuItemId) will be
called.
titleThis gets set correctly in the for loop scope (and the creation
parameters), but that callback will be executed sometime later, when
titleThis has already changed.
This issue isn't specific to, its the nature of using javascript
callbacks - you have to carefully chain them.

twinsen

unread,
Jun 18, 2010, 11:14:46 AM6/18/10
to Chromium-extensions
-Does this give you enough functionality to build something useful?
Yep I can do everything I want (however hooking up data to the menu
item was tricky).

There are a few minor improvements that could be made:
* Able to retrieve the createProperties from a menuItemId.
* Able to store one "custom data" object in createProperties.
* Since you can get the menuItemId from the onclick object you would
then be able to access everything you need for the menu.
I've managed to do everything I want with the current API - I just
have to maintain a hashtable of menuItemId->custom data objects.

I'll release my experimental extension shortly. For some reason the
chromeplugins.org website has been down all day so I couldn't update
the "view source with" thread:
http://www.chromeplugins.org/google/chrome-plugins/new-ext-view-source-9849.html#post24618
The experimental edition allows access to the menu via a context menu
(all dynamically populated).

Thangaraju

unread,
Jun 18, 2010, 4:52:04 PM6/18/10
to Chromium-extensions

I believe this is happening because, in this case, a closure has been
created, which refers the latest value during execution of the closure
function.
This could be solved using a callback generator function.

function callbackGenerator(titleThis) {
return function(menuItemId) {
console.log('menuItemId = ' + menuItemId + ' + titleThis = ' +
titleThis);
// Do some more stuff........................
}
}

// creates a temporary array of item names
var myArray = ['item 1', 'item 2', 'item 3'];
// starts the loop for the length of myArray
for ( i = 0; i < myArray.length; i++) {
var titleThis = ltsar[i];
//creates the context menu item with the correct title
chrome.experimental.contextMenu.create({
"title": titleThis,
"contexts": ["EDITABLE"]
}, callbackGenerator(titleThis));
}

The above code will work as expected, though I did not test. Someone
can correct me if I miss something

BEWARE of accidental CLOSURE.
Use the power of closure effectively.

Hope this will help.
Thanks
Thangaraju Ramasamy

On May 3, 9:10 am, Zach Williams <cooldudez...@gmail.com> wrote:
> I have another suggestion / question.
>
> When trying to use thecontextmenuAPIwithin a loop, I run into a
> 'counting' problem.
>
> // creates a temporary array of item names
> var myArray = new Array('item 1', 'item 2', 'item 3');
>
> // starts the loop for the length of myArray
> for(i=0;i<ltsar.length;i++) {
>         // gets the correct item title from the array and sets it to a
> variable
>         var titleThis = ltsar[i];
>
>         //creates thecontextmenu item with the correct title
>         chrome.experimental.contextMenu.create({
>                 "title": titleThis,
>                 "contexts": ["EDITABLE"]
>         }, function(menuItemId) {
>                 console.log('menuItemId = ' + menuItemId + ' + titleThis = ' +
> titleThis)});
>                 // outputs :
>                 // menuItemId = 252 + titleThis = item 6
>                 // menuItemId = 253 + titleThis = item 6
>                 // menuItemId = 254 + titleThis = item 6
>                 //
>                 // should output:
>                 // menuItemId = 252 + titleThis = item 1
>                 // menuItemId = 253 + titleThis = item 2
>                 // menuItemId = 254 + titleThis = item 3
>
> }
>
> Why is it doing this?
>
> ALSO, there should be a way to get the title of thecontextmenu
> title.
>
> for example:
> function contextMenuItemCallback (info, tab) {
>         console.log("Thecontextmenu item's title is: " +
> info.menuItemTitle)
>
> }
>
> --
> You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
> To post to this group, send email to chromium-extensi...@chromium.org.
> To unsubscribe from this group, send email to chromium-extensions+unsubscr...@chromium.org.

twinsen

unread,
Aug 7, 2010, 2:45:35 AM8/7/10
to Chromium-extensions
Since context menus have been moved out of the experimental apis they
have become unusable for my extensions.
I relied on contex menus working for file:// urls and now they don't
have permission to be created on those urls (even with
documentUrlPatterns passed to chrome.contextMenus.create - "file://*/
*" patterns are considered invalid). So the only option I have for
newer versions of chrome is to use drop down menus from the browser
actions!
I am currently using chrome 6.0.472.14 dev.

PhistucK

unread,
Aug 7, 2010, 2:58:40 AM8/7/10
to twinsen, Chromium-extensions
There is a newer version (just out) - 6.0.472.25. Try that, though, no guarantee.

☆PhistucK


--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.

Antony Sargent

unread,
Aug 9, 2010, 6:09:11 PM8/9/10
to twinsen, Chromium-extensions
Sorry, I should have given a heads up about this change. 

We decided to restrict context menu items to appearing on http/https pages only for now, but are considering widening that in Chrome 7 to allow file:// and chrome-extension:// (at least for an extension's own pages). 


--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.

akira

unread,
Sep 4, 2010, 3:21:34 AM9/4/10
to Chromium-extensions
Now that Chrome 6 is out, can we assume that this API is official and
there won't be any retraction of features released so far? (trivial
things aside)

Akira

PhistucK

unread,
Sep 4, 2010, 4:12:25 AM9/4/10
to akira, Chromium-extensions
Yes, that is the intention, anyway.

PhistucK




--
Reply all
Reply to author
Forward
0 new messages