chrome.experimental.debugger documentation: events are not per tab

1,242 views
Skip to first unread message

johnjbarton

unread,
Nov 1, 2011, 12:32:34 PM11/1/11
to google-chrome-...@googlegroups.com
When reading these paragraphs

----

Debugger API serves as an alternate transport for Chrome's remote debugging protocol. Use debugger to attach to a tab, instrument its network interaction, debug JavaScript, mutate page's DOM and CSS, etc.

As of today, attaching to the tab by means of the debugger API and using embedded Chrome DevTools with that tab are mutually exclusive. If user invokes Chrome DevTools while extension is attached to the tab, debugging session is terminated. Extension can re-establish it later.

----
on this page:
http://code.google.com/chrome/extensions/trunk/experimental.debugger.html

I came away with the impression that the chrome.experimental.debugger api was "bound to a tab". That is, when you "attach to the tab" the events you receive come from the tab you attached to. I was mistaken: when you pass an event listener via
chrome.experimental.debugger.onEvent.addListener(), that listener will be called for all tabs with attached debugger instances, not just the one you attached to. For example, if you have two windows that call attach() with two different tab ids, then call addListener with two different listeners (of course in separate windows), then both windows will see all events from both tabs.  This was especially surprising to me because I had gotten the API to work with one window, moved on to other parts of the app, then tried two windows. So it took me a while to realize why the two debugger windows have the same data ;-).

jjb


pfeldman

unread,
Nov 1, 2011, 12:50:23 PM11/1/11
to Google Chrome Developer Tools
That's right, events are per extension. This is somewhat a style of
the Chrome Extensions API. I thought it was pretty clear given that
API does not allow you subscribing to a particular _tab_ events. What
are 'windows' in your case?

Regards
Pavel

John J Barton

unread,
Nov 1, 2011, 1:03:48 PM11/1/11
to pfeldman, Google Chrome Developer Tools
On Tue, Nov 1, 2011 at 9:50 AM, pfeldman <pfel...@chromium.org> wrote:
> That's right, events are per extension. This is somewhat a style of
> the Chrome Extensions API. I thought it was pretty clear given that
> API does not allow you subscribing to a particular _tab_ events.

I'm not sure why you say that, the API uses
chrome.experimental.debugger.attach(Debuggee target, string
requiredVersion, function callback)
and target is just tabId inside of an object.

In addition, I guess I was thrown of track by the remote debug
protocol, which never mentions tab id. It has a rich API so it
commands a lot of attention. So in my mind the debugger was 'attached'
to a tab and everything after that was within a tab.

> What
> are 'windows' in your case?

I call
chrome.windows.create(createData);
twice from background.html, then call the debugger.attach() in the result.

jjb

pfeldman

unread,
Nov 1, 2011, 1:10:59 PM11/1/11
to Google Chrome Developer Tools
> I'm not sure why you say that, the API uses
> chrome.experimental.debugger.attach(Debuggee target, string
> requiredVersion, function callback)

You are saying that both callbacks got the attach ack? I was talking
about chrome.experimental.debugger.onEvent - that one has no notion of
tabId.

> In addition, I guess I was thrown of track by the remote debug
> protocol, which never mentions tab id. It has a rich API so it
> commands a lot of attention. So in my mind the debugger was 'attached'
> to a tab and everything after that was within a tab.

That's pretty much the idea. chrome.experimental.debugger is just a
transport for the protocol messages.

>
> > What
> > are 'windows' in your case?
>
> I call
>   chrome.windows.create(createData);
> twice from background.html, then call the debugger.attach() in the result.

Makes sense, this is still single extension, both onEvent handlers
will be receiving events since you were not specifying the tabs while
subscribing.

>
> jjb

John J Barton

unread,
Nov 1, 2011, 1:32:30 PM11/1/11
to pfeldman, Google Chrome Developer Tools
On Tue, Nov 1, 2011 at 10:10 AM, pfeldman <pfel...@chromium.org> wrote:
>> I'm not sure why you say that, the API uses
>> chrome.experimental.debugger.attach(Debuggee target, string
>> requiredVersion, function callback)
>
> You are saying that both callbacks got the attach ack?

I don't know what you mean here. According to the doc page, the
|callback| above is only called if there is an error.

> I was talking
> about chrome.experimental.debugger.onEvent - that one has no notion of
> tabId.

When I wrote the code I did not think much about onEvent. I was trying
to decipher the relationship between chrome.experimental.debugger and
the remote protocol. So in my onEvent handler I immediately call
another method in an object organized around the remote protocol. I
assumed the tabId argument was just a convenience. After all I already
supplied the target tabId in the attach() call.

