mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
209 lines
7.3 KiB
C++
209 lines
7.3 KiB
C++
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/sky/shell/platform_view_service_protocol.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <string>
|
|
|
|
#include "flutter/sky/shell/shell.h"
|
|
|
|
namespace sky {
|
|
namespace shell {
|
|
namespace {
|
|
|
|
constexpr char kViewIdPrefx[] = "_flutterView/";
|
|
constexpr size_t kViewIdPrefxLength = sizeof(kViewIdPrefx) - 1;
|
|
|
|
static intptr_t KeyIndex(const char** param_keys,
|
|
intptr_t num_params,
|
|
const char* key) {
|
|
if (param_keys == NULL) {
|
|
return -1;
|
|
}
|
|
for (intptr_t i = 0; i < num_params; i++) {
|
|
if (strcmp(param_keys[i], key) == 0) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
static const char* ValueForKey(const char** param_keys,
|
|
const char** param_values,
|
|
intptr_t num_params,
|
|
const char* key) {
|
|
intptr_t index = KeyIndex(param_keys, num_params, key);
|
|
if (index < 0) {
|
|
return NULL;
|
|
}
|
|
return param_values[index];
|
|
}
|
|
|
|
static bool ErrorMissingParameter(const char** json_object, const char* name) {
|
|
const intptr_t kInvalidParams = -32602;
|
|
std::stringstream response;
|
|
response << "{\"code\":" << std::to_string(kInvalidParams) << ",";
|
|
response << "\"message\":\"Invalid params\",";
|
|
response << "\"data\": {\"details\": \"" << name << "\"}}";
|
|
*json_object = strdup(response.str().c_str());
|
|
return false;
|
|
}
|
|
|
|
static bool ErrorBadParameter(const char** json_object,
|
|
const char* name,
|
|
const char* value) {
|
|
const intptr_t kInvalidParams = -32602;
|
|
std::stringstream response;
|
|
response << "{\"code\":" << std::to_string(kInvalidParams) << ",";
|
|
response << "\"message\":\"Invalid params\",";
|
|
response << "\"data\": {\"details\": \"parameter: " << name << " has a bad ";
|
|
response << "value: " << value << "\"}}";
|
|
*json_object = strdup(response.str().c_str());
|
|
return false;
|
|
}
|
|
|
|
static bool ErrorUnknownView(const char** json_object, const char* view_id) {
|
|
const intptr_t kInvalidParams = -32602;
|
|
std::stringstream response;
|
|
response << "{\"code\":" << std::to_string(kInvalidParams) << ",";
|
|
response << "\"message\":\"Invalid params\",";
|
|
response << "\"data\": {\"details\": \"view not found: " << view_id << "\"}}";
|
|
*json_object = strdup(response.str().c_str());
|
|
return false;
|
|
}
|
|
|
|
static bool ErrorIsolateSpawn(const char** json_object, const char* view_id) {
|
|
const intptr_t kInvalidParams = -32602;
|
|
std::stringstream response;
|
|
response << "{\"code\":" << std::to_string(kInvalidParams) << ",";
|
|
response << "\"message\":\"Invalid params\",";
|
|
response << "\"data\": {\"details\": \"view " << view_id;
|
|
response << " did not spawn an isolate\"}}";
|
|
*json_object = strdup(response.str().c_str());
|
|
return false;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void PlatformViewServiceProtocol::RegisterHook(bool running_precompiled_code) {
|
|
if (running_precompiled_code) {
|
|
return;
|
|
}
|
|
Dart_RegisterRootServiceRequestCallback(kRunInViewExtensionName, &RunInView,
|
|
nullptr);
|
|
Dart_RegisterRootServiceRequestCallback(kListViewsExtensionName, &ListViews,
|
|
nullptr);
|
|
}
|
|
|
|
const char* PlatformViewServiceProtocol::kRunInViewExtensionName =
|
|
"_flutter.runInView";
|
|
|
|
bool PlatformViewServiceProtocol::RunInView(const char* method,
|
|
const char** param_keys,
|
|
const char** param_values,
|
|
intptr_t num_params,
|
|
void* user_data,
|
|
const char** json_object) {
|
|
const char* view_id =
|
|
ValueForKey(param_keys, param_values, num_params, "viewId");
|
|
const char* asset_directory =
|
|
ValueForKey(param_keys, param_values, num_params, "assetDirectory");
|
|
const char* main_script =
|
|
ValueForKey(param_keys, param_values, num_params, "mainScript");
|
|
const char* packages_file =
|
|
ValueForKey(param_keys, param_values, num_params, "packagesFile");
|
|
if (view_id == NULL) {
|
|
return ErrorMissingParameter(json_object, "viewId");
|
|
}
|
|
if (strncmp(view_id, kViewIdPrefx, kViewIdPrefxLength) != 0) {
|
|
return ErrorBadParameter(json_object, "viewId", view_id);
|
|
}
|
|
if (asset_directory == NULL) {
|
|
return ErrorMissingParameter(json_object, "assetDirectory");
|
|
}
|
|
if (main_script == NULL) {
|
|
return ErrorMissingParameter(json_object, "mainScript");
|
|
}
|
|
if (packages_file == NULL) {
|
|
return ErrorMissingParameter(json_object, "packagesFile");
|
|
}
|
|
|
|
// Convert the actual flutter view hex id into a number.
|
|
uintptr_t view_id_as_num =
|
|
std::stoull((view_id + kViewIdPrefxLength), nullptr, 16);
|
|
|
|
// Ask the Shell to run this script in the specified view. This will run a
|
|
// task on the UI thread before returning.
|
|
Shell& shell = Shell::Shared();
|
|
bool view_existed = false;
|
|
Dart_Port main_port = ILLEGAL_PORT;
|
|
shell.RunInPlatformView(view_id_as_num, main_script, packages_file,
|
|
asset_directory, &view_existed, &main_port);
|
|
|
|
if (!view_existed) {
|
|
// If the view did not exist this request has definitely failed.
|
|
return ErrorUnknownView(json_object, view_id);
|
|
} else if (main_port == ILLEGAL_PORT) {
|
|
// We did not create an isolate.
|
|
return ErrorIsolateSpawn(json_object, view_id);
|
|
} else {
|
|
// The view existed and the isolate was created. Success.
|
|
std::stringstream response;
|
|
response << "{\"type\":\"Success\","
|
|
<< "\"viewId\": \"" << kViewIdPrefx << "0x" << std::hex << view_id
|
|
<< "\","
|
|
<< "\"isolateId\": \"isolates/" << std::dec << main_port << "\""
|
|
<< "}";
|
|
*json_object = strdup(response.str().c_str());
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const char* PlatformViewServiceProtocol::kListViewsExtensionName =
|
|
"_flutter.listViews";
|
|
|
|
bool PlatformViewServiceProtocol::ListViews(const char* method,
|
|
const char** param_keys,
|
|
const char** param_values,
|
|
intptr_t num_params,
|
|
void* user_data,
|
|
const char** json_object) {
|
|
// Ask the Shell for the list of platform views. This will run a task on
|
|
// the UI thread before returning.
|
|
Shell& shell = Shell::Shared();
|
|
std::vector<Shell::PlatformViewInfo> platform_views;
|
|
shell.WaitForPlatformViewIds(&platform_views);
|
|
|
|
std::stringstream response;
|
|
|
|
response << "{\"type\":\"FlutterViewList\",\"views\":[";
|
|
bool prefix_comma = false;
|
|
for (auto it = platform_views.begin(); it != platform_views.end(); it++) {
|
|
uintptr_t view_id = it->view_id;
|
|
int64_t isolate_id = it->isolate_id;
|
|
if (!view_id) {
|
|
continue;
|
|
}
|
|
if (prefix_comma) {
|
|
response << ',';
|
|
} else {
|
|
prefix_comma = true;
|
|
}
|
|
response << "{\"type\":\"FlutterView\", \"id\": \"" << kViewIdPrefx << "0x"
|
|
<< std::hex << view_id << "\","
|
|
<< "\"isolateId\": \"isolates/" << std::dec << isolate_id << "\""
|
|
<< "}";
|
|
}
|
|
response << "]}";
|
|
// Copy the response.
|
|
*json_object = strdup(response.str().c_str());
|
|
return true;
|
|
}
|
|
|
|
} // namespace shell
|
|
} // namespace sky
|