Bug 35016

Summary: Enable alternate front-ends for Web Inspector
Product: WebKit Reporter: Jamey Hicks <jamey.hicks>
Component: Web Inspector (Deprecated)Assignee: Nobody <webkit-unassigned>
Status: RESOLVED INVALID    
Severity: Enhancement CC: burg, bweinstein, eostroukhov, joepeck, keishi, laszlo.gombos, pfeldman, pmuellr, rik, yael, yurys, zalan
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Attachments:
Description Flags
Patch that enables use of alternate inspector frontends
pfeldman: review-
Qt debug agent partially implementing ChromeDevTools and V8 debug protocol
none
Web Inspector current architecture
none
Web Inspector architecture with patch 48854 applied
none
Web Inspector UI remoted via HTTP with this patch plus additional components
none
Eclipse or Aptana debugging using inspector backend and ChromeDevTools/V8DebuggerProtocol none

Description Jamey Hicks 2010-02-16 19:31:20 PST
Created attachment 48854 [details]
Patch that enables use of alternate inspector frontends

Converted InspectorFrontend to an abstract base class. Moved previous implementation to InspectorInprocessFrontend. Debug agents providing alternate frontends may register them via  InspectorController::setInspectorFrontend.

This is the first in a series of patches that will enable out-of-process debug using either Eclipse Chrome Debugger or Web Inspector remoted via HTTP.
Comment 1 Pavel Feldman 2010-02-17 00:22:59 PST
Comment on attachment 48854 [details]
Patch that enables use of alternate inspector frontends

Jamey, there is already work in progress on this one. Let me provide you with some context:

Chromium is already using a custom front-end that is backed with the out-of-process implementation. The way it is achieved is that setFrontendProxyObject is being called and it injects a special js object that is sending information over the wire. So technically it is possible and there is a working product using this approach. It was myself to serialize all the inspector interaction, extract InspectorFrontend abstraction, re-work large chunks of the front-end to allow only asynchronous operations between the two. So we (chrome dev tools authors) have been continuously working on achieving this goal for half a year or so. Some of our work is still in progress (such as splitting InspectorClient into InspectorClient and InspectorFrontendClient) since these parities are potentially operating in different processes (on different devices).

Our present plan in fact is to allow remote debugging of the device using existing front-end, it is ourselves developing Eclipse Chrome Debugger you are talking about, we have some plans on merging the protocols there (it currently only supports v8 raw debugging protocol). Sounds familiar?

Anyways, I would encourage you to start with a design doc in this bug and sync up with pfeldman@chromium.org and yurys@chromium.org before you start sending patches. We are both working on Chromium Dev Tools from St.Petersburg (similar TZ as you?), so we should be able to sync up with no problem. If you can spend some cycles on this, it would be great. We have a lot of work. I can see that you are already familiar with the code, so your help would be greatly appreciated!
Comment 2 Patrick Mueller 2010-02-17 03:54:29 PST
I was also going to suggest providing an overall design doc, in some form.

Pavel, do you have a design doc for the direction you're heading?  I probably have some cycles to spend here.
Comment 3 Jamey Hicks 2010-02-17 05:39:16 PST
I'll add a design document. We discussed implementing the debug agent / protocol adapter in Javascript, but it seemed cleaner to stick to a native implementation.

I am in favor of cleaning up Web Inspector's backend interface so that it would be easier to support different debuggers, including:
1) Web Inspector in-process
2) Web Inspector remote (e.g., via HTTP)
3) Chrome Dev Tools protocol (with V8 debug)
4) Aptana via Chrome Dev Tools protocol
5) Dreamweaver

I have a prototype of Web Inspector remoted via HTTP using Qt/Webkit 4.6. I would be happy to post that patch.

