diff options
Diffstat (limited to 'support/hololens/ServoApp/Devtools/Client.cpp')
-rw-r--r-- | support/hololens/ServoApp/Devtools/Client.cpp | 288 |
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 |