blob: 191d51a0caa894d1e1ae36acf80be0c08f8e222a [file] [log] [blame]
// Copyright 2013 The Flutter 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/method_call.h>
#include <flutter/method_result_functions.h>
#include <flutter/standard_method_codec.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <windows.h>
#include <memory>
#include <string>
#include "url_launcher_plugin.h"
namespace url_launcher_plugin {
namespace test {
namespace {
using flutter::EncodableMap;
using flutter::EncodableValue;
using ::testing::DoAll;
using ::testing::Pointee;
using ::testing::Return;
using ::testing::SetArgPointee;
class MockSystemApis : public SystemApis {
public:
MOCK_METHOD(LSTATUS, RegCloseKey, (HKEY key), (override));
MOCK_METHOD(LSTATUS, RegQueryValueExW,
(HKEY key, LPCWSTR value_name, LPDWORD type, LPBYTE data,
LPDWORD data_size),
(override));
MOCK_METHOD(LSTATUS, RegOpenKeyExW,
(HKEY key, LPCWSTR sub_key, DWORD options, REGSAM desired,
PHKEY result),
(override));
MOCK_METHOD(HINSTANCE, ShellExecuteW,
(HWND hwnd, LPCWSTR operation, LPCWSTR file, LPCWSTR parameters,
LPCWSTR directory, int show_flags),
(override));
};
class MockMethodResult : public flutter::MethodResult<> {
public:
MOCK_METHOD(void, SuccessInternal, (const EncodableValue* result),
(override));
MOCK_METHOD(void, ErrorInternal,
(const std::string& error_code, const std::string& error_message,
const EncodableValue* details),
(override));
MOCK_METHOD(void, NotImplementedInternal, (), (override));
};
std::unique_ptr<EncodableValue> CreateArgumentsWithUrl(const std::string& url) {
EncodableMap args = {
{EncodableValue("url"), EncodableValue(url)},
};
return std::make_unique<EncodableValue>(args);
}
} // namespace
TEST(UrlLauncherPlugin, CanLaunchSuccessTrue) {
std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>();
std::unique_ptr<MockMethodResult> result =
std::make_unique<MockMethodResult>();
// Return success values from the registery commands.
HKEY fake_key = reinterpret_cast<HKEY>(1);
EXPECT_CALL(*system, RegOpenKeyExW)
.WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS)));
EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_SUCCESS));
EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS));
// Expect a success response.
EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(true))));
UrlLauncherPlugin plugin(std::move(system));
plugin.HandleMethodCall(
flutter::MethodCall("canLaunch",
CreateArgumentsWithUrl("https://some.url.com")),
std::move(result));
}
TEST(UrlLauncherPlugin, CanLaunchQueryFailure) {
std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>();
std::unique_ptr<MockMethodResult> result =
std::make_unique<MockMethodResult>();
// Return success values from the registery commands, except for the query,
// to simulate a scheme that is in the registry, but has no URL handler.
HKEY fake_key = reinterpret_cast<HKEY>(1);
EXPECT_CALL(*system, RegOpenKeyExW)
.WillOnce(DoAll(SetArgPointee<4>(fake_key), Return(ERROR_SUCCESS)));
EXPECT_CALL(*system, RegQueryValueExW).WillOnce(Return(ERROR_FILE_NOT_FOUND));
EXPECT_CALL(*system, RegCloseKey(fake_key)).WillOnce(Return(ERROR_SUCCESS));
// Expect a success response.
EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(false))));
UrlLauncherPlugin plugin(std::move(system));
plugin.HandleMethodCall(
flutter::MethodCall("canLaunch",
CreateArgumentsWithUrl("https://some.url.com")),
std::move(result));
}
TEST(UrlLauncherPlugin, CanLaunchHandlesOpenFailure) {
std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>();
std::unique_ptr<MockMethodResult> result =
std::make_unique<MockMethodResult>();
// Return failure for opening.
EXPECT_CALL(*system, RegOpenKeyExW).WillOnce(Return(ERROR_BAD_PATHNAME));
// Expect a success response.
EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(false))));
UrlLauncherPlugin plugin(std::move(system));
plugin.HandleMethodCall(
flutter::MethodCall("canLaunch",
CreateArgumentsWithUrl("https://some.url.com")),
std::move(result));
}
TEST(UrlLauncherPlugin, LaunchSuccess) {
std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>();
std::unique_ptr<MockMethodResult> result =
std::make_unique<MockMethodResult>();
// Return a success value (>32) from launching.
EXPECT_CALL(*system, ShellExecuteW)
.WillOnce(Return(reinterpret_cast<HINSTANCE>(33)));
// Expect a success response.
EXPECT_CALL(*result, SuccessInternal(Pointee(EncodableValue(true))));
UrlLauncherPlugin plugin(std::move(system));
plugin.HandleMethodCall(
flutter::MethodCall("launch",
CreateArgumentsWithUrl("https://some.url.com")),
std::move(result));
}
TEST(UrlLauncherPlugin, LaunchReportsFailure) {
std::unique_ptr<MockSystemApis> system = std::make_unique<MockSystemApis>();
std::unique_ptr<MockMethodResult> result =
std::make_unique<MockMethodResult>();
// Return a faile value (<=32) from launching.
EXPECT_CALL(*system, ShellExecuteW)
.WillOnce(Return(reinterpret_cast<HINSTANCE>(32)));
// Expect an error response.
EXPECT_CALL(*result, ErrorInternal);
UrlLauncherPlugin plugin(std::move(system));
plugin.HandleMethodCall(
flutter::MethodCall("launch",
CreateArgumentsWithUrl("https://some.url.com")),
std::move(result));
}
} // namespace test
} // namespace url_launcher_plugin