>
>> In addition, I guess I was thrown of track by the remote debug
>> protocol, which never mentions tab id. It has a rich API so it
>> commands a lot of attention. So in my mind the debugger was 'attached'
>> to a tab and everything after that was within a tab.
>
> That's pretty much the idea. chrome.experimental.debugger is just a
> transport for the protocol messages.

But unlike the socket protocol, this one is not bound to a tab on
creation. Hence my confusion.

jjb

pfeldman

unread,
Nov 1, 2011, 1:49:04 PM11/1/11
to Google Chrome Developer Tools
> > You are saying that both callbacks got the attach ack?
>
> I don't know what you mean here. According to the doc page, the
> |callback| above is only called if there is an error.
>

I can't find this 'only' bit you are referring to. After all,
asynchronous error handler suggests that you should not proceed with
the interaction unless your attach succeeded.

> > I was talking
> > about chrome.experimental.debugger.onEvent - that one has no notion of
> > tabId.
>
> When I wrote the code I did not think much about onEvent. I was trying
> to decipher the relationship between chrome.experimental.debugger and
> the remote protocol. So in my onEvent handler I immediately call
> another method in an object organized around the remote protocol.

Well, this is a static dispatcher, you should care. My hope is that
Chrome Extensions authors have learned this already (probably the hard
way).

I
> assumed the tabId argument was just a convenience. After all I already
> supplied the target tabId in the attach() call.

Which was also static. Unfortunately, there is no "DebuggerSession"
object that would expose debugging API per connection. I would be in
favor of one, but this is against the Chrome Extensions API style.

John J Barton

unread,
Nov 1, 2011, 2:17:59 PM11/1/11
to pfeldman, Google Chrome Developer Tools
On Tue, Nov 1, 2011 at 10:49 AM, pfeldman <pfel...@chromium.org> wrote:
>> > You are saying that both callbacks got the attach ack?
>>
>> I don't know what you mean here. According to the doc page, the
>> |callback| above is only called if there is an error.
>>
>
> I can't find this 'only' bit you are referring to. After all,
> asynchronous error handler suggests that you should not proceed with
> the interaction unless your attach succeeded.

The doc says:
----
callback
( optional function )
If an error occurs while attaching to the target, the callback
will be called with no arguments and chrome.extension.lastError will
be set to the error message.
---
There is no "else". I have to use the Debugger.debuggerWasEnabled
event to confirm the connection.

>
>> > I was talking
>> > about chrome.experimental.debugger.onEvent - that one has no notion of
>> > tabId.
>>
>> When I wrote the code I did not think much about onEvent. I was trying
>> to decipher the relationship between chrome.experimental.debugger and
>> the remote protocol. So in my onEvent handler I immediately call
>> another method in an object organized around the remote protocol.
>
> Well, this is a static dispatcher, you should care. My hope is that
> Chrome Extensions authors have learned this already (probably the hard
> way).

Well for what it's worth I am not a Chrome Extension author.
chrome.experimental.debugger was my first attempt.

jjb

Andrey Kosyakov

unread,
Nov 1, 2011, 3:31:07 PM11/1/11
to John J Barton, pfeldman, Google Chrome Developer Tools
On Tue, Nov 1, 2011 at 10:17 PM, John J Barton
<johnj...@johnjbarton.com> wrote:
> On Tue, Nov 1, 2011 at 10:49 AM, pfeldman <pfel...@chromium.org> wrote:

>> Well, this is a static dispatcher, you should care. My hope is that
>> Chrome Extensions authors have learned this already (probably the hard
>> way).
>
> Well for what it's worth I am not a Chrome Extension author.
> chrome.experimental.debugger was my first attempt.
>

We had a similar concern while discussing the options to implement
chrome.devtools.* APIs: exposing interface to multiple possible
debuggees into a single background page (or, for that matter, any
extension page that shares global events) is inherently confusing. It
could possibly be addressed by using a debuggee-specific event object
(e.g. returned by an attach() call) instead of the global one, but
that would go against the procedural style of chrome.* APIs
(chrome.devtools.* do; some are unhappy about this).
On the other hand, if you regard chrome.debugger.* as a drop-in
replacement for the WebSocket interface, this is probably ok, as one
would face very similar problems while using a socket. It's a
low-level API anyway, mastering the protocol is going to bring
additional challenges for many anyway.
In the long term, if we have an OO-style SDK to use as an abstraction
of the protocol, it would be perfectly natural to address the problem
there.

Best regards,
Andrey.

John J Barton

