PageRenderTime 1702ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc

https://gitlab.com/jonnialva90/iridium-browser
C++ | 358 lines | 278 code | 55 blank | 25 comment | 33 complexity | d5ca2439f8f6073c72b24de22d26c104 MD5 | raw file
  1. // Copyright 2014 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/ui/views/apps/app_info_dialog/app_info_summary_panel.h"
  5. #include <vector>
  6. #include "base/callback_forward.h"
  7. #include "base/files/file_util.h"
  8. #include "base/logging.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "base/task_runner_util.h"
  11. #include "chrome/browser/extensions/extension_service.h"
  12. #include "chrome/browser/extensions/extension_util.h"
  13. #include "chrome/browser/extensions/launch_util.h"
  14. #include "chrome/browser/profiles/profile.h"
  15. #include "chrome/common/extensions/extension_constants.h"
  16. #include "chrome/grit/generated_resources.h"
  17. #include "content/public/browser/browser_thread.h"
  18. #include "extensions/browser/extension_prefs.h"
  19. #include "extensions/browser/extension_system.h"
  20. #include "extensions/common/extension.h"
  21. #include "extensions/common/manifest.h"
  22. #include "extensions/common/manifest_handlers/shared_module_info.h"
  23. #include "extensions/common/manifest_url_handlers.h"
  24. #include "ui/base/l10n/l10n_util.h"
  25. #include "ui/base/models/combobox_model.h"
  26. #include "ui/base/text/bytes_formatting.h"
  27. #include "ui/views/controls/combobox/combobox.h"
  28. #include "ui/views/controls/label.h"
  29. #include "ui/views/controls/link.h"
  30. #include "ui/views/layout/box_layout.h"
  31. #include "ui/views/layout/layout_constants.h"
  32. #include "ui/views/view.h"
  33. // A model for a combobox selecting the launch options for a hosted app.
  34. // Displays different options depending on the host OS.
  35. class LaunchOptionsComboboxModel : public ui::ComboboxModel {
  36. public:
  37. LaunchOptionsComboboxModel();
  38. ~LaunchOptionsComboboxModel() override;
  39. extensions::LaunchType GetLaunchTypeAtIndex(int index) const;
  40. int GetIndexForLaunchType(extensions::LaunchType launch_type) const;
  41. // Overridden from ui::ComboboxModel:
  42. int GetItemCount() const override;
  43. base::string16 GetItemAt(int index) override;
  44. private:
  45. // A list of the launch types available in the combobox, in order.
  46. std::vector<extensions::LaunchType> launch_types_;
  47. // A list of the messages to display in the combobox, in order. The indexes in
  48. // this list correspond to the indexes in launch_types_.
  49. std::vector<base::string16> launch_type_messages_;
  50. };
  51. LaunchOptionsComboboxModel::LaunchOptionsComboboxModel() {
  52. if (extensions::util::IsNewBookmarkAppsEnabled()) {
  53. // When bookmark apps are enabled, hosted apps can only toggle between
  54. // LAUNCH_TYPE_WINDOW and LAUNCH_TYPE_REGULAR.
  55. // TODO(sashab): Use a checkbox for this choice instead of combobox.
  56. launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR);
  57. launch_type_messages_.push_back(
  58. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_TAB));
  59. if (extensions::util::CanHostedAppsOpenInWindows()) {
  60. launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW);
  61. launch_type_messages_.push_back(
  62. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
  63. }
  64. } else {
  65. launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR);
  66. launch_type_messages_.push_back(
  67. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR));
  68. launch_types_.push_back(extensions::LAUNCH_TYPE_PINNED);
  69. launch_type_messages_.push_back(
  70. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED));
  71. if (extensions::util::CanHostedAppsOpenInWindows()) {
  72. launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW);
  73. launch_type_messages_.push_back(
  74. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
  75. }
  76. #if defined(OS_MACOSX)
  77. // Mac does not support standalone web app browser windows or maximize
  78. // unless the new bookmark apps system is enabled.
  79. launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN);
  80. launch_type_messages_.push_back(
  81. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN));
  82. #else
  83. // Even though the launch type is Full Screen, it is more accurately
  84. // described as Maximized in non-Mac OSs.
  85. launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN);
  86. launch_type_messages_.push_back(
  87. l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED));
  88. #endif
  89. }
  90. }
  91. LaunchOptionsComboboxModel::~LaunchOptionsComboboxModel() {
  92. }
  93. extensions::LaunchType LaunchOptionsComboboxModel::GetLaunchTypeAtIndex(
  94. int index) const {
  95. return launch_types_[index];
  96. }
  97. int LaunchOptionsComboboxModel::GetIndexForLaunchType(
  98. extensions::LaunchType launch_type) const {
  99. for (size_t i = 0; i < launch_types_.size(); i++) {
  100. if (launch_types_[i] == launch_type) {
  101. return i;
  102. }
  103. }
  104. // If the requested launch type is not available, just select the first one.
  105. LOG(WARNING) << "Unavailable launch type " << launch_type << " selected.";
  106. return 0;
  107. }
  108. int LaunchOptionsComboboxModel::GetItemCount() const {
  109. return launch_types_.size();
  110. }
  111. base::string16 LaunchOptionsComboboxModel::GetItemAt(int index) {
  112. return launch_type_messages_[index];
  113. }
  114. AppInfoSummaryPanel::AppInfoSummaryPanel(Profile* profile,
  115. const extensions::Extension* app)
  116. : AppInfoPanel(profile, app),
  117. size_value_(NULL),
  118. homepage_link_(NULL),
  119. licenses_link_(NULL),
  120. launch_options_combobox_(NULL),
  121. weak_ptr_factory_(this) {
  122. SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical,
  123. 0,
  124. 0,
  125. views::kRelatedControlVerticalSpacing));
  126. AddSubviews();
  127. }
  128. AppInfoSummaryPanel::~AppInfoSummaryPanel() {
  129. // Destroy view children before their models.
  130. RemoveAllChildViews(true);
  131. }
  132. void AppInfoSummaryPanel::AddDescriptionAndLinksControl(
  133. views::View* vertical_stack) {
  134. views::View* description_and_labels_stack = new views::View();
  135. description_and_labels_stack->SetLayoutManager(
  136. new views::BoxLayout(views::BoxLayout::kVertical,
  137. 0,
  138. 0,
  139. views::kRelatedControlSmallVerticalSpacing));
  140. if (!app_->description().empty()) {
  141. // TODO(sashab): Clip the app's description to 4 lines, and use Label's
  142. // built-in elide behavior to add ellipses at the end: crbug.com/358053
  143. const size_t max_length = 400;
  144. base::string16 text = base::UTF8ToUTF16(app_->description());
  145. if (text.length() > max_length) {
  146. text = text.substr(0, max_length);
  147. text += base::ASCIIToUTF16(" ... ");
  148. }
  149. views::Label* description_label = new views::Label(text);
  150. description_label->SetMultiLine(true);
  151. description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  152. description_and_labels_stack->AddChildView(description_label);
  153. }
  154. if (CanShowAppHomePage()) {
  155. homepage_link_ = new views::Link(
  156. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_HOMEPAGE_LINK));
  157. homepage_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  158. homepage_link_->set_listener(this);
  159. description_and_labels_stack->AddChildView(homepage_link_);
  160. }
  161. if (CanDisplayLicenses()) {
  162. licenses_link_ = new views::Link(
  163. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LICENSES_BUTTON_TEXT));
  164. licenses_link_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  165. licenses_link_->set_listener(this);
  166. description_and_labels_stack->AddChildView(licenses_link_);
  167. }
  168. vertical_stack->AddChildView(description_and_labels_stack);
  169. }
  170. void AppInfoSummaryPanel::AddDetailsControl(views::View* vertical_stack) {
  171. // Component apps have no details.
  172. if (app_->location() == extensions::Manifest::COMPONENT)
  173. return;
  174. views::View* details_list =
  175. CreateVerticalStack(views::kRelatedControlSmallVerticalSpacing);
  176. // Add the size.
  177. views::Label* size_title = new views::Label(
  178. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_LABEL));
  179. size_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  180. size_value_ = new views::Label(
  181. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_LOADING_LABEL));
  182. size_value_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  183. StartCalculatingAppSize();
  184. details_list->AddChildView(CreateKeyValueField(size_title, size_value_));
  185. // The version doesn't make sense for bookmark apps.
  186. if (!app_->from_bookmark()) {
  187. views::Label* version_title = new views::Label(
  188. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_VERSION_LABEL));
  189. version_title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  190. views::Label* version_value =
  191. new views::Label(base::UTF8ToUTF16(app_->GetVersionForDisplay()));
  192. version_value->SetHorizontalAlignment(gfx::ALIGN_LEFT);
  193. details_list->AddChildView(
  194. CreateKeyValueField(version_title, version_value));
  195. }
  196. vertical_stack->AddChildView(details_list);
  197. }
  198. void AppInfoSummaryPanel::AddLaunchOptionControl(views::View* vertical_stack) {
  199. if (!CanSetLaunchType())
  200. return;
  201. launch_options_combobox_model_.reset(new LaunchOptionsComboboxModel());
  202. launch_options_combobox_ =
  203. new views::Combobox(launch_options_combobox_model_.get());
  204. launch_options_combobox_->set_listener(this);
  205. launch_options_combobox_->SetSelectedIndex(
  206. launch_options_combobox_model_->GetIndexForLaunchType(GetLaunchType()));
  207. vertical_stack->AddChildView(launch_options_combobox_);
  208. }
  209. void AppInfoSummaryPanel::AddSubviews() {
  210. AddChildView(CreateHeading(
  211. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_APP_OVERVIEW_TITLE)));
  212. views::View* vertical_stack =
  213. CreateVerticalStack(views::kUnrelatedControlVerticalSpacing);
  214. AddChildView(vertical_stack);
  215. AddDescriptionAndLinksControl(vertical_stack);
  216. AddDetailsControl(vertical_stack);
  217. AddLaunchOptionControl(vertical_stack);
  218. }
  219. void AppInfoSummaryPanel::OnPerformAction(views::Combobox* combobox) {
  220. if (combobox == launch_options_combobox_) {
  221. SetLaunchType(launch_options_combobox_model_->GetLaunchTypeAtIndex(
  222. launch_options_combobox_->selected_index()));
  223. } else {
  224. NOTREACHED();
  225. }
  226. }
  227. void AppInfoSummaryPanel::LinkClicked(views::Link* source, int event_flags) {
  228. if (source == homepage_link_) {
  229. ShowAppHomePage();
  230. } else if (source == licenses_link_) {
  231. DisplayLicenses();
  232. } else {
  233. NOTREACHED();
  234. }
  235. }
  236. void AppInfoSummaryPanel::StartCalculatingAppSize() {
  237. base::PostTaskAndReplyWithResult(
  238. content::BrowserThread::GetBlockingPool(),
  239. FROM_HERE,
  240. base::Bind(&base::ComputeDirectorySize, app_->path()),
  241. base::Bind(&AppInfoSummaryPanel::OnAppSizeCalculated, AsWeakPtr()));
  242. }
  243. void AppInfoSummaryPanel::OnAppSizeCalculated(int64 app_size_in_bytes) {
  244. const int one_mebibyte_in_bytes = 1024 * 1024;
  245. if (app_size_in_bytes < one_mebibyte_in_bytes) {
  246. size_value_->SetText(
  247. l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_SIZE_SMALL_LABEL));
  248. } else {
  249. size_value_->SetText(ui::FormatBytesWithUnits(
  250. app_size_in_bytes, ui::DATA_UNITS_MEBIBYTE, true));
  251. }
  252. }
  253. extensions::LaunchType AppInfoSummaryPanel::GetLaunchType() const {
  254. return extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile_),
  255. app_);
  256. }
  257. void AppInfoSummaryPanel::SetLaunchType(
  258. extensions::LaunchType launch_type) const {
  259. DCHECK(CanSetLaunchType());
  260. extensions::SetLaunchType(profile_, app_->id(), launch_type);
  261. }
  262. bool AppInfoSummaryPanel::CanSetLaunchType() const {
  263. // V2 apps and extensions don't have a launch type, and neither does the
  264. // Chrome app.
  265. return !app_->is_platform_app() && !app_->is_extension() &&
  266. app_->id() != extension_misc::kChromeAppId;
  267. }
  268. void AppInfoSummaryPanel::ShowAppHomePage() {
  269. DCHECK(CanShowAppHomePage());
  270. OpenLink(extensions::ManifestURL::GetHomepageURL(app_));
  271. Close();
  272. }
  273. bool AppInfoSummaryPanel::CanShowAppHomePage() const {
  274. return extensions::ManifestURL::SpecifiedHomepageURL(app_);
  275. }
  276. void AppInfoSummaryPanel::DisplayLicenses() {
  277. DCHECK(CanDisplayLicenses());
  278. for (const auto& license_url : GetLicenseUrls())
  279. OpenLink(license_url);
  280. Close();
  281. }
  282. bool AppInfoSummaryPanel::CanDisplayLicenses() const {
  283. return !GetLicenseUrls().empty();
  284. }
  285. const std::vector<GURL> AppInfoSummaryPanel::GetLicenseUrls() const {
  286. if (!extensions::SharedModuleInfo::ImportsModules(app_))
  287. return std::vector<GURL>();
  288. std::vector<GURL> license_urls;
  289. ExtensionService* service =
  290. extensions::ExtensionSystem::Get(profile_)->extension_service();
  291. DCHECK(service);
  292. const std::vector<extensions::SharedModuleInfo::ImportInfo>& imports =
  293. extensions::SharedModuleInfo::GetImports(app_);
  294. for (const auto& shared_module : imports) {
  295. const extensions::Extension* imported_module =
  296. service->GetExtensionById(shared_module.extension_id, true);
  297. DCHECK(imported_module);
  298. GURL about_page = extensions::ManifestURL::GetAboutPage(imported_module);
  299. if (about_page != GURL::EmptyGURL())
  300. license_urls.push_back(about_page);
  301. }
  302. return license_urls;
  303. }