I have the beginnings of Chrome Dev Tools protocol with the V8 debugger protocol. You can attach the debugger, set and clear breakpoints, and I am working on the backtrace command. It is a work in progress, but I would be happy to attach that patch as well.
Comment 4 Pavel Feldman 2010-02-17 06:20:49 PST
(In reply to comment #3)
> I'll add a design document. We discussed implementing the debug agent /
> protocol adapter in Javascript, but it seemed cleaner to stick to a native
> implementation.
>

It does not seem cleaner to me and here is why. We'd like to define a protocol for the interaction between the backend and the front-end. This protocol is likely to use JSON for the message content. Today WebCore contains both backend and the front-end pieces and defines the interchange "API". We'd like to leave specifics to the WebCore and make inspector clients/hosts serve backend-frontend transport needs only without cracking the messages.

Today, InspectorFrontend is a guy sitting on the backend side that is serializing messages for the front-end into the standard protocol format. It does not make much sense to make it pluggable since its responsibility is very narrow. What you need is to take these JSON messages and send them over the pipe. That's basically a reason for r-.
 
> I am in favor of cleaning up Web Inspector's backend interface so that it would
> be easier to support different debuggers, including:
> 1) Web Inspector in-process
> 2) Web Inspector remote (e.g., via HTTP)

(1) and (2) is our goal as well as mentioned in my previous message.

> 3) Chrome Dev Tools protocol (with V8 debug)

This one is not clear to me. We are currently changing v8 debugger and profiler so that it conformed same apis as in (1) and (2). See ScriptProfiler / ScriptDebugger classes that are being added in bindings.

> 4) Aptana via Chrome Dev Tools protocol

We are thinking of switching from Chrome Dev Tools protocol to the same protocol as in (1), (2) and (3) in Eclipse SDK when protocol is mature enough.

> 5) Dreamweaver
> 

Please explain what exactly you are suggesting here.

> I have a prototype of Web Inspector remoted via HTTP using Qt/Webkit 4.6. I
> would be happy to post that patch.
>

That's great!

> I have the beginnings of Chrome Dev Tools protocol with the V8 debugger
> protocol. You can attach the debugger, set and clear breakpoints, and I am
> working on the backtrace command. It is a work in progress, but I would be
> happy to attach that patch as well.

It is not clear why you need this one. Could you please describe the scenario?
Comment 5 Jamey Hicks 2010-02-17 10:58:46 PST
Created attachment 48913 [details]
Qt debug agent partially implementing ChromeDevTools and V8 debug protocol

For reference: This is a patch to Qt that implements remote Web Inspector usage, supporting all Web Inspector functionality. It is a quick prototype and not stable.

It includes an HTTP server in QWebInspector that can be enabled for remote debug. It serves 4 information channels through the HTTP server:
1) Built-in resource files -- the HTML, Javascript, images, and style sheets composing the Web Inspector UI (original encoding)
2) Asynchronous RPC to InspectorBackend via HTTP POST (encoded as JSON)
3) Polling for events to the frontend via HTTP POST (encoded as JSON)
4) Dynamic resources via HTTP POST (to fetch these resources from the same context as the browser, in original encoding)

The Inspector front-end javascript is modified to use asynchronous style when communicating with the back-end.

In my current design, the remote debug agent would not require instantiating the Page for the Web Inspector UI nor would it require QWebInspector.

In terms of implementation, it was very quick because it does not change the messages or encodings between the backend and UI, though use of XMLHttpRequest caused a change to an asynchronous style of communication.
Comment 6 Pavel Feldman 2010-02-17 12:11:58 PST
(In reply to comment #5)
> Created an attachment (id=48913) [details]
> Qt debug agent partially implementing ChromeDevTools and V8 debug protocol
> 
> For reference: This is a patch to Qt that implements remote Web Inspector
> usage, supporting all Web Inspector functionality. It is a quick prototype and
> not stable.
> 
> It includes an HTTP server in QWebInspector that can be enabled for remote
> debug. It serves 4 information channels through the HTTP server:
> 1) Built-in resource files -- the HTML, Javascript, images, and style sheets
> composing the Web Inspector UI (original encoding)

Ok.

> 2) Asynchronous RPC to InspectorBackend via HTTP POST (encoded as JSON)

How do you deal with the calls to the InspectorFrontendHost? They are supposed to be served on the front-end side. Are you sending those to the inspected page side as well?

> 3) Polling for events to the frontend via HTTP POST (encoded as JSON)

Polling is not good - couldn't we just leave connection open and push client dispatches in the <script> tags?

> 4) Dynamic resources via HTTP POST (to fetch these resources from the same
> context as the browser, in original encoding)
> 

Could you explain what this is about?

> The Inspector front-end javascript is modified to use asynchronous style when
> communicating with the back-end.
> 

