Webコンソールリモーティング

イントロダクション

このドキュメントでは、Webコンソールのリモート処理のしくみについて説明します。Webコンソールはユーザーインターフェイスを備えたクライアントと、タブ内で発生するすべてのもののリスナーを持つサーバーに分割されています。サーバーとクライアント間の通信には、リモートデバッグプロトコルを使用します。このアーキテクチャでは、WebコンソールクライアントインスタンスをB2G、Fennecまたはその他のFirefoxインスタンス上で動作するサーバーに接続できます。

Webコンソールのアーキテクチャをよりよく理解するために、デバッガのアーキテクチャについて学ぶことをお勧めします。

リモートWebコンソールは、Firefox 18で導入された機能です。このドキュメントでは、最新のプロトコルについて説明しています。

WebConsoleActorWebConsoleClient

WebConsoleActor は、toolkit/devtools/webconsole フォルダの dbg-webconsole-actors.js にあります。

WebConsoleClient は (toolkit/devtools/webconsole の) WebConsoleClient.jsm にあり、Web コンソールアクターで作業するときにWeb コンソールで使用されます。

デバッガが Web コンソールコードでどのように使用されているかを確認するには、browser/devtools/webconsole/webconsole.js を開き、WebConsoleConnectionProxy を検索します。

新しい Web コンソールアクターは次のとおりです。

  • WebConsoleActor は JS 評価、オートコンプリート、リスナーの開始/停止などを許可します。
  • NetworkEventActor は、新しいネットワークリクエストごとに使用されます。クライアントは、レスポンス本文やリクエストヘッダーなど、詳細なネットワークイベントの詳細を要求できます。

WebConsoleActor に接続するには、次の手順を実行します。

connectToServer() // the usual
listTabs()
pickTheTabYouWant()
debuggerClient.attachConsole(tab.consoleActor, listeners, onAttachConsole)

listeners 引数は、Web コンソールで開始するリスナーを指定する配列です。ページエラー、window.console API メッセージ、ネットワークアクティビティ、ファイルアクティビティなどがあります。例えば:

["PageError", "ConsoleAPI", "NetworkActivity", "FileActivity"]

Webコンソールアクタはデフォルトではリスナーを起動しません。クライアントには、必要なときに各リスナーを起動するオプションがあります。この方法で、サーバーでのリソース使用率を低く抑えることができます。これは、サーバーが少ないリソースでデバイスを実行する場合に起こりうる問題です。

onAttachConsole コールバックは WebConsoleClient オブジェクトの新しいインスタンスを受け取ります。このオブジェクトは startListeners()stopListeners() などのプロトコルパケットを抽象化するメソッドを提供します。

プロトコルパケットは次のようになります。

{
  "to": "root",
  "type": "listTabs"
}
{
  "from": "root",
  "consoleActor": "conn0.console9",
  "selected": 2,
  "tabs": [
    {
      "actor": "conn0.tab2",
      "consoleActor": "conn0.console7",
      "title": "",
      "url": "https://tbpl.mozilla.org/?tree=Fx-Team"
    },
// ...
  ]
}

consoleActorグローバルアクターとしても利用可能であることに注意してください。グローバル consoleActor にアタッチすると、すべてのネットワークリクエスト、ページエラー、およびその他のイベント (クロムエラーやネットワークイベントなど) がすべてのタブとウィンドウから受信されます。このアクターはブラウザコンソールの実装や、リモート Firefox/B2G インスタンスのデバッグに使用されます。

startListeners(listeners, onResponse)

新しい startListeners パケット:

{
  "to": "conn0.console9",
  "type": "startListeners",
  "listeners": [
    "PageError",
    "ConsoleAPI",
    "NetworkActivity",
    "FileActivity"
  ]
}

返答:

{
  "startedListeners": [
    "PageError",
    "ConsoleAPI",
    "NetworkActivity",
    "FileActivity"
  ],
  "nativeConsoleAPI": true,
  "from": "conn0.console9"
}

レスポンスは開始されたリスナーを示し、window.console オブジェクトがページ内のスクリプトによってオーバーライドされたかどうかを示す nativeConsoleAPI フラグを含みます。

タブナビゲーション

タブナビゲーションイベントを待ち受けるには、指定したタブのタブアクターにアタッチする必要もあります。tabNavigated 通知はタブのアクターから来ます。

