forked from lxm_flutter/FlutterUnit
168 lines
5.7 KiB
C++
168 lines
5.7 KiB
C++
// Copyright 2019 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
#include "include/path_provider_fde/path_provider_plugin.h"
|
|
|
|
#include <ShlObj.h>
|
|
#include <flutter/method_channel.h>
|
|
#include <flutter/plugin_registrar_windows.h>
|
|
#include <flutter/standard_method_codec.h>
|
|
#include <windows.h>
|
|
|
|
#include <codecvt>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
namespace {
|
|
|
|
using flutter::EncodableValue;
|
|
|
|
// Converts an null-terminated array of wchar_t's to a std::string.
|
|
std::string StdStringFromWideChars(wchar_t *wide_chars) {
|
|
std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> wide_to_utf8;
|
|
return wide_to_utf8.to_bytes(wide_chars);
|
|
}
|
|
|
|
// Gets the path to the given folder ID, without verifying that it exists,
|
|
// or an empty string on failure.
|
|
std::string GetFolderPath(REFKNOWNFOLDERID folder_id) {
|
|
wchar_t *wide_path = nullptr;
|
|
if (!SUCCEEDED(SHGetKnownFolderPath(folder_id, KF_FLAG_DONT_VERIFY, nullptr,
|
|
&wide_path))) {
|
|
return "";
|
|
}
|
|
std::string path = StdStringFromWideChars(wide_path);
|
|
CoTaskMemFree(wide_path);
|
|
return path;
|
|
}
|
|
|
|
// Returns the name of the executable, without the .exe extension, or an empty
|
|
// string on failure.
|
|
std::string GetExecutableName() {
|
|
wchar_t buffer[MAX_PATH];
|
|
if (GetModuleFileName(nullptr, buffer, MAX_PATH) == 0) {
|
|
return "";
|
|
}
|
|
std::string executable_path = StdStringFromWideChars(buffer);
|
|
size_t last_separator_position = executable_path.find_last_of('\\');
|
|
std::string executable_name;
|
|
if (last_separator_position == std::string::npos) {
|
|
executable_name = executable_path;
|
|
} else {
|
|
executable_name = executable_path.substr(last_separator_position + 1);
|
|
}
|
|
// Strip the .exe extension, if present.
|
|
std::string extension = ".exe";
|
|
if (executable_name.compare(executable_name.size() - extension.size(),
|
|
extension.size(), extension) == 0) {
|
|
executable_name =
|
|
executable_name.substr(0, executable_name.size() - extension.size());
|
|
}
|
|
return executable_name;
|
|
}
|
|
|
|
class PathProviderPlugin : public flutter::Plugin {
|
|
public:
|
|
static void RegisterWithRegistrar(flutter::PluginRegistrar *registrar);
|
|
|
|
virtual ~PathProviderPlugin();
|
|
|
|
private:
|
|
PathProviderPlugin();
|
|
|
|
// Called when a method is called on plugin channel;
|
|
void HandleMethodCall(
|
|
const flutter::MethodCall<> &method_call,
|
|
std::unique_ptr<flutter::MethodResult<>> result);
|
|
};
|
|
|
|
// static
|
|
void PathProviderPlugin::RegisterWithRegistrar(
|
|
flutter::PluginRegistrar *registrar) {
|
|
auto channel = std::make_unique<flutter::MethodChannel<>>(
|
|
registrar->messenger(), "plugins.flutter.io/path_provider",
|
|
&flutter::StandardMethodCodec::GetInstance());
|
|
|
|
// Uses new instead of make_unique due to private constructor.
|
|
std::unique_ptr<PathProviderPlugin> plugin(new PathProviderPlugin());
|
|
|
|
channel->SetMethodCallHandler(
|
|
[plugin_pointer = plugin.get()](const auto &call, auto result) {
|
|
plugin_pointer->HandleMethodCall(call, std::move(result));
|
|
});
|
|
|
|
registrar->AddPlugin(std::move(plugin));
|
|
}
|
|
|
|
PathProviderPlugin::PathProviderPlugin() = default;
|
|
|
|
PathProviderPlugin::~PathProviderPlugin() = default;
|
|
|
|
void PathProviderPlugin::HandleMethodCall(
|
|
const flutter::MethodCall<> &method_call,
|
|
std::unique_ptr<flutter::MethodResult<>> result) {
|
|
if (method_call.method_name().compare("getTemporaryDirectory") == 0) {
|
|
wchar_t path_buffer[MAX_PATH];
|
|
DWORD length = GetTempPath(MAX_PATH, path_buffer);
|
|
if (length == 0 || length > MAX_PATH) {
|
|
result->Error("Unable to get temporary path");
|
|
return;
|
|
}
|
|
std::string result_path = StdStringFromWideChars(path_buffer);
|
|
result->Success(EncodableValue(result_path));
|
|
} else if (method_call.method_name().compare(
|
|
"getApplicationSupportDirectory") == 0) {
|
|
std::string path = GetFolderPath(FOLDERID_RoamingAppData);
|
|
if (path.empty()) {
|
|
result->Error("Unable to get application data path");
|
|
return;
|
|
}
|
|
// Use the executable name as the subdirectory for now.
|
|
std::string exe_name = GetExecutableName();
|
|
if (exe_name.empty()) {
|
|
result->Error("Unable to get exe name");
|
|
return;
|
|
}
|
|
std::ostringstream response_stream;
|
|
response_stream << path << "\\" << exe_name;
|
|
result->Success(EncodableValue(response_stream.str()));
|
|
} else if (method_call.method_name().compare(
|
|
"getApplicationDocumentsDirectory") == 0) {
|
|
std::string path = GetFolderPath(FOLDERID_Documents);
|
|
if (path.empty()) {
|
|
result->Error("Unable to get documents path");
|
|
return;
|
|
}
|
|
result->Success(EncodableValue(path));
|
|
} else if (method_call.method_name().compare("getDownloadsDirectory") == 0) {
|
|
std::string path = GetFolderPath(FOLDERID_Downloads);
|
|
if (path.empty()) {
|
|
result->Error("Unable to get downloads path");
|
|
return;
|
|
}
|
|
result->Success(EncodableValue(path));
|
|
} else {
|
|
result->NotImplemented();
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
void PathProviderPluginRegisterWithRegistrar(
|
|
FlutterDesktopPluginRegistrarRef registrar) {
|
|
PathProviderPlugin::RegisterWithRegistrar(
|
|
flutter::PluginRegistrarManager::GetInstance()
|
|
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
|
|
}
|