| // Copyright (c) 2006-2008 The Chromium 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 "webkit/default_plugin/install_dialog.h" |
| |
| #include "base/hash_tables.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/string_util.h" |
| #include "grit/webkit_strings.h" |
| #include "webkit/default_plugin/plugin_impl.h" |
| #include "webkit/glue/webkit_glue.h" |
| |
| typedef base::hash_map<const std::wstring, PluginInstallDialog*> DialogMap; |
| base::LazyInstance<DialogMap> s_dialogs(base::LINKER_INITIALIZED); |
| |
| PluginInstallDialog* PluginInstallDialog::AddInstaller( |
| PluginInstallerImpl* plugin_impl, const std::wstring& plugin_name) { |
| PluginInstallDialog* dialog; |
| if (s_dialogs.Get().count(plugin_name)) { |
| dialog = s_dialogs.Get()[plugin_name]; |
| } else { |
| dialog = new PluginInstallDialog(plugin_name); |
| } |
| |
| dialog->installers_.push_back(plugin_impl); |
| return dialog; |
| } |
| |
| PluginInstallDialog::PluginInstallDialog(const std::wstring& plugin_name) |
| : plugin_name_(plugin_name) { |
| s_dialogs.Get()[plugin_name] = this; |
| } |
| |
| PluginInstallDialog::~PluginInstallDialog() { |
| s_dialogs.Get().erase(plugin_name_); |
| if (IsWindow()) |
| DestroyWindow(); |
| } |
| |
| void PluginInstallDialog::RemoveInstaller(PluginInstallerImpl* installer) { |
| for (size_t i = 0; i < installers_.size(); ++i) { |
| if (installers_[i] == installer) { |
| installers_.erase(installers_.begin() + i); |
| if (installers_.empty()) |
| delete this; |
| return; |
| } |
| } |
| NOTREACHED(); |
| } |
| |
| void PluginInstallDialog::ShowInstallDialog(HWND parent) { |
| if (IsWindow()) |
| return; |
| |
| Create(parent, NULL); |
| ShowWindow(SW_SHOW); |
| } |
| |
| HWND PluginInstallDialog::Create(HWND parent_window, LPARAM init_param) { |
| // Most of the code here is based on CDialogImpl<T>::Create. |
| DCHECK(m_hWnd == NULL); |
| |
| // Allocate the thunk structure here, where we can fail |
| // gracefully. |
| BOOL thunk_inited = m_thunk.Init(NULL, NULL); |
| if (thunk_inited == FALSE) { |
| SetLastError(ERROR_OUTOFMEMORY); |
| return NULL; |
| } |
| |
| _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); |
| |
| #ifdef _DEBUG |
| m_bModal = false; |
| #endif // _DEBUG |
| |
| HINSTANCE instance_handle = _AtlBaseModule.GetResourceInstance(); |
| |
| HRSRC dialog_resource = FindResource(instance_handle, |
| MAKEINTRESOURCE(IDD), RT_DIALOG); |
| if (!dialog_resource) { |
| NOTREACHED(); |
| return NULL; |
| } |
| |
| HGLOBAL dialog_template = LoadResource(instance_handle, |
| dialog_resource); |
| if (!dialog_template) { |
| NOTREACHED(); |
| return NULL; |
| } |
| |
| _DialogSplitHelper::DLGTEMPLATEEX* dialog_template_struct = |
| reinterpret_cast<_DialogSplitHelper::DLGTEMPLATEEX *>( |
| ::LockResource(dialog_template)); |
| DCHECK(dialog_template_struct != NULL); |
| |
| unsigned long dialog_template_size = |
| SizeofResource(instance_handle, dialog_resource); |
| |
| HGLOBAL rtl_layout_dialog_template = NULL; |
| |
| if (PluginInstallerImpl::IsRTLLayout()) { |
| rtl_layout_dialog_template = GlobalAlloc(GPTR, dialog_template_size); |
| DCHECK(rtl_layout_dialog_template != NULL); |
| |
| _DialogSplitHelper::DLGTEMPLATEEX* rtl_layout_dialog_template_struct = |
| reinterpret_cast<_DialogSplitHelper::DLGTEMPLATEEX*>( |
| ::GlobalLock(rtl_layout_dialog_template)); |
| DCHECK(rtl_layout_dialog_template_struct != NULL); |
| |
| memcpy(rtl_layout_dialog_template_struct, dialog_template_struct, |
| dialog_template_size); |
| |
| rtl_layout_dialog_template_struct->exStyle |= |
| (WS_EX_LAYOUTRTL | WS_EX_RTLREADING); |
| |
| dialog_template_struct = rtl_layout_dialog_template_struct; |
| } |
| |
| HWND dialog_window = |
| CreateDialogIndirectParam( |
| instance_handle, |
| reinterpret_cast<DLGTEMPLATE*>(dialog_template_struct), |
| parent_window, StartDialogProc, init_param); |
| |
| DCHECK(m_hWnd == dialog_window); |
| |
| if (rtl_layout_dialog_template) { |
| GlobalUnlock(rtl_layout_dialog_template); |
| GlobalFree(rtl_layout_dialog_template); |
| } |
| |
| return dialog_window; |
| } |
| |
| |
| LRESULT PluginInstallDialog::OnInitDialog(UINT message, WPARAM wparam, |
| LPARAM lparam, BOOL& handled) { |
| std::wstring dialog_title = |
| PluginInstallerImpl::ReplaceStringForPossibleEmptyReplacement( |
| IDS_DEFAULT_PLUGIN_CONFIRMATION_DIALOG_TITLE, |
| IDS_DEFAULT_PLUGIN_CONFIRMATION_DIALOG_TITLE_NO_PLUGIN_NAME, |
| plugin_name_); |
| AdjustTextDirectionality(&dialog_title); |
| SetWindowText(dialog_title.c_str()); |
| |
| std::wstring get_the_plugin_btn_msg = |
| webkit_glue::GetLocalizedString( |
| IDS_DEFAULT_PLUGIN_GET_THE_PLUGIN_BTN_MSG); |
| AdjustTextDirectionality(&get_the_plugin_btn_msg); |
| SetDlgItemText(IDB_GET_THE_PLUGIN, get_the_plugin_btn_msg.c_str()); |
| |
| std::wstring cancel_plugin_download_msg = |
| webkit_glue::GetLocalizedString( |
| IDS_DEFAULT_PLUGIN_CANCEL_PLUGIN_DOWNLOAD_MSG); |
| AdjustTextDirectionality(&cancel_plugin_download_msg); |
| SetDlgItemText(IDCANCEL, cancel_plugin_download_msg.c_str()); |
| |
| std::wstring plugin_user_action_msg = |
| PluginInstallerImpl::ReplaceStringForPossibleEmptyReplacement( |
| IDS_DEFAULT_PLUGIN_USER_OPTION_MSG, |
| IDS_DEFAULT_PLUGIN_USER_OPTION_MSG_NO_PLUGIN_NAME, |
| plugin_name_); |
| AdjustTextDirectionality(&plugin_user_action_msg); |
| SetDlgItemText(IDC_PLUGIN_INSTALL_CONFIRMATION_LABEL, |
| plugin_user_action_msg.c_str()); |
| return 0; |
| } |
| |
| |
| LRESULT PluginInstallDialog::OnGetPlugin(WORD notify_code, WORD id, |
| HWND wnd_ctl, BOOL &handled) { |
| DestroyWindow(); |
| if (!installers_.empty()) |
| installers_[0]->DownloadPlugin(); |
| |
| return 0; |
| } |
| |
| LRESULT PluginInstallDialog::OnCancel(WORD notify_code, WORD id, HWND wnd_ctl, |
| BOOL &handled) { |
| DestroyWindow(); |
| if (!installers_.empty()) |
| installers_[0]->DownloadCancelled(); |
| return 0; |
| } |
| |
| // TODO(idana) bug# 1246452: use the library l10n_util once it is moved from |
| // the Chrome module into the Base module. For now, we simply copy/paste the |
| // same code. |
| void PluginInstallDialog::AdjustTextDirectionality(std::wstring* text) const { |
| if (PluginInstallerImpl::IsRTLLayout()) { |
| // Inserting an RLE (Right-To-Left Embedding) mark as the first character. |
| text->insert(0, L"\x202B"); |
| |
| // Inserting a PDF (Pop Directional Formatting) mark as the last character. |
| text->append(L"\x202C"); |
| } |
| } |