Firefox 20 以前では、Web コンソールの実行者はLocationChangeリスナを提供し、locationChanged 通知を関連付けました。これはもはや当てはまりません。Web コンソールクライアントが tabNavigated 通知を再利用 (bug 792062) できるように変更しました。

ページナビゲーションが開始されると、次のパケットがタブアクターから送信されます。

{
  "from": tabActor,
  "type": "tabNavigated",
  "state": "start",
  "url": newURL,
  "nativeConsoleAPI": true
}

nativeConsoleAPI プロパティは、window.console オブジェクトがネイティブかどうかを、指定されたタブのトップレベルウィンドウオブジェクトに対して示します。これは、ナビゲーションが開始されると常に true になります。ナビゲーションが停止すると、次のパケットが送信されます。

{
  "from": tabActor,
  "type": "tabNavigated",
  "state": "stop",
  "url": newURL,
  "title": newTitle,
  "nativeConsoleAPI": true|false
}

getCachedMessages(types, onResponse)

webConsoleClient.getCachedMessages(types, onResponse) メソッドは、次のパケットをサーバーに送信します。

{
  "to": "conn0.console9",
  "type": "getCachedMessages",
  "messageTypes": [
    "PageError",
    "ConsoleAPI"
  ]
}

getCachedMessages パケットを使用すると、Web コンソールを開く前にキャッシュされたメッセージを取得できます。 ページエラーとコンソール API 呼び出しのキャッシュメッセージしか取得できません。 返信は次のようになります。

{
  "messages": [ ... ],
  "from": "conn0.console9"
}

配列内の各メッセージは、典型的なページエラーやコンソール API コールを送信するときと同じタイプです。これらについては、本書の以下のセクションで説明します。

アクター設定

Web コンソールが実行中にログオプションを設定できるように、setPreferencesパケットを追加しました。

{
  "to": "conn0.console9",
  "type": "setPreferences",
  "preferences": {
    "NetworkMonitor.saveRequestAndResponseBodies": false
  }
}

返答:

{
  "updated": [
    "NetworkMonitor.saveRequestAndResponseBodies"
  ],
  "from": "conn0.console10"
}

便宜上 webConsoleClient.setPreferences(prefs, onResponse)を使用できます。prefs 引数は { prefName: prefValue, ... } のようなオブジェクトです。

Firefox 25 では getPreferences リクエストパケットが追加されました:

{
  "to": "conn0.console34",
  "type": "getPreferences",
  "preferences": [
    "NetworkMonitor.saveRequestAndResponseBodies"
  ]
}

返答パケット:

{
  "preferences": {
    "NetworkMonitor.saveRequestAndResponseBodies": false
  },
  "from": "conn0.console34"
}

webConsoleClient.getPreferences(prefs, onResponse) を使用することもできます。prefs 引数は、名前で値を取得したい設定の配列です。

プライベートブラウジング

ブラウザコンソールは、ユーザーがプライベートウィンドウを開いているときに使用できます。各ページエラー、コンソール API メッセージ、およびネットワークリクエストにはプライベートフラグが付いています。プライベートメッセージは、最後のプライベートウィンドウが閉じられるたびにクリアされます。コンソールアクタは lastPrivateContextExited 通知を提供します。

{
  "from": "conn0.console19",
  "type": "lastPrivateContextExited"
}

この通知はクライアントがグローバルコンソールアクターに接続されている場合にのみ送信され、タブコンソールアクターには意味をなしません。

この通知は Firefox 24 で導入されました。

HTTP リクエストの送信

Firefox 25 から、コンソールアクタを使用して HTTP リクエストを送信することができます:

{
  "to": "conn0.console9",
  "type": "sendHTTPRequest",
  "request": {
    "url": "http://localhost",
    "method": "GET",
    "headers": [
      {
        name: "Header-name",
        value: "header value",
      },
      // ...
    ],
  },
}

レスポンスパケットは、ネットワークイベントアクターグリップです。

{
  "to": "conn0.console9",
  "eventActor": {
    "actor": "conn0.netEvent14",
    "startedDateTime": "2013-08-26T19:50:03.699Z",
    "url": "http://localhost",
    "method": "GET"
    "isXHR": true,
    "private": false
  }
}

webConsoleClient.sendHTTPRequest(request, onResponse) メソッドを使用することもできます。request 引数は上記のリクエストパケットの request オブジェクトと同じです。

ページエラー

ページエラーは nsIConsoleService から発生します。許可される各ページエラーは nsIScriptError オブジェクトです。

pageError パケットは次のとおりです。

