// 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 #include #include #include #include #include #include #include #include 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> 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> result); }; // static void PathProviderPlugin::RegisterWithRegistrar( flutter::PluginRegistrar *registrar) { auto channel = std::make_unique>( registrar->messenger(), "plugins.flutter.io/path_provider", &flutter::StandardMethodCodec::GetInstance()); // Uses new instead of make_unique due to private constructor. std::unique_ptr 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> 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(registrar)); }