OLD | NEW |
---|---|
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <windows.h> | 5 #include <windows.h> |
6 | |
grt (UTC plus 2)
2011/07/04 18:42:04
remove blank line?
robertshield
2011/07/04 19:12:31
Done.
| |
7 #include <mshtmhst.h> | |
6 #include <urlmon.h> | 8 #include <urlmon.h> |
7 | 9 |
10 #include "base/win/scoped_variant.h" | |
8 #include "chrome/installer/util/html_dialog.h" | 11 #include "chrome/installer/util/html_dialog.h" |
9 | 12 |
10 #pragma comment(lib, "urlmon.lib") | 13 #pragma comment(lib, "urlmon.lib") |
11 | 14 |
12 namespace { | |
13 // Signature of MSHTML.DLL ShowHTMLDlg. | |
14 typedef HRESULT (CALLBACK *ShowHTMLDlg)(HWND parent_hwnd, | |
15 IMoniker *moniker, | |
16 VARIANT *in_args, | |
17 TCHAR *options, | |
18 VARIANT *out_args); | |
19 } // namespace. | |
20 | |
21 namespace installer { | 15 namespace installer { |
22 | 16 |
23 // Windows implementation of the HTML dialog class. The main danger with | 17 // Windows implementation of the HTML dialog class. The main danger with |
24 // using the IE embedded control as a child window of a custom window is that | 18 // using the IE embedded control as a child window of a custom window is that |
25 // it still contains too much browser functionality, allowing the user to do | 19 // it still contains too much browser functionality, allowing the user to do |
26 // things that are not expected of a plain dialog. ShowHTMLDialog API solves | 20 // things that are not expected of a plain dialog. ShowHTMLDialog API solves |
27 // that problem but gives us a not very customizable frame. We solve that | 21 // that problem but gives us a not very customizable frame. We solve that |
28 // using hooks to end up with a robust dialog at the expense of having to do | 22 // using hooks to end up with a robust dialog at the expense of having to do |
29 // the buttons in html itself, like so: | 23 // the buttons in html itself, like so: |
30 // | 24 // |
31 // <form onsubmit="submit_it(this); return false;"> | 25 // <form onsubmit="submit_it(this); return false;"> |
32 // <input name="accept" type="checkbox" /> My cool option | 26 // <input name="accept" type="checkbox" /> My cool option |
33 // <input name="submit" type="submit" value="[accept]" /> | 27 // <input name="submit" type="submit" value="[accept]" /> |
34 // </form> | 28 // </form> |
35 // | 29 // |
36 // function submit_it(f) { | 30 // function submit_it(f) { |
37 // if (f.accept.checked) { | 31 // if (f.accept.checked) { |
38 // window.returnValue = 1; <-- this matches HTML_DLG_ACCEPT | 32 // window.returnValue = 1; <-- this matches HTML_DLG_ACCEPT |
39 // } else { | 33 // } else { |
40 // window.returnValue = 2; <-- this matches HTML_DLG_DECLINE | 34 // window.returnValue = 2; <-- this matches HTML_DLG_DECLINE |
41 // } | 35 // } |
42 // window.close(); | 36 // window.close(); |
43 // } | 37 // } |
44 // | 38 // |
45 // Note that on the submit handler you need to set window.returnValue to one of | 39 // Note that on the submit handler you need to set window.returnValue to one of |
46 // the values of DialogResult and call window.close(). | 40 // the values of DialogResult and call window.close(). |
47 | 41 |
48 class HTMLDialogWin : public HTMLDialog { | 42 class HTMLDialogWin : public HTMLDialog { |
49 public: | 43 public: |
50 explicit HTMLDialogWin(const std::wstring& url) : url_(url) { | 44 explicit HTMLDialogWin(const std::wstring& url, |
grt (UTC plus 2)
2011/07/04 18:42:04
remove "explicit"
robertshield
2011/07/04 19:12:31
Done.
| |
45 const std::wstring& param) : url_(url), | |
46 param_(param) { | |
51 if (!mshtml_) | 47 if (!mshtml_) |
52 mshtml_ = LoadLibrary(L"MSHTML.DLL"); | 48 mshtml_ = LoadLibrary(L"MSHTML.DLL"); |
53 } | 49 } |
54 | 50 |
55 virtual DialogResult ShowModal(void* parent_window, | 51 virtual DialogResult ShowModal(void* parent_window, |
56 CustomizationCallback* callback) { | 52 CustomizationCallback* callback) { |
57 int result = HTML_DLG_DECLINE; | 53 int result = HTML_DLG_DECLINE; |
58 if (!InternalDoDialog(callback, &result)) | 54 if (!InternalDoDialog(callback, &result)) |
59 return HTML_DLG_ERROR; | 55 return HTML_DLG_ERROR; |
60 return static_cast<DialogResult>(result); | 56 return static_cast<DialogResult>(result); |
61 } | 57 } |
62 | 58 |
63 // TODO(cpu): Not yet implemented. | 59 // TODO(cpu): Not yet implemented. |
64 virtual std::wstring GetExtraResult() { | 60 virtual std::wstring GetExtraResult() { |
65 return std::wstring(); | 61 return std::wstring(); |
66 } | 62 } |
67 | 63 |
68 private: | 64 private: |
69 bool InternalDoDialog(CustomizationCallback* callback, int* result); | 65 bool InternalDoDialog(CustomizationCallback* callback, int* result); |
70 static LRESULT CALLBACK MsgFilter(int code, WPARAM wParam, LPARAM lParam); | 66 static LRESULT CALLBACK MsgFilter(int code, WPARAM wParam, LPARAM lParam); |
71 | 67 |
72 std::wstring url_; | 68 std::wstring url_; |
69 std::wstring param_; | |
73 static HHOOK hook_; | 70 static HHOOK hook_; |
74 static HINSTANCE mshtml_; | 71 static HINSTANCE mshtml_; |
75 static CustomizationCallback* callback_; | 72 static CustomizationCallback* callback_; |
76 }; | 73 }; |
77 | 74 |
78 HTMLDialog* CreateNativeHTMLDialog(const std::wstring& url) { | 75 HTMLDialog* CreateNativeHTMLDialog(const std::wstring& url, |
79 return new HTMLDialogWin(url); | 76 const std::wstring& param) { |
77 return new HTMLDialogWin(url, param); | |
80 } | 78 } |
81 | 79 |
82 HHOOK HTMLDialogWin::hook_ = NULL; | 80 HHOOK HTMLDialogWin::hook_ = NULL; |
83 HINSTANCE HTMLDialogWin::mshtml_ = NULL; | 81 HINSTANCE HTMLDialogWin::mshtml_ = NULL; |
84 HTMLDialogWin::CustomizationCallback* HTMLDialogWin::callback_ = NULL; | 82 HTMLDialogWin::CustomizationCallback* HTMLDialogWin::callback_ = NULL; |
85 | 83 |
86 // This hook function gets called for messages bound to the windows that | 84 // This hook function gets called for messages bound to the windows that |
87 // ShowHTMLDialog creates. We tell apart the top window because it has the | 85 // ShowHTMLDialog creates. We tell apart the top window because it has the |
88 // system menu style. | 86 // system menu style. |
89 LRESULT HTMLDialogWin::MsgFilter(int code, WPARAM wParam, LPARAM lParam) { | 87 LRESULT HTMLDialogWin::MsgFilter(int code, WPARAM wParam, LPARAM lParam) { |
90 static bool tweak_window = true; | 88 static bool tweak_window = true; |
91 if (lParam && tweak_window) { | 89 if (lParam && tweak_window) { |
92 HWND target_window = reinterpret_cast<MSG*>(lParam)->hwnd; | 90 HWND target_window = reinterpret_cast<MSG*>(lParam)->hwnd; |
93 if (target_window) { | 91 if (target_window) { |
94 LONG_PTR style = ::GetWindowLongPtrW(target_window, GWL_STYLE); | 92 LONG_PTR style = ::GetWindowLongPtrW(target_window, GWL_STYLE); |
95 if (style & WS_SYSMENU) { | 93 if (style & WS_SYSMENU) { |
96 tweak_window = false; | 94 tweak_window = false; |
97 callback_->OnBeforeDisplay(target_window); | 95 callback_->OnBeforeDisplay(target_window); |
98 } | 96 } |
99 } | 97 } |
100 } | 98 } |
101 // Always call the next hook in the chain. | 99 // Always call the next hook in the chain. |
102 return ::CallNextHookEx(hook_, code, wParam, lParam); | 100 return ::CallNextHookEx(hook_, code, wParam, lParam); |
103 } | 101 } |
104 | 102 |
105 bool HTMLDialogWin::InternalDoDialog(CustomizationCallback* callback, | 103 bool HTMLDialogWin::InternalDoDialog(CustomizationCallback* callback, |
106 int* result) { | 104 int* result) { |
107 if (!mshtml_) | 105 if (!mshtml_) |
108 return false; | 106 return false; |
109 ShowHTMLDlg show_html_dialog = | 107 SHOWHTMLDIALOGFN* show_html_dialog = |
110 reinterpret_cast<ShowHTMLDlg>(GetProcAddress(mshtml_, "ShowHTMLDialog")); | 108 reinterpret_cast<SHOWHTMLDIALOGFN*>( |
109 GetProcAddress(mshtml_, "ShowHTMLDialog")); | |
111 if (!show_html_dialog) | 110 if (!show_html_dialog) |
112 return false; | 111 return false; |
113 | 112 |
114 IMoniker *url_moniker = NULL; | 113 IMoniker *url_moniker = NULL; |
115 ::CreateURLMoniker(NULL, url_.c_str(), &url_moniker); | 114 ::CreateURLMonikerEx(NULL, url_.c_str(), &url_moniker, URL_MK_UNIFORM); |
116 if (!url_moniker) | 115 if (!url_moniker) |
117 return false; | 116 return false; |
118 | 117 |
119 wchar_t* extra_args = NULL; | 118 wchar_t* extra_args = NULL; |
120 if (callback) { | 119 if (callback) { |
121 callback->OnBeforeCreation(reinterpret_cast<void**>(&extra_args)); | 120 callback->OnBeforeCreation(reinterpret_cast<void**>(&extra_args)); |
122 // Sets a windows hook for this thread only. | 121 // Sets a windows hook for this thread only. |
123 hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, MsgFilter, NULL, | 122 hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, MsgFilter, NULL, |
124 GetCurrentThreadId()); | 123 GetCurrentThreadId()); |
125 if (hook_) | 124 if (hook_) |
126 callback_ = callback; | 125 callback_ = callback; |
127 } | 126 } |
128 | 127 |
128 // Pass our parameter to the dialog in the dialogArguments property of | |
129 // the window object. | |
130 base::win::ScopedVariant dialog_args(param_.c_str()); | |
grt (UTC plus 2)
2011/07/04 18:42:04
nit: dialog_args(param_.data(), param_.size()) wil
robertshield
2011/07/04 19:12:31
It would avoid an extra call, but it feels like pr
grt (UTC plus 2)
2011/07/04 19:24:19
SysAllocStringLen is broken if it reads memory bey
| |
131 | |
129 VARIANT v_result; | 132 VARIANT v_result; |
130 ::VariantInit(&v_result); | 133 ::VariantInit(&v_result); |
131 | 134 |
132 // Creates the window with the embedded IE control in a modal loop. | 135 // Creates the window with the embedded IE control in a modal loop. |
133 HRESULT hr = show_html_dialog(NULL, url_moniker, NULL, extra_args, &v_result); | 136 HRESULT hr = show_html_dialog(NULL, |
137 url_moniker, | |
138 dialog_args.AsInput(), | |
139 extra_args, | |
140 &v_result); | |
134 url_moniker->Release(); | 141 url_moniker->Release(); |
135 | 142 |
136 if (v_result.vt == VT_I4) | 143 if (v_result.vt == VT_I4) |
137 *result = v_result.intVal; | 144 *result = v_result.intVal; |
138 ::VariantClear(&v_result); | 145 ::VariantClear(&v_result); |
139 | 146 |
140 if (hook_) { | 147 if (hook_) { |
141 ::UnhookWindowsHookEx(hook_); | 148 ::UnhookWindowsHookEx(hook_); |
142 callback_ = NULL; | 149 callback_ = NULL; |
143 hook_ = NULL; | 150 hook_ = NULL; |
(...skipping 12 matching lines...) Expand all Loading... | |
156 if (!window) | 163 if (!window) |
157 return; | 164 return; |
158 HWND top_window = static_cast<HWND>(window); | 165 HWND top_window = static_cast<HWND>(window); |
159 LONG_PTR style = ::GetWindowLongPtrW(top_window, GWL_STYLE); | 166 LONG_PTR style = ::GetWindowLongPtrW(top_window, GWL_STYLE); |
160 ::SetWindowLongPtrW(top_window, GWL_STYLE, style & ~WS_SYSMENU); | 167 ::SetWindowLongPtrW(top_window, GWL_STYLE, style & ~WS_SYSMENU); |
161 HICON ico = ::LoadIcon(NULL, IDI_INFORMATION); | 168 HICON ico = ::LoadIcon(NULL, IDI_INFORMATION); |
162 ::SendMessageW(top_window, WM_SETICON, ICON_SMALL, | 169 ::SendMessageW(top_window, WM_SETICON, ICON_SMALL, |
163 reinterpret_cast<LPARAM>(ico)); | 170 reinterpret_cast<LPARAM>(ico)); |
164 } | 171 } |
165 | 172 |
166 EulaHTMLDialog::EulaHTMLDialog(const std::wstring& file) { | 173 EulaHTMLDialog::EulaHTMLDialog(const std::wstring& file, |
167 dialog_ = CreateNativeHTMLDialog(file); | 174 const std::wstring& param) { |
175 dialog_ = CreateNativeHTMLDialog(file, param); | |
168 } | 176 } |
169 | 177 |
170 EulaHTMLDialog::~EulaHTMLDialog() { | 178 EulaHTMLDialog::~EulaHTMLDialog() { |
171 delete dialog_; | 179 delete dialog_; |
172 } | 180 } |
173 | 181 |
174 EulaHTMLDialog::Outcome EulaHTMLDialog::ShowModal() { | 182 EulaHTMLDialog::Outcome EulaHTMLDialog::ShowModal() { |
175 Customizer customizer; | 183 Customizer customizer; |
176 HTMLDialog::DialogResult dr = dialog_->ShowModal(NULL, &customizer); | 184 HTMLDialog::DialogResult dr = dialog_->ShowModal(NULL, &customizer); |
177 if (HTMLDialog::HTML_DLG_ACCEPT == dr) | 185 if (HTMLDialog::HTML_DLG_ACCEPT == dr) |
178 return EulaHTMLDialog::ACCEPTED; | 186 return EulaHTMLDialog::ACCEPTED; |
179 else if (HTMLDialog::HTML_DLG_EXTRA == dr) | 187 else if (HTMLDialog::HTML_DLG_EXTRA == dr) |
180 return EulaHTMLDialog::ACCEPTED_OPT_IN; | 188 return EulaHTMLDialog::ACCEPTED_OPT_IN; |
181 else | 189 else |
182 return EulaHTMLDialog::REJECTED; | 190 return EulaHTMLDialog::REJECTED; |
183 } | 191 } |
184 | 192 |
185 } // namespace installer | 193 } // namespace installer |
OLD | NEW |