{
  "from": "conn0.console9",
  "type": "pageError",
  "pageError": {
    "errorMessage": "ReferenceError: foo is not defined",
    "sourceName": "http://localhost/~mihai/mozilla/test.js",
    "lineText": "",
    "lineNumber": 6,
    "columnNumber": 0,
    "category": "content javascript",
    "timeStamp": 1347294508210,
    "error": false,
    "warning": false,
    "exception": true,
    "strict": false,
    "private": false,
  }
}

単純化のため、パケットは nsIScriptError に似ています。いくつかの不必要なプロパティを削除し、フラグの働きを変更しました。

private フラグは、エラーがプライベートウィンドウ/タブ (Firefox 24で追加されたもの) から来たものかどうかを示します。

Firefox 24 以降、文字列が非常に長い場合、errorMessage および lineText プロパティは長い文字列アクターグリップになることがあります。

Console API メッセージ

window.console API 呼び出しは、Gecko を通して内部メッセージを送信します。これにより、各呼び出しに必要な処理を実行できます。Web コンソールのアクターは、これらのメッセージをリモートデバッグクライアントに送信します。

dbg-script-actors.jsObjectActorThreadActor なしで使用すると、ページスクリプトの速度低下を避けることができます。デバッガはターゲットページで JavaScript の実行を非最適化します。Web コンソールのオブジェクトアクタの有効期間は、デバッガ内のこれらのオブジェクトの存続期間とは異なります。通常、一時停止またはスレッドごとです。 Web コンソールは ObjectActors の有効期間を手動で管理します。

Firefox 23以前は、プロトコルを通じてJavaScriptオブジェクトを操作するために、別のアクタ(WebConsoleObjectActor)を使用しました。bug 783499では、デバッガからObjectActorを再利用するためにいくつかの変更を行いました。

コンソール API メッセージは nsIObserverService を経由します。コンソールオブジェクトの実装は dom/base/ConsoleAPI.js にあります。

サーバーで受信したコンソールメッセージごとに、次の consoleAPICall パケットをクライアントに送信します。

{
  "from": "conn0.console9",
  "type": "consoleAPICall",
  "message": {
    "level": "error",
    "filename": "http://localhost/~mihai/mozilla/test.html",
    "lineNumber": 149,
    "functionName": "",
    "timeStamp": 1347302713771,
    "private": false,
    "arguments": [
      "error omg aloha ",
      {
        "type": "object",
        "className": "HTMLBodyElement",
        "actor": "conn0.consoleObj20"
      },
      " 960 739 3.141592653589793 %a",
      "zuzu",
      { "type": "null" },
      { "type": "undefined" }
    ]
  }
}

ページエラーを送信する方法と同様に、ここでは nsIObserverService から受信した実際のコンソールイベントを送信します。arguments の配列を変更します - 引数として渡される各オブジェクトの ObjectActor インスタンスを作成し、最後に不要なプロパティ (ウィンドウIDなど) を削除します。長い文字列の場合、LongStringActor を使用します。Web コンソールは引き数を検査できます。

private フラグは、コンソール API 呼び出しがプライベートウィンドウ/タブ (Firefox 24 で追加されたもの) から来ているかどうかを示します。

オブザーバーサービスから受け取ったコンソールイベントオブジェクトには小さな違いがあるように、コンソール API 呼び出しメソッドに応じて、オブジェクトの小さなバリエーションがあります。これらの相違点を確認するには、コンソール API 実装の dom/base/ConsoleAPI.js を参照してください。

JavaScript 評価

evaluateJS リクエストとレスポンスパケット

Web コンソールクライアントは evaluateJS(requestId, string, onResponse) メソッドを提供し、次のパケットを送信します。

{
  "to": "conn0.console9",
  "type": "evaluateJS",
  "text": "document",
  "bindObjectActor": null,
  "frameActor": null,
  "url": null,
  "selectedNodeActor": null,
}

bindObjectActor プロパティは、Debugger.Object を指すオプションの ObjectActor IDです。このオプションを使用すると、文字列の評価中に _self を指定されたオブジェクトアクターの Debugger.Object にバインドできます。バインディングについては evalInGlobalWithBindings() を参照してください。

変数ビューはオブジェクトを更新する必要があり、表示されているObjectActorDebugger.Object_selfをバインドすることによってオブジェクトを更新する必要があります。 そのため、変数ビューは評価のために次のような文字列を送信します。

  _self["prop"] = value;

