slhck
slhck

Reputation: 38701

Accessing a JavaScript variable from Chrome Remote Debugging Protocol

I am connected to Chrome (34.0.1847.132) via the Remote Debugging Protocol, and I have successfully enabled runtime and console debugging. I can send Chrome messages and will get the responses back.

Now, I'd like to inspect the properties of a certain JavaScript variable in the current page. So, in my HTML page, I have the following statement in a script tag:

window.foo = {
  'bar' : 'baz'
}

I can query the property with window.foo.bar from the console in Chrome itself, but I cannot do it via remote debugging, since I receive an error.

To get the property, I send this JSON message to the WebSocket:

{
  :method => "Runtime.getProperties", 
  :params => {
    :objectId => "window.foo.bar"
  }, 
  "id"=>2
}

And I get the response:

{
    "error" => {
           "code" => -32000,
        "message" => "Inspected frame has gone"
    },
       "id" => 2
}

Similarly, if I try to Runtime.evaluate the expression window.foo.bar, I get:

{
    "result" => {
           "result" => {
                   "type" => "object",
               "objectId" => "{\"injectedScriptId\":1,\"id\":1}",
              "className" => "TypeError",
            "description" => "TypeError: Cannot read property 'bar' of undefined"
        },
        "wasThrown" => true
    },
        "id" => 2
}

What would cause the "inspected frame" to be gone? What is that, even? Or is the objectId something completely different?

How do I access the property of a JavaScript variable then?

Upvotes: 1

Views: 3377

Answers (3)

Laurence Chen
Laurence Chen

Reputation: 1848

Runtime.evaluate and Runtime.callFunctionOn return a RemoteObject that has objectId field, in case the expression has evaluated into an Object. Further object identifiers will be returned for the object's properties if you enumerate them via Runtime.getProperties.

Upvotes: 2

slhck
slhck

Reputation: 38701

What's important to know is that Runtime.evaluate accesses at the level of window, so if you want to access window.document, you need document as an expression.

Doing this worked, in the end:

window.document.foo = "bar"

And in the request:

{
  :method => "Runtime.evaluate", 
  :params => {
    :expression => "document.foo"
  },
  "id" => 1
}

You may want to set returnByValue in the parameters to true if you want to access object properties and such.

Upvotes: 1

Matas Vaitkevicius
Matas Vaitkevicius

Reputation: 61409

Take a look at source search for "Inspected frame has gone" it might give you some insight on what is happening. This does look like a good candidate.

void InspectorRuntimeAgent::getProperties(ErrorString* errorString, const String& objectId, const bool* const ownProperties, RefPtr<InspectorArray>* result)
{
    InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
    if (injectedScript.hasNoValue()) {
        *errorString = "Inspected frame has gone";
    return;
    }
    injectedScript.getProperties(errorString, objectId, ownProperties ? *ownProperties : false, result);
}

You are passing window.foo.bar as const String& objectId.
I would assume it cannot find it, as you must be hitting injectedScript.hasNoValue().

Upvotes: 0

Related Questions