unread,
Nov 1, 2011, 3:57:56 PM11/1/11
to Andrey Kosyakov, pfeldman, Google Chrome Developer Tools

In the meantime a couple of small changes to the doc pages would help:

1. on http://code.google.com/chrome/extensions/trunk/experimental.debugger.html
Notes:

"Debugger API serves as an alternate transport for Chrome's remote
debugging protocol. Use debugger to attach to a tab, instrument its
network interaction, debug JavaScript, mutate page's DOM and CSS, etc.
"

could be:

Debugger API serves as an alternate transport for Chrome's remote

debugging protocol. Use chrome.debugger to attach to one or more tabs
to instrument network interaction, debug JavaScript, mutate the DOM
and CSS, etc.
Use the Debuggee tabId to target tabs with sendCommand and route
events by tabId from onEvent callbacks.

2. http://code.google.com/chrome/extensions/trunk/experimental.debugger.html#method-attach

"callback
( optional function )
If an error occurs while attaching to the target, the callback
will be called with no arguments and chrome.extension.lastError will
be set to the error message."

could be (assuming that the callback is called always??)


"callback
( optional function )

Called once the attach operation succeeds or fails. No arguments
are passed to the callback. If the attach fails,


chrome.extension.lastError will be set to the error message"

HTH,
jjb

pfeldman

unread,
Nov 1, 2011, 4:31:36 PM11/1/11
to Google Chrome Developer Tools
Thanks! I'll fix the docs.

Regards
Pavel

johnjbarton

unread,
Nov 2, 2011, 12:59:48 AM11/2/11
to google-chrome-...@googlegroups.com, pfeldman


On Tuesday, November 1, 2011 11:17:59 AM UTC-7, johnjbarton wrote:
> I can't find this 'only' bit you are referring to. After all,
> asynchronous error handler suggests that you should not proceed with
> the interaction unless your attach succeeded.

Hmm... maybe I misunderstood you here.

I changed my code to call  Debugger.enable from within the callback of
chrome.experimental.debugger.attach(integer tabId, function callback)

I'm pretty sure this does not work now. It seems reasonable, but I don't get "Debugger.debuggerWasEnabled" unless I put alert() in the callback. Without the alert I sometimes (but not every time) get Debugger is not attached to the tab with id: 200.

jjb




johnjbarton

unread,
Nov 2, 2011, 5:12:25 PM11/2/11
to google-chrome-...@googlegroups.com, pfeldman

Ok I got my code to work again.

The following sequence does not work
  sendRequest for Debugger.enable
  chrome.tabs.update the debuggee page
The Debugger.debuggerWasEnabled never arrives and sometimes the above (nonsense) error message is emitted. The Debugger is not enabled.

The following sequence does work:
  sendRequest for Debugger.enable
  wait for response Debugger.debuggerWasEnabled
  chrome.tabs.update the debuggee page

I don't think this makes complete sense. I think at worst I would miss some events. But somehow if I don't wait for the response, the debugger is not enabled.

jjb

pfeldman

unread,
Nov 8, 2011, 4:15:07 AM11/8/11
to Google Chrome Developer Tools
[Note that debuggerWasEnabled is not documented experimental event, we
are planning to remove it]

tl;dr: You should not assume that the debugger has been enabled unless
Debugger.enable callback is invoked.

In your case, chrome.tabs.update operates on the browser level and
nukes the entire renderer process. We don't have a chance to propagate
the new renderer state to the browser so that we could restore it post
navigation.

Regards
Pavel

John J Barton

unread,
Nov 8, 2011, 12:49:42 PM11/8/11
to pfeldman, Google Chrome Developer Tools
On Tue, Nov 8, 2011 at 1:15 AM, pfeldman <pfel...@chromium.org> wrote:
> [Note that debuggerWasEnabled is not documented experimental event, we
> are planning to remove it]

? You're confusing me here. If it was not documented how did I read it
in the documentation and decide to write code to detect it?

But it does not matter, I removed the debuggerWasEnabled approach last week.

>
> tl;dr: You should not assume that the debugger has been enabled unless
> Debugger.enable callback is invoked.

This would be a great line to add to the documentation for enable(). I
know it seems obvious now, but with async APIs the caller generally
wants to issue as many parallel requests as possible.

>
> In your case, chrome.tabs.update operates on the browser level and
> nukes the entire renderer process. We don't have a chance to propagate
> the new renderer state to the browser so that we could restore it post
> navigation.

A 'nice to have' would be a categorization of operations that can
proceed in parallel with debugger requests, including "no operations
what so ever".

jjb

Reply all
Reply to author
Forward
0 new messages