It took us a while (half a year of so) to re-implement entire front-end in order to serialize communication and make it asynchronous. What did you find missing? The only thing I can remember of is debuggerEnabled / profilerEnabled calls (we did not need these in Chromium). I had a pending change for that. Anyways, I can't see your changes in the patch.

> In my current design, the remote debug agent would not require instantiating
> the Page for the Web Inspector UI nor would it require QWebInspector.
> 

Yury is currently working on a change that would abstract creation of the inspector UI page via the InspectorClient interface. InspectorController will basically be asking for host to open inspector somewhere and will wait while this new front-end connects to it. Any external client (non-standard frontend) should also be able to connect using new API. It will be a modified version of setFrontendProxyObject.

> In terms of implementation, it was very quick because it does not change the
> messages or encodings between the backend and UI, though use of XMLHttpRequest
> caused a change to an asynchronous style of communication.

Where is this code located?


General notes:
- It would be interesting to see the server implementation and the front-end code. It is important to remember that inspector controller does not expose its protocol and that InspectorFrontend / InspectorBackend interfaces are private to WebCore (should not be accessed from within WebKit).
- Talking about supporting V8 protocol over InspectorBackend, it is something quite opposite from what we were thinking about. Instead, we were going to establish a scope-alike protocol in the WebKit first, let it mature and move Eclipse debugger to it.
- Eclipse ChromeDevTools / Chromium do not maintain debugging API in terms of protocol, they provide the support in terms of the SDK instead. Every new version of Chromium has an SDK update in case of breaking changes to the protocol. Your implementation is clearly not ready for that.
Comment 7 Jamey Hicks 2010-02-17 12:37:04 PST
Created attachment 48922 [details]
Web Inspector current architecture

Current Web Inspector archtiecture with process boundary and color coding for C++ / Javascript components
Comment 8 Jamey Hicks 2010-02-17 12:38:44 PST
Created attachment 48923 [details]
Web Inspector architecture with patch 48854 applied

Shows subclassing of InspectorFrontend for the direct communication path into the ScriptState of the Web Inspector UI Page.
Comment 9 Jamey Hicks 2010-02-17 12:41:12 PST
Created attachment 48924 [details]
Web Inspector UI remoted via HTTP with this patch plus additional components

Adds InspectorHttpServer as a component which receives information from InspectorController via InspectorRemoteFrontend. InspectorRemoteFrontend encodes the information in the same format but enqueues it to the HTTP server for deliver rather than injecting it into a ScriptState javascript environment.
Comment 10 Jamey Hicks 2010-02-17 12:45:37 PST
Created attachment 48925 [details]
Eclipse or Aptana debugging using inspector backend and ChromeDevTools/V8DebuggerProtocol

This configuration varies in two ways from the remote Web Inspector.

First, it uses a completely different UI for debug.

Second, it uses ChromeDevTools / V8DebuggingProtocol as the encoding.

I have no particular desire to use this particular encoding except that it is documented and has client side code that we can use. In a few days, we were able to use ChromeDevTools in Aptana to debug apps running in Chrome and would like to do the same with Qt/Webkit. Also, we plan to add support for profiling, etc. by mapping the existing inspector functionality onto the same wire encoding.
Comment 11 Pavel Feldman 2010-02-17 12:50:49 PST
(In reply to comment #8)
> Created an attachment (id=48923) [details]
> Web Inspector architecture with patch 48854 applied
> 
> Shows subclassing of InspectorFrontend for the direct communication path into
> the ScriptState of the Web Inspector UI Page.

I can see the subclassing, but that's not really what you want. All inspector frontend methods are dispatched into the "dispatch" script function calls with script value parameters. All that you need is to be able to use your ScriptFunctionCall that would serialize parameters. There already is a perfect tool for serializing ScriptValues that is JSON. So you don't really need any subclassing, just parametrized proxy object or pluggable ScriptFunctionCall version.
Comment 12 Jamey Hicks 2010-02-17 13:08:10 PST
(In reply to comment #6)
> (In reply to comment #5)
> > Created an attachment (id=48913) [details] [details]
> > Qt debug agent partially implementing ChromeDevTools and V8 debug protocol
> > 
> > For reference: This is a patch to Qt that implements remote Web Inspector
> > usage, supporting all Web Inspector functionality. It is a quick prototype and
> > not stable.
> > 
> > It includes an HTTP server in QWebInspector that can be enabled for remote
> > debug. It serves 4 information channels through the HTTP server:
> > 1) Built-in resource files -- the HTML, Javascript, images, and style sheets
> > composing the Web Inspector UI (original encoding)
> 
> Ok.
> 
> > 2) Asynchronous RPC to InspectorBackend via HTTP POST (encoded as JSON)
> 
> How do you deal with the calls to the InspectorFrontendHost? They are supposed
> to be served on the front-end side. Are you sending those to the inspected page
> side as well?

Qt 4.6 uses an older version of WebKit that does not yet have
InspectorFrontendHost, so I did not encounter this problem. I do not have a
solution for this problem, but InspectorFrontendHost should be in the
process/page of the UI, not the backend.

> 
> > 3) Polling for events to the frontend via HTTP POST (encoded as JSON)
> 
> Polling is not good - couldn't we just leave connection open and push client
> dispatches in the <script> tags?