frameActor プロパティは、オプションの FrameActor IDです。FAは Debugger.Frame への参照を保持します。このオプションを使用すると指定された FA のフレーム内の文字列を評価できます。

url プロパティはスクリプトを評価するためのオプションの URL です(Firefox 25 の新機能)。評価のためのデフォルトのソース URL は "debugger eval code" です。

selectedNodeActor プロパティはオプションの NodeActor ID であり、Inspector で現在選択されているノードがある場合はそのノードを示すために使用されます。この NodeActor$0 JSTerm ヘルパーによって参照できます。

レスポンスパケット:

{
  "from": "conn0.console9",
  "input": "document",
  "result": {
    "type": "object",
    "className": "HTMLDocument",
    "actor": "conn0.consoleObj20"
    "extensible": true,
    "frozen": false,
    "sealed": false
  },
  "timestamp": 1347306273605,
  "exception": null,
  "exceptionMessage": null,
  "helperResult": null
}
  • exception は、評価中にスローされた例外の JSON-ification を保持します。
  • exceptionMessageexception.toString() の結果を保持します。
  • result は結果の ObjectActor インスタンスを保持します。
  • helperResult は JSTerm ヘルパーの結果、JSON のもの (コンテンツオブジェクトではありません) から来るものです。

Firefox 23では、プロトコルエラーが発生したときに使用されるデフォルトプロパティとの競合を避けるために、errorおよびerrorMessageプロパティの名前をそれぞれexceptionおよびexceptionMessageに変更しました。

Autocomplete など

autocomplete リクエストパケット:

{
  "to": "conn0.console9",
  "type": "autocomplete",
  "text": "d",
  "cursor": 1
}

レスポンスパケット:

{
  "from": "conn0.console9",
  "matches": [
    "decodeURI",
    "decodeURIComponent",
    "defaultStatus",
    "devicePixelRatio",
    "disableExternalCapture",
    "dispatchEvent",
    "doMyXHR",
    "document",
    "dump"
  ],
  "matchProp": "d"
}

また、レスポンスがない clearMessagesCache リクエストパケットもあります。これにより、コンソール API コールキャッシュがクリアされ、ページエラーキャッシュがクリアされるはずです。バグ 717611 を参照してください。

ネットワークロギング

networkEvent パケット

新しいネットワークリクエストがログに記録されるたびに networkEvent パケットが送信されます。

{
  "from": "conn0.console10",
  "type": "networkEvent",
  "eventActor": {
    "actor": "conn0.netEvent14",
    "startedDateTime": "2012-09-17T19:50:03.699Z",
    "url": "http://localhost/~mihai/mozilla/test2.css",
    "method": "GET"
    "isXHR": false,
    "private": false
  }
}

このパケットは Web コンソールに新しいネットワークイベントを通知するために使用されます。リクエストごとに新しい NetworkEventActor インスタンスが作成されます。isXHR フラグはリクエストが XMLHttpRequest インスタンスを介して開始されたかどうかを示します。つまり、nsIHttpChannel の通知は nsIXMLHttpRequest インターフェイスです。

private フラグは、ネットワークリクエストがプライベートウィンドウ/タブ (Firefox 24 で追加されたもの) から来たものかどうかを示します。

NetworkEventActor

新しいネットワークイベントアクターは、さらにリクエストおよびレスポンス情報を格納します。

networkEventUpdate パケット

変更が発生したとき、新しいものが追加されたときに Web コンソール UI を最新の状態に保つ必要があります。この目的のために新しい networkEventUpdate パケットが送信されます。例:

{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "requestHeaders",
  "headers": 10,
  "headersSize": 425
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "requestCookies",
  "cookies": 0
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "requestPostData",
  "dataSize": 1024,
  "discardRequestBody": false
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "responseStart",
  "response": {
    "httpVersion": "HTTP/1.1",
    "status": "304",
    "statusText": "Not Modified",
    "headersSize": 194,
    "discardResponseBody": true
  }
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "eventTimings",
  "totalTime": 1
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "responseHeaders",
  "headers": 6,
  "headersSize": 194
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "responseCookies",
  "cookies": 0
},
{
  "from": "conn0.netEvent14",
  "type": "networkEventUpdate",
  "updateType": "responseContent",
  "mimeType": "text/css",
  "contentSize": 0,
  "discardResponseBody": true
}

実際のヘッダー、Cookie、および本文は送信されません。

getRequestHeaders とその他のパケット

