This source file includes following definitions.
- param_
- ShowModal
- GetExtraResult
- CreateNativeHTMLDialog
- MsgFilter
- InternalDoDialog
- OnBeforeCreation
- OnBeforeDisplay
- ShowModal
#include <windows.h>
#include <mshtmhst.h>
#include <urlmon.h>
#include "base/win/scoped_variant.h"
#include "chrome/installer/util/html_dialog.h"
#pragma comment(lib, "urlmon.lib")
namespace installer {
class HTMLDialogWin : public HTMLDialog {
public:
HTMLDialogWin(const std::wstring& url, const std::wstring& param)
: url_(url), param_(param) {
if (!mshtml_)
mshtml_ = LoadLibrary(L"MSHTML.DLL");
}
virtual DialogResult ShowModal(void* parent_window,
CustomizationCallback* callback) {
int result = HTML_DLG_DECLINE;
if (!InternalDoDialog(callback, &result))
return HTML_DLG_ERROR;
return static_cast<DialogResult>(result);
}
virtual std::wstring GetExtraResult() {
return extra_result_;
}
private:
bool InternalDoDialog(CustomizationCallback* callback, int* result);
static LRESULT CALLBACK MsgFilter(int code, WPARAM wParam, LPARAM lParam);
std::wstring url_;
std::wstring param_;
static HHOOK hook_;
static HINSTANCE mshtml_;
static CustomizationCallback* callback_;
std::wstring extra_result_;
};
HTMLDialog* CreateNativeHTMLDialog(const std::wstring& url,
const std::wstring& param) {
return new HTMLDialogWin(url, param);
}
HHOOK HTMLDialogWin::hook_ = NULL;
HINSTANCE HTMLDialogWin::mshtml_ = NULL;
HTMLDialogWin::CustomizationCallback* HTMLDialogWin::callback_ = NULL;
LRESULT HTMLDialogWin::MsgFilter(int code, WPARAM wParam, LPARAM lParam) {
static bool tweak_window = true;
if (lParam && tweak_window) {
HWND target_window = reinterpret_cast<MSG*>(lParam)->hwnd;
if (target_window) {
LONG_PTR style = ::GetWindowLongPtrW(target_window, GWL_STYLE);
if (style & WS_SYSMENU) {
tweak_window = false;
callback_->OnBeforeDisplay(target_window);
}
}
}
return ::CallNextHookEx(hook_, code, wParam, lParam);
}
bool HTMLDialogWin::InternalDoDialog(CustomizationCallback* callback,
int* result) {
if (!mshtml_)
return false;
SHOWHTMLDIALOGFN* show_html_dialog =
reinterpret_cast<SHOWHTMLDIALOGFN*>(
GetProcAddress(mshtml_, "ShowHTMLDialog"));
if (!show_html_dialog)
return false;
IMoniker *url_moniker = NULL;
::CreateURLMonikerEx(NULL, url_.c_str(), &url_moniker, URL_MK_UNIFORM);
if (!url_moniker)
return false;
wchar_t* extra_args = NULL;
if (callback) {
callback->OnBeforeCreation(&extra_args);
hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, MsgFilter, NULL,
GetCurrentThreadId());
if (hook_)
callback_ = callback;
}
base::win::ScopedVariant dialog_args(param_.c_str());
VARIANT v_result;
::VariantInit(&v_result);
HRESULT hr = show_html_dialog(NULL,
url_moniker,
dialog_args.AsInput(),
extra_args,
&v_result);
url_moniker->Release();
if (v_result.vt == VT_I4) {
*result = v_result.intVal;
} else if (v_result.vt == VT_BSTR) {
*result = HTML_DLG_EXTRA;
extra_result_.assign(v_result.bstrVal, SysStringLen(v_result.bstrVal));
}
::VariantClear(&v_result);
if (hook_) {
::UnhookWindowsHookEx(hook_);
callback_ = NULL;
hook_ = NULL;
}
return SUCCEEDED(hr);
}
void EulaHTMLDialog::Customizer::OnBeforeCreation(wchar_t** extra) {
}
void EulaHTMLDialog::Customizer::OnBeforeDisplay(void* window) {
if (!window)
return;
HWND top_window = static_cast<HWND>(window);
LONG_PTR style = ::GetWindowLongPtrW(top_window, GWL_STYLE);
::SetWindowLongPtrW(top_window, GWL_STYLE, style & ~WS_SYSMENU);
HICON ico = ::LoadIcon(NULL, IDI_INFORMATION);
::SendMessageW(top_window, WM_SETICON, ICON_SMALL,
reinterpret_cast<LPARAM>(ico));
}
EulaHTMLDialog::EulaHTMLDialog(const std::wstring& file,
const std::wstring& param) {
dialog_ = CreateNativeHTMLDialog(file, param);
}
EulaHTMLDialog::~EulaHTMLDialog() {
delete dialog_;
}
EulaHTMLDialog::Outcome EulaHTMLDialog::ShowModal() {
Customizer customizer;
HTMLDialog::DialogResult dr = dialog_->ShowModal(NULL, &customizer);
if (HTMLDialog::HTML_DLG_ACCEPT == dr)
return EulaHTMLDialog::ACCEPTED;
else if (HTMLDialog::HTML_DLG_EXTRA == dr)
return EulaHTMLDialog::ACCEPTED_OPT_IN;
else
return EulaHTMLDialog::REJECTED;
}
}