That would be an improvement. I am still learning how to do some of these
things in Javascript. In my prototype, I believe it delivers all the items that
are in the InspectorRemoteFrontend's queue each time a POST is handled, and it
keeps a POST open until there is some data. I'm sure a slight tweak would allow
that connection to be kept open for the duration of the debug session.

> > 4) Dynamic resources via HTTP POST (to fetch these resources from the same
> > context as the browser, in original encoding)
> > 
> 
> Could you explain what this is about?

Currently, the Web Inspector UI fetches resources in its own page context when
the user wants to see them. If those were local file URLs, for example, and the
UI is running on a different device, then it cannot fetch them. This interface
enables the UI to fetch resources in same context as the inspected page so that
it gets the same thing the inspected page would get. This was a tiny change to
the UI.

> > The Inspector front-end javascript is modified to use asynchronous style when
> > communicating with the back-end.
> > 
> 
> It took us a while (half a year of so) to re-implement entire front-end in
> order to serialize communication and make it asynchronous. What did you find
> missing? The only thing I can remember of is debuggerEnabled / profilerEnabled
> calls (we did not need these in Chromium). I had a pending change for that.
> Anyways, I can't see your changes in the patch.

I'm pretty sure that some of the changes I made here were not needed, but I did
not understand the code before I started. However, there were some calls to
WebInspector.InspectorController methods that were expecting to be synchronous.
Again, this is using an older webkit snapshot.

> > In my current design, the remote debug agent would not require instantiating
> > the Page for the Web Inspector UI nor would it require QWebInspector.
> > 
> 
> Yury is currently working on a change that would abstract creation of the
> inspector UI page via the InspectorClient interface. InspectorController will
> basically be asking for host to open inspector somewhere and will wait while
> this new front-end connects to it. Any external client (non-standard frontend)
> should also be able to connect using new API. It will be a modified version of
> setFrontendProxyObject.
> 
> > In terms of implementation, it was very quick because it does not change the
> > messages or encodings between the backend and UI, though use of XMLHttpRequest
> > caused a change to an asynchronous style of communication.
> 
> Where is this code located?

In patch 48913, webkit is in src/3rdparty/webkit and the debug server is in
src/3rdparty/webkit/WebKit/qt/WebCoreSupport. It is just a proof of concept.

> 
> General notes:
> - It would be interesting to see the server implementation and the front-end
> code. It is important to remember that inspector controller does not expose its
> protocol and that InspectorFrontend / InspectorBackend interfaces are private
> to WebCore (should not be accessed from within WebKit).

In that case, I think we need to develop a stable inspector backend interface
to be exported from WebCore.

> - Talking about supporting V8 protocol over InspectorBackend, it is something
> quite opposite from what we were thinking about. Instead, we were going to
> establish a scope-alike protocol in the WebKit first, let it mature and move
> Eclipse debugger to it.

Sounds OK to me. The V8 debugger protocol is clearly V8 specific. It would be
nice to have a more neutral protocol.

> - Eclipse ChromeDevTools / Chromium do not maintain debugging API in terms of
> protocol, they provide the support in terms of the SDK instead. Every new
> version of Chromium has an SDK update in case of breaking changes to the
> protocol. Your implementation is clearly not ready for that.