ネットワークイベントの詳細については、次のパケットリクエスト (およびレスポンス) を使用できます。

getRequestHeaders パケット:

{
  "to": "conn0.netEvent15",
  "type": "getRequestHeaders"
}
{
  "from": "conn0.netEvent15",
  "headers": [
    {
      "name": "Host",
      "value": "localhost"
    }, ...
  ],
  "headersSize": 350
}

getRequestCookies パケット:

{
  "to": "conn0.netEvent15",
  "type": "getRequestCookies"
}
{
  "from": "conn0.netEvent15",
  "cookies": []
}

getResponseHeaders パケット:

{
  "to": "conn0.netEvent15",
  "type": "getResponseHeaders"
}
{
  "from": "conn0.netEvent15",
  "headers": [
    {
      "name": "Date",
      "value": "Mon, 17 Sep 2012 20:05:27 GMT"
    }, ...
  ],
  "headersSize": 320
}

getResponseCookies パケット:

{
  "to": "conn0.netEvent15",
  "type": "getResponseCookies"
}
{
  "from": "conn0.netEvent15",
  "cookies": []
}

Firefox19より提供開始:上記のパケットのすべてのヘッダーとCookieの値に対して、値が非常に長い場合はLongStringActor gripsを使用します。 これにより、ネットワーク帯域幅の使い過ぎを避けることができます。

getRequestPostData パケット:

{
  "to": "conn0.netEvent15",
  "type": "getRequestPostData"
}
{
  "from": "conn0.netEvent15",
  "postData": { text: "foobar" },
  "postDataDiscarded": false
}

getResponseContent パケット:

{
  "to": "conn0.netEvent15",
  "type": "getResponseContent"
}
{
  "from": "conn0.netEvent15",
  "content": {
    "mimeType": "text/css",
    "text": "\n@import \"test.css\";\n\n.foobar { color: green }\n\n"
  },
  "contentDiscarded": false
}

リクエストとレスポンスの内容のテキスト値は、LongStringActorグリップを使用して最も一般的に送信されます。 非常に短いリクエスト/レスポンスのボディについては、生のテキストを送信します。

Firefox19から:非テキストレスポンスタイプの場合、Base64エンコーディング(これはおそらくLongStringActorグリップです)でコンテンツを送信します。違いを伝えるには、response.content.encoding == "base64"かどうかを確認してください。

getEventTimings パケット:

{
  "to": "conn0.netEvent15",
  "type": "getEventTimings"
}
{
  "from": "conn0.netEvent15",
  "timings": {
    "blocked": 0,
    "dns": 0,
    "connect": 0,
    "send": 0,
    "wait": 16,
    "receive": 0
  },
  "totalTime": 16
}

fileActivity パケット

ファイルのロードが監視されると、次の fileActivity パケットがクライアントに送信されます。

{
  "from": "conn0.console9",
  "type": "fileActivity",
  "uri": "file:///home/mihai/public_html/mozilla/test2.css"
}

ヒストリー

Firefoxバージョンによるプロトコルの変更:

  • Firefox 18: 初期バージョン。
  • Firefox 19: bug 787981 - いくつかの場所で LongStringActor の使用法を追加しました。
  • Firefox 20: bug 792062 - removed locationChanged packet and updated the tabNavigated packet for tab actors.
  • Firefox 23: bug 783499 - removed the WebConsoleObjectActor. Now the Web Console uses the JavaScript debugger API and the ObjectActor.
  • Firefox 23: added the bindObjectActor and frameActor options to the evaluateJS request packet.
  • Firefox 24: new private flags for the console actor notifications, bug 874061. Also added the lastPrivateContextExited notification for the global console actor.
  • Firefox 24: new isXHR flag for the networkEvent notification, bug 859046.
  • Firefox 24: removed the message property from the pageError packet notification, bug 877773. The lineText and errorMessage properties can be long string actors now.
  • Firefox 25: added the url option to the evaluateJS request packet.
  • Firefox 25: added the getPreferences and sendHTTPRequest request packets to the console actor, bug 886067 and bug 731311.

まとめ

この文書の執筆時点では、この文書は バグ 768096 で行った作業とそれに続く変更をまとめたものです。このドキュメントを最新の状態に保つよう努めています。これがあなたの役立つことを願っています。

Webコンソールサーバーを変更する場合は、このドキュメントを更新してください。 ありがとうございました!

ドキュメントのタグと貢献者

このページの貢献者: silverskyvicto
最終更新者: silverskyvicto,