aboutsummaryrefslogtreecommitdiffstats
path: root/support/hololens/ServoApp/Devtools/Client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'support/hololens/ServoApp/Devtools/Client.cpp')
-rw-r--r--support/hololens/ServoApp/Devtools/Client.cpp288
1 files changed, 0 insertions, 288 deletions
diff --git a/support/hololens/ServoApp/Devtools/Client.cpp b/support/hololens/ServoApp/Devtools/Client.cpp
deleted file mode 100644
index a790b2f0eb8..00000000000
--- a/support/hololens/ServoApp/Devtools/Client.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-#include "pch.h"
-#include "strutils.h"
-#include "Client.h"
-
-using namespace winrt::Windows::Data::Json;
-using namespace winrt::Windows::Foundation;
-using namespace winrt::Windows::Networking;
-using namespace winrt::Windows::Storage::Streams;
-
-namespace winrt::servo {
-
-void DevtoolsClient::Stop() {
- if (mReceiving && mReceiveOp.has_value() &&
- mReceiveOp->Status() != AsyncStatus::Completed) {
- mReceiveOp->Cancel();
- }
-}
-
-void DevtoolsClient::Run() {
- if (mReceiving) {
- throw hresult_error(E_FAIL, L"Already running");
- }
- mReceiving = true;
- auto socket = Sockets::StreamSocket();
- auto hostname = HostName(mHostname);
- auto connecting = socket.ConnectAsync(hostname, mPort);
- connecting.Completed([=](const auto &, const auto &) {
- mDataReader = DataReader(socket.InputStream());
- mDataWriter = DataWriter(socket.OutputStream());
-
- JsonObject out;
- out.Insert(L"auth_token", JsonValue::CreateStringValue(mToken));
- Send(out);
-
- mReceiveOp = {Loop()};
- mReceiveOp->Completed([=](const auto &, const auto &) {
- mReceiveOp = {};
- mDataReader->DetachStream();
- mDataWriter->DetachStream();
- mReceiving = false;
- mDelegate.OnDevtoolsDetached();
- });
- });
-}
-
-void DevtoolsClient::Evaluate(hstring code) {
- if (!code.empty() && mConsoleActor.has_value()) {
- JsonObject out;
- out.Insert(L"to", *mConsoleActor);
- out.Insert(L"type", JsonValue::CreateStringValue(L"evaluateJSAsync"));
- out.Insert(L"text", JsonValue::CreateStringValue(code));
- Send(out);
- }
-}
-
-IAsyncAction DevtoolsClient::Loop() {
- auto cancellation = co_await winrt::get_cancellation_token();
- cancellation.callback([=] {
- if (mReaderOp.Status() != AsyncStatus::Completed) {
- mReaderOp.Cancel();
- }
- });
-
- while (!cancellation()) {
- unsigned int len = 0;
- while (!cancellation()) {
- mReaderOp = mDataReader->LoadAsync(1);
- co_await mReaderOp;
- hstring c = mDataReader->ReadString(1);
- if (c == L":")
- break;
- try {
- unsigned int digit = std::stoi(c.c_str());
- len = 10 * len + digit;
- } catch (...) {
- throw hresult_error(E_FAIL, L"Can't parse message header:" + c);
- }
- if (len >= 100000) {
- throw hresult_error(E_FAIL, L"Message length too long");
- }
- }
- if (cancellation()) {
- break;
- }
- hstring request = L"";
- mReaderOp = mDataReader->LoadAsync(len);
- auto bytesLoaded = co_await mReaderOp;
- request = request + mDataReader->ReadString(bytesLoaded);
- JsonObject json;
- if (!JsonObject::TryParse(request, json)) {
- throw hresult_error(E_FAIL, L"Can't parse message: " + request);
- }
- HandleMessage(json);
- }
-}
-
-void DevtoolsClient::HandleMessage(JsonObject obj) {
- // Basic devtools protocol implementation:
- // https://docs.firefox-dev.tools/backend/protocol.html
-
- if (obj.HasKey(L"from") && obj.GetNamedString(L"from") == L"root") {
- if (obj.HasKey(L"applicationType")) {
- // First message. Ask for the current tab
- JsonObject out;
- out.Insert(L"to", JsonValue::CreateStringValue(L"root"));
- out.Insert(L"type", JsonValue::CreateStringValue(L"getTab"));
- Send(out);
- return;
- } else if (obj.HasKey(L"tab")) {
- // Got the current tab.
- auto tab = obj.GetNamedObject(L"tab");
- JsonObject out;
- out.Insert(L"to", tab.GetNamedValue(L"actor"));
- out.Insert(L"type", JsonValue::CreateStringValue(L"getTarget"));
- Send(out);
- return;
- }
- } else if (obj.HasKey(L"resultID")) {
- // evaluateJSAsync response.
- if (obj.GetNamedString(L"type", L"") == L"evaluationResult") {
- HandleEvaluationResult(obj);
- }
- return;
- } else if (obj.HasKey(L"type")) { // Not from root
- if (obj.GetNamedString(L"type") == L"pageError") {
- // Got a page error
- HandlePageError(obj.GetNamedObject(L"pageError"));
- return;
- } else if (obj.GetNamedString(L"type") == L"consoleAPICall") {
- // console.* calls
- auto message = obj.GetNamedObject(L"message");
- HandleConsoleMessage(message);
- return;
- } else if (obj.GetNamedString(L"type") == L"tabAttached") {
- // Ignore
- return;
- } else if (obj.GetNamedString(L"type") == L"networkEvent") {
- // Ignore
- return;
- } else if (obj.GetNamedString(L"type") == L"tabNavigated") {
- if (obj.HasKey(L"state") && obj.GetNamedString(L"state") == L"stop") {
- mDelegate.ClearConsole();
- }
- return;
- } else if (obj.GetNamedString(L"type") == L"networkEventUpdate") {
- // FIXME: log if there is a non-200 HTTP response
- return;
- }
- } else if (obj.HasKey(L"frame")) {
- auto frame = obj.GetNamedObject(L"frame");
- // Attach to tab, and ask for cached messaged
- JsonObject msg1;
- mConsoleActor = frame.GetNamedValue(L"consoleActor");
- msg1.Insert(L"to", frame.GetNamedValue(L"actor"));
- msg1.Insert(L"type", JsonValue::CreateStringValue(L"attach"));
- Send(msg1);
- JsonObject msg2;
- msg2.Insert(L"to", *mConsoleActor);
- msg2.Insert(L"type", JsonValue::CreateStringValue(L"getCachedMessages"));
- JsonArray types;
- types.Append(JsonValue::CreateStringValue(L"PageError"));
- types.Append(JsonValue::CreateStringValue(L"ConsoleAPI"));
- msg2.Insert(L"messageTypes", types);
- Send(msg2);
- return;
- } else if (obj.HasKey(L"messages")) {
- // Response to getCachedMessages
- for (auto messageValue : obj.GetNamedArray(L"messages")) {
- auto message = messageValue.GetObject();
- if (message.GetNamedString(L"_type") == L"ConsoleAPI") {
- HandleConsoleMessage(message);
- } else if (message.GetNamedString(L"_type") == L"PageError") {
- HandlePageError(message);
- } else {
- HandleNonHandledMessage(message);
- }
- }
- return;
- }
- HandleNonHandledMessage(obj);
-}
-
-DevtoolsMessageLevel DevtoolsClient::ParseLevel(JsonObject message) {
- if (message.GetNamedBoolean(L"error", false)) {
- return DevtoolsMessageLevel::Error;
- }
- if (message.GetNamedBoolean(L"warning", false)) {
- return DevtoolsMessageLevel::Warn;
- }
- if (message.GetNamedBoolean(L"exception", false)) {
- return DevtoolsMessageLevel::Error;
- }
- auto level = message.GetNamedString(L"level", L"");
- if (level == L"warn") {
- return DevtoolsMessageLevel::Warn;
- } else if (level == L"error") {
- return DevtoolsMessageLevel::Error;
- }
- return DevtoolsMessageLevel::None;
-}
-
-hstring DevtoolsClient::ParseSource(JsonObject message) {
- auto source = message.GetNamedString(L"filename", L"<>");
- if (message.HasKey(L"lineNumber")) {
- source = source + L":" + to_hstring(message.GetNamedNumber(L"lineNumber"));
- }
- if (message.HasKey(L"columnNumber")) {
- source =
- source + L":" + to_hstring(message.GetNamedNumber(L"columnNumber"));
- }
- return source;
-}
-
-void DevtoolsClient::HandlePageError(JsonObject message) {
- auto source = ParseSource(message);
- auto body = message.GetNamedString(L"errorMessage", L"");
- auto level = ParseLevel(message);
- mDelegate.OnDevtoolsMessage(level, source, body);
-}
-
-void DevtoolsClient::HandleEvaluationResult(JsonObject message) {
- auto level = DevtoolsMessageLevel::None;
- hstring body = L"";
- if (message.HasKey(L"result")) {
- auto value = message.GetNamedValue(L"result");
- if (value.ValueType() == JsonValueType::Object) {
- auto type = value.GetObject().GetNamedString(L"type");
- if (type == L"undefined") {
- body = L"undefined";
- } else {
- body = L"<object>";
- }
- } else {
- body = value.Stringify();
- }
- } else if (message.GetNamedValue(L"exception").ValueType() !=
- JsonValueType::Null) {
- level = DevtoolsMessageLevel::Error;
- body = message.GetNamedString(L"exceptionMessage", L"");
- }
- mDelegate.OnDevtoolsMessage(level, L"", body);
-}
-
-void DevtoolsClient::HandleConsoleMessage(JsonObject message) {
- auto source = ParseSource(message);
- auto level = ParseLevel(message);
- hstring body = L"";
- for (auto arg : message.GetNamedArray(L"arguments")) {
- body = body + arg.Stringify();
- }
- mDelegate.OnDevtoolsMessage(level, source, body);
-}
-
-void DevtoolsClient::HandleNonHandledMessage(JsonObject message) {
- auto level = DevtoolsMessageLevel::Warn;
- auto body = L"Unhandled devtools message: " + message.Stringify();
- mDelegate.OnDevtoolsMessage(level, L"", body);
-}
-
-void DevtoolsClient::SendPendingObjects() {
- if (mPendingObjects.empty() || mSending) {
- return;
- }
- mSending = true;
- auto obj = mPendingObjects.front();
- mPendingObjects.erase(mPendingObjects.begin());
- hstring msg = obj.Stringify();
- hstring size = to_hstring(msg.size());
- hstring request = size + L":" + msg;
- mDataWriter->WriteString(request);
- mDataWriter->StoreAsync().Completed([=](const auto &, const auto &) {
- mDataWriter->FlushAsync().Completed([=](const auto &, const auto &) {
- mSending = false;
- SendPendingObjects();
- });
- });
-}
-
-void DevtoolsClient::Send(JsonObject obj) {
- mPendingObjects.push_back(obj);
- SendPendingObjects();
-}
-
-} // namespace winrt::servo