Agreed. My implementation is just a starting point for discussion about what
interfaces are needed and what the information flows are across those
interfaces.
Comment 13 Jamey Hicks 2010-02-17 13:22:52 PST
(In reply to comment #11)
> (In reply to comment #8)
> > Created an attachment (id=48923) [details] [details]
> > Web Inspector architecture with patch 48854 applied
> > 
> > Shows subclassing of InspectorFrontend for the direct communication path into
> > the ScriptState of the Web Inspector UI Page.
> 
> I can see the subclassing, but that's not really what you want. All inspector
> frontend methods are dispatched into the "dispatch" script function calls with
> script value parameters. All that you need is to be able to use your
> ScriptFunctionCall that would serialize parameters. There already is a perfect
> tool for serializing ScriptValues that is JSON. So you don't really need any
> subclassing, just parametrized proxy object or pluggable ScriptFunctionCall
> version.

Just to make sure I understand what you are suggesting. You are saying that it is OK to provide alternate implementations of the interface provided by the script proxy object or by providing alternate implementations of ScriptFunctionCall. 

The former implies that the communication channel to the UI needs to be implemented in Javascript by a script proxy object that implements the same interface as WebInspector from WebCore/inspector/front-end/inspector.js.

The latter (subclassing ScriptFunctionCall) seems like a bigger change to WebCore but enables more choice of implementation language for the debugger communication protocol. But I can envision how to make this work.

I'm a little curious why the designated externizable inspector API is one that doesn't have any declaration apart from its implementation, rather than one of the ones defined in a C++ header file or a .idl file.
Comment 14 Pavel Feldman 2010-02-17 13:33:24 PST
> Just to make sure I understand what you are suggesting. You are saying that it
> is OK to provide alternate implementations of the interface provided by the
> script proxy object or by providing alternate implementations of
> ScriptFunctionCall. 
> 
> The former implies that the communication channel to the UI needs to be
> implemented in Javascript by a script proxy object that implements the same
> interface as WebInspector from WebCore/inspector/front-end/inspector.js.
> 
> The latter (subclassing ScriptFunctionCall) seems like a bigger change to
> WebCore but enables more choice of implementation language for the debugger
> communication protocol. But I can envision how to make this work.
> 
> I'm a little curious why the designated externizable inspector API is one that
> doesn't have any declaration apart from its implementation, rather than one of
> the ones defined in a C++ header file or a .idl file.

First of all, ScriptValue/Object/FunctionCall are inspector's properties. They are only used in Inspector code, we can change them. The point I was trying to make was that ScriptFunctionCall is essentially a container for a message. It is an array of ScriptValues that can be serialized into a JSON string. We could change InspectorFrontend to receive a delegate with interface 

InspectorFrontendDelegate {
    void dispatch(String)
}

and do serialization in the InspectorFrontend. It is just that we did not want to do that because we wanted to stay on the JS object ground for in-process case efficiency. In Chromium, we pass a frontend proxy object that does exactly this - it serializes this JS value using JSON.stringify and sends it to the front-end over the wire as string. So we already have an abstraction you are looking for, no need to subclass.

Here is how I see adding an HTTP server into the WebCore picture:
1. InspectorController receives a command to open the front-end.
2. This command is going to the emedded via the InspectorClient interface and
initiates one of the following:
- in-process front-end page opening in WebKit or
- server setup or a device or 
- chrome dev tools init in case of WebKit/chromium.
3. InspectorController awaits for WebKit to report that the front-end is ready.
WebKit notifies InspectorController and passes it a front-end delegate. This
delegate basically has a single method: "dispatch(String message);".
InspectorFrontend serializes ScriptValue into JSON and pushes resulting string
into the host's front-end representative. As mentioned above, this could be a two step thing (frontend object proxy -> frontend delegate) for in-process efficiency of WebKit.
4. In case of HTTP server, this object is wrapped with <script> and pushed to
the client.
5. Incoming messages are dispatched from JSON against InspectorBackend binding via the injected script.

HTTP message format should also be defined by the WebCore, so there should
be single HTTP server located beside InspectorController code. We should come
up with something browser and Eclipse SDK would equally like. It might be that
<script> with payload is not the best message format.

It is important that in the beginning, there is always inspector's front-end
instance on the other end of this communication. It allows us not to expose
interchange protocol to third parties for now. If you are interested in the
protocol to be exposed and maintained, please file a separate bug with the
request.