从Chrome远程调试协议访问JavaScript变量

Accessing a JavaScript variable from Chrome Remote Debugging Protocol

本文关键字:协议 访问 JavaScript 变量 调试 Chrome 程调试      更新时间:2023-09-26

我已通过远程调试协议连接到Chrome(34.0.1847.132),并已成功启用运行时和控制台调试。我可以发送Chrome消息,并将得到回复。

现在,我想检查当前页面中某个JavaScript变量的属性。因此,在我的HTML页面中,我在脚本标签中有以下语句:

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

我可以从Chrome本身的控制台查询window.foo.bar的属性,但我不能通过远程调试做到这一点,因为我收到一个错误。

为了获得属性,我将这个JSON消息发送给WebSocket:

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

我得到了响应:

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

同样,如果我尝试将表达式window.foo.bar转换为Runtime.evaluate,我得到:

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

什么会导致"已检查的框架"消失?那是什么?或者objectId是完全不同的东西?

如何访问JavaScript变量的属性?

Runtime.evaluateRuntime.callFunctionOn返回具有objectId字段的RemoteObject,以防表达式被计算为对象。如果您通过Runtime.getProperties枚举它们,则将返回对象属性的进一步对象标识符。

重要的是要知道Runtime.evaluate访问的是window的级别,所以如果你想访问window.document,你需要document作为一个表达式。

这样做成功了,最后:

window.document.foo = "bar"

在请求中:

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

如果要访问对象属性等,可以将参数中的returnByValue设置为true

看看"Inspected frame has gone"的源代码搜索,它可能会让您对正在发生的事情有所了解。这看起来确实是个不错的选择。

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);
}

window.foo.bar作为const String&objectId。
我假设它找不到它,因为你一定是点击了injectedScript.hasNoValue()