PageRenderTime 49ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/external/chromium/chrome/browser/first_run/try_chrome_dialog_view.cc

https://gitlab.com/brian0218/rk3066_r-box_android4.2.2_sdk
C++ | 260 lines | 200 code | 27 blank | 33 comment | 11 complexity | 962c4bc2dd4cd5146c361a249e72c2e4 MD5 | raw file
  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
  3. // found in the LICENSE file.
  4. #include "chrome/browser/first_run/try_chrome_dialog_view.h"
  5. #include <shellapi.h>
  6. #include "base/logging.h"
  7. #include "base/message_loop.h"
  8. #include "base/string16.h"
  9. #include "chrome/browser/process_singleton.h"
  10. #include "chrome/installer/util/browser_distribution.h"
  11. #include "grit/chromium_strings.h"
  12. #include "grit/generated_resources.h"
  13. #include "grit/theme_resources.h"
  14. #include "ui/base/resource/resource_bundle.h"
  15. #include "views/controls/button/image_button.h"
  16. #include "views/controls/button/radio_button.h"
  17. #include "views/controls/image_view.h"
  18. #include "views/layout/grid_layout.h"
  19. #include "views/layout/layout_constants.h"
  20. #include "views/widget/root_view.h"
  21. #include "views/widget/widget.h"
  22. #include "ui/base/l10n/l10n_util.h"
  23. namespace {
  24. const wchar_t kHelpCenterUrl[] =
  25. L"https://www.google.com/support/chrome/bin/answer.py?answer=150752";
  26. } // namespace
  27. // static
  28. TryChromeDialogView::Result TryChromeDialogView::Show(
  29. size_t version,
  30. ProcessSingleton* process_singleton) {
  31. if (version > 10000) {
  32. // This is a test value. We want to make sure we exercise
  33. // returning this early. See EarlyReturnTest test harness.
  34. return NOT_NOW;
  35. }
  36. TryChromeDialogView dialog(version);
  37. return dialog.ShowModal(process_singleton);
  38. }
  39. TryChromeDialogView::TryChromeDialogView(size_t version)
  40. : version_(version),
  41. popup_(NULL),
  42. try_chrome_(NULL),
  43. kill_chrome_(NULL),
  44. result_(COUNT) {
  45. }
  46. TryChromeDialogView::~TryChromeDialogView() {
  47. }
  48. TryChromeDialogView::Result TryChromeDialogView::ShowModal(
  49. ProcessSingleton* process_singleton) {
  50. ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  51. views::ImageView* icon = new views::ImageView();
  52. icon->SetImage(*rb.GetBitmapNamed(IDR_PRODUCT_ICON_32));
  53. gfx::Size icon_size = icon->GetPreferredSize();
  54. // An approximate window size. After Layout() we'll get better bounds.
  55. views::Widget::CreateParams params(views::Widget::CreateParams::TYPE_POPUP);
  56. params.can_activate = true;
  57. popup_ = views::Widget::CreateWidget(params);
  58. if (!popup_) {
  59. NOTREACHED();
  60. return DIALOG_ERROR;
  61. }
  62. gfx::Rect pos(310, 160);
  63. popup_->Init(NULL, pos);
  64. views::RootView* root_view = popup_->GetRootView();
  65. // The window color is a tiny bit off-white.
  66. root_view->set_background(
  67. views::Background::CreateSolidBackground(0xfc, 0xfc, 0xfc));
  68. views::GridLayout* layout = views::GridLayout::CreatePanel(root_view);
  69. if (!layout) {
  70. NOTREACHED();
  71. return DIALOG_ERROR;
  72. }
  73. root_view->SetLayoutManager(layout);
  74. views::ColumnSet* columns;
  75. // First row: [icon][pad][text][button].
  76. columns = layout->AddColumnSet(0);
  77. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING, 0,
  78. views::GridLayout::FIXED, icon_size.width(),
  79. icon_size.height());
  80. columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
  81. columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
  82. views::GridLayout::USE_PREF, 0, 0);
  83. columns->AddColumn(views::GridLayout::TRAILING, views::GridLayout::FILL, 1,
  84. views::GridLayout::USE_PREF, 0, 0);
  85. // Second row: [pad][pad][radio 1].
  86. columns = layout->AddColumnSet(1);
  87. columns->AddPaddingColumn(0, icon_size.width());
  88. columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
  89. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
  90. views::GridLayout::USE_PREF, 0, 0);
  91. // Third row: [pad][pad][radio 2].
  92. columns = layout->AddColumnSet(2);
  93. columns->AddPaddingColumn(0, icon_size.width());
  94. columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
  95. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
  96. views::GridLayout::USE_PREF, 0, 0);
  97. // Fourth row: [pad][pad][button][pad][button].
  98. columns = layout->AddColumnSet(3);
  99. columns->AddPaddingColumn(0, icon_size.width());
  100. columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
  101. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 0,
  102. views::GridLayout::USE_PREF, 0, 0);
  103. columns->AddPaddingColumn(0, views::kRelatedButtonHSpacing);
  104. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 0,
  105. views::GridLayout::USE_PREF, 0, 0);
  106. // Fifth row: [pad][pad][link].
  107. columns = layout->AddColumnSet(4);
  108. columns->AddPaddingColumn(0, icon_size.width());
  109. columns->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
  110. columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
  111. views::GridLayout::USE_PREF, 0, 0);
  112. // First row views.
  113. layout->StartRow(0, 0);
  114. layout->AddView(icon);
  115. // Find out what experiment we are conducting.
  116. BrowserDistribution* dist = BrowserDistribution::GetDistribution();
  117. if (!dist) {
  118. NOTREACHED() << "Cannot determine browser distribution";
  119. return DIALOG_ERROR;
  120. }
  121. BrowserDistribution::UserExperiment experiment;
  122. if (!dist->GetExperimentDetails(&experiment, version_) ||
  123. !experiment.heading) {
  124. NOTREACHED() << "Cannot determine which headline to show.";
  125. return DIALOG_ERROR;
  126. }
  127. string16 heading = l10n_util::GetStringUTF16(experiment.heading);
  128. views::Label* label = new views::Label(heading);
  129. label->SetFont(rb.GetFont(ResourceBundle::MediumBoldFont));
  130. label->SetMultiLine(true);
  131. label->SizeToFit(200);
  132. label->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
  133. layout->AddView(label);
  134. // The close button is custom.
  135. views::ImageButton* close_button = new views::ImageButton(this);
  136. close_button->SetImage(views::CustomButton::BS_NORMAL,
  137. rb.GetBitmapNamed(IDR_CLOSE_BAR));
  138. close_button->SetImage(views::CustomButton::BS_HOT,
  139. rb.GetBitmapNamed(IDR_CLOSE_BAR_H));
  140. close_button->SetImage(views::CustomButton::BS_PUSHED,
  141. rb.GetBitmapNamed(IDR_CLOSE_BAR_P));
  142. close_button->set_tag(BT_CLOSE_BUTTON);
  143. layout->AddView(close_button);
  144. // Second row views.
  145. const string16 try_it(l10n_util::GetStringUTF16(IDS_TRY_TOAST_TRY_OPT));
  146. layout->StartRowWithPadding(0, 1, 0, 10);
  147. try_chrome_ = new views::RadioButton(try_it, 1);
  148. layout->AddView(try_chrome_);
  149. try_chrome_->SetChecked(true);
  150. // Third row views.
  151. const string16 kill_it(l10n_util::GetStringUTF16(IDS_UNINSTALL_CHROME));
  152. layout->StartRow(0, 2);
  153. kill_chrome_ = new views::RadioButton(kill_it, 1);
  154. layout->AddView(kill_chrome_);
  155. // Fourth row views.
  156. const string16 ok_it(l10n_util::GetStringUTF16(IDS_OK));
  157. const string16 cancel_it(l10n_util::GetStringUTF16(IDS_TRY_TOAST_CANCEL));
  158. const string16 why_this(l10n_util::GetStringUTF16(IDS_TRY_TOAST_WHY));
  159. layout->StartRowWithPadding(0, 3, 0, 10);
  160. views::Button* accept_button = new views::NativeButton(this, ok_it);
  161. accept_button->set_tag(BT_OK_BUTTON);
  162. layout->AddView(accept_button);
  163. views::Button* cancel_button = new views::NativeButton(this, cancel_it);
  164. cancel_button->set_tag(BT_CLOSE_BUTTON);
  165. layout->AddView(cancel_button);
  166. // Fifth row views.
  167. layout->StartRowWithPadding(0, 4, 0, 10);
  168. views::Link* link = new views::Link(why_this);
  169. link->SetController(this);
  170. layout->AddView(link);
  171. // We resize the window according to the layout manager. This takes into
  172. // account the differences between XP and Vista fonts and buttons.
  173. layout->Layout(root_view);
  174. gfx::Size preferred = layout->GetPreferredSize(root_view);
  175. pos = ComputeWindowPosition(preferred.width(), preferred.height(),
  176. base::i18n::IsRTL());
  177. popup_->SetBounds(pos);
  178. // Carve the toast shape into the window.
  179. SetToastRegion(popup_->GetNativeView(),
  180. preferred.width(), preferred.height());
  181. // Time to show the window in a modal loop. We don't want this chrome
  182. // instance trying to serve WM_COPYDATA requests, as we'll surely crash.
  183. process_singleton->Lock(popup_->GetNativeView());
  184. popup_->Show();
  185. MessageLoop::current()->Run();
  186. process_singleton->Unlock();
  187. return result_;
  188. }
  189. gfx::Rect TryChromeDialogView::ComputeWindowPosition(int width,
  190. int height,
  191. bool is_RTL) {
  192. // The 'Shell_TrayWnd' is the taskbar. We like to show our window in that
  193. // monitor if we can. This code works even if such window is not found.
  194. HWND taskbar = ::FindWindowW(L"Shell_TrayWnd", NULL);
  195. HMONITOR monitor = ::MonitorFromWindow(taskbar, MONITOR_DEFAULTTOPRIMARY);
  196. MONITORINFO info = {sizeof(info)};
  197. if (!GetMonitorInfoW(monitor, &info)) {
  198. // Quite unexpected. Do a best guess at a visible rectangle.
  199. return gfx::Rect(20, 20, width + 20, height + 20);
  200. }
  201. // The |rcWork| is the work area. It should account for the taskbars that
  202. // are in the screen when we called the function.
  203. int left = is_RTL ? info.rcWork.left : info.rcWork.right - width;
  204. int top = info.rcWork.bottom - height;
  205. return gfx::Rect(left, top, width, height);
  206. }
  207. void TryChromeDialogView::SetToastRegion(HWND window, int w, int h) {
  208. static const POINT polygon[] = {
  209. {0, 4}, {1, 2}, {2, 1}, {4, 0}, // Left side.
  210. {w-4, 0}, {w-2, 1}, {w-1, 2}, {w, 4}, // Right side.
  211. {w, h}, {0, h}
  212. };
  213. HRGN region = ::CreatePolygonRgn(polygon, arraysize(polygon), WINDING);
  214. ::SetWindowRgn(window, region, FALSE);
  215. }
  216. void TryChromeDialogView::ButtonPressed(views::Button* sender,
  217. const views::Event& event) {
  218. if (sender->tag() == BT_CLOSE_BUTTON) {
  219. // The user pressed cancel or the [x] button.
  220. result_ = NOT_NOW;
  221. } else if (!try_chrome_) {
  222. // We don't have radio buttons, the user pressed ok.
  223. result_ = TRY_CHROME;
  224. } else {
  225. // The outcome is according to the selected ratio button.
  226. result_ = try_chrome_->checked() ? TRY_CHROME : UNINSTALL_CHROME;
  227. }
  228. popup_->Close();
  229. MessageLoop::current()->Quit();
  230. }
  231. void TryChromeDialogView::LinkActivated(views::Link* source, int event_flags) {
  232. ::ShellExecuteW(NULL, L"open", kHelpCenterUrl, NULL, NULL, SW_SHOW);
  233. }