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

Posted

技术标签:

【中文标题】从 Chrome 远程调试协议访问 JavaScript 变量【英文标题】:Accessing a JavaScript variable from Chrome Remote Debugging Protocol 【发布时间】:2014-06-24 12:55:16 【问题描述】:

我已通过Remote Debugging Protocol 连接到 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

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


    "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.getProperties` 使检查的框架“消失”。 【参考方案1】:

重要的是要知道Runtime.evaluateaccesses at the level of window,所以如果你想访问window.document,你需要document作为一个表达式。

最终成功了:

window.document.foo = "bar"

在请求中:


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

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

【讨论】:

但是window.window === window? 是的,我知道。但是如果我设置了window.foo,我就不能查询foo,也不能查询window.foo。不要问我这是为什么。【参考方案2】:

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

【讨论】:

【参考方案3】:

看看source 搜索"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()

【讨论】:

谢谢,但这更像是一个评论而不是一个答案,真的。它只是提出了更多的问题.. 似乎它正在寻找一些注入的脚本?那会是什么? 您将 window.foo.bar 作为 const String& objectId 传递?我会假设它找不到它。试试“foo.bar” window.foo.bar,就像问题中提到的那样。但也许它应该是完全不同的东西——我不知道,我无法从文档中看出。 我已经编辑了我之前的评论,因为它很愚蠢,对此感到抱歉。请尝试不带窗口的 foo.bar。 没有骰子,同样的错误信息。 (尽管如此,连接仍然保持活动状态。)

以上是关于从 Chrome 远程调试协议访问 JavaScript 变量的主要内容,如果未能解决你的问题,请参考以下文章

使用谷歌浏览器远程调试协议

使用 ChromeDriver 和 Chrome DevTools 协议进行多客户端远程调试

如何通过chrome远程调试获取网页资源内容

[转] 在安卓设备上使用 Chrome 远程调试功能

远程调试 - 如何创建端口代理?

如何使用 Chrome 开发工具调试基于 v8 的远程应用程序