1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/it2me/it2me_confirmation_dialog.h"
#include <windows.h>
#include <commctrl.h>
#include <cstdint>
#include <memory>
#include <string>
#include <string_view>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/i18n/message_formatter.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "remoting/host/win/core_resource.h"
#include "remoting/host/win/simple_task_dialog.h"
namespace remoting {
namespace {
// Time to wait before closing the dialog and cancelling the connection.
constexpr base::TimeDelta kDialogTimeout = base::Minutes(1);
class It2MeConfirmationDialogWin : public It2MeConfirmationDialog {
public:
It2MeConfirmationDialogWin();
It2MeConfirmationDialogWin(const It2MeConfirmationDialogWin&) = delete;
It2MeConfirmationDialogWin& operator=(const It2MeConfirmationDialogWin&) =
delete;
~It2MeConfirmationDialogWin() override;
// It2MeConfirmationDialog implementation.
void Show(const std::string& remote_user_email,
ResultCallback callback) override;
};
It2MeConfirmationDialogWin::It2MeConfirmationDialogWin() = default;
It2MeConfirmationDialogWin::~It2MeConfirmationDialogWin() = default;
void It2MeConfirmationDialogWin::Show(const std::string& remote_user_email,
ResultCallback callback) {
DCHECK(!remote_user_email.empty());
DCHECK(callback);
// Default to a cancelled state. We only accept the connection if the user
// explicitly allows it.
Result result = Result::CANCEL;
// |resource_module| does not need to be freed as GetModuleHandle() does not
// increment the refcount for the module. This DLL is not unloaded until the
// process exits so using a stored handle is safe.
HMODULE resource_module = GetModuleHandle(L"remoting_core.dll");
if (resource_module == nullptr) {
PLOG(ERROR) << "GetModuleHandle() failed";
std::move(callback).Run(result);
return;
}
SimpleTaskDialog task_dialog(resource_module);
if (!task_dialog.SetTitleTextWithStringId(IDS_PRODUCT_NAME) ||
!task_dialog.AppendButtonWithStringId(IDYES,
IDS_SHARE_CONFIRM_DIALOG_CONFIRM) ||
!task_dialog.AppendButtonWithStringId(IDNO,
IDS_SHARE_CONFIRM_DIALOG_DECLINE)) {
LOG(ERROR) << "Failed to load text for confirmation dialog.";
std::move(callback).Run(result);
return;
}
const wchar_t* message_stringw = nullptr;
int string_length = LoadStringW(
resource_module, IDS_SHARE_CONFIRM_DIALOG_MESSAGE_WITH_USERNAME,
reinterpret_cast<wchar_t*>(&message_stringw),
/*cchBufferMax=*/0);
if (string_length <= 0) {
PLOG(ERROR) << "Failed to load message text for confirmation dialog.";
std::move(callback).Run(result);
return;
}
std::wstring message_text =
base::AsWString(base::i18n::MessageFormatter::FormatWithNumberedArgs(
base::AsStringPiece16(
std::wstring_view(message_stringw, string_length)),
base::UTF8ToUTF16(remote_user_email)));
task_dialog.set_message_text(message_text);
task_dialog.set_default_button(IDNO);
task_dialog.set_dialog_timeout(kDialogTimeout);
std::optional<int> button_result = task_dialog.Show();
if (!button_result.has_value()) {
std::move(callback).Run(result);
return;
}
if (*button_result == IDYES) {
// Only accept the connection if the user chose 'share'.
result = Result::OK;
}
std::move(callback).Run(result);
}
} // namespace
std::unique_ptr<It2MeConfirmationDialog>
It2MeConfirmationDialogFactory::Create() {
return std::make_unique<It2MeConfirmationDialogWin>();
}
} // namespace remoting
|