restore_data.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // Copyright 2020 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 "components/app_restore/restore_data.h"
  5. #include <utility>
  6. #include "base/i18n/number_formatting.h"
  7. #include "base/strings/string_number_conversions.h"
  8. #include "base/values.h"
  9. #include "components/app_constants/constants.h"
  10. #include "components/app_restore/app_launch_info.h"
  11. #include "components/app_restore/window_info.h"
  12. namespace app_restore {
  13. namespace {
  14. // Used to generate unique restore window IDs for desk template launches. These
  15. // IDs will all be negative in order to avoid clashes with full restore (which
  16. // are all positive). The first generated ID will be one lower than the starting
  17. // point and then proceed down. The starting point is a special case value that
  18. // a valid RWID should not use.
  19. int32_t g_desk_template_window_restore_id = -1;
  20. } // namespace
  21. RestoreData::RestoreData() = default;
  22. RestoreData::RestoreData(std::unique_ptr<base::Value> restore_data_value) {
  23. if (!restore_data_value || !restore_data_value->is_dict()) {
  24. DVLOG(0) << "Fail to parse full restore data. "
  25. << "Cannot find the full restore data dict.";
  26. return;
  27. }
  28. for (auto iter : restore_data_value->DictItems()) {
  29. const std::string& app_id = iter.first;
  30. base::Value* value = restore_data_value->FindDictKey(app_id);
  31. if (!value || !value->is_dict()) {
  32. DVLOG(0) << "Fail to parse full restore data. "
  33. << "Cannot find the app restore data dict.";
  34. continue;
  35. }
  36. for (auto data_iter : value->DictItems()) {
  37. int window_id = 0;
  38. if (!base::StringToInt(data_iter.first, &window_id)) {
  39. DVLOG(0) << "Fail to parse full restore data. "
  40. << "Cannot find the valid id.";
  41. continue;
  42. }
  43. app_id_to_launch_list_[app_id][window_id] =
  44. std::make_unique<AppRestoreData>(
  45. std::move(*value->FindDictKey(data_iter.first)));
  46. }
  47. }
  48. }
  49. RestoreData::~RestoreData() = default;
  50. std::unique_ptr<RestoreData> RestoreData::Clone() const {
  51. std::unique_ptr<RestoreData> restore_data = std::make_unique<RestoreData>();
  52. for (const auto& it : app_id_to_launch_list_) {
  53. for (const auto& data_it : it.second) {
  54. restore_data->app_id_to_launch_list_[it.first][data_it.first] =
  55. data_it.second->Clone();
  56. }
  57. }
  58. return restore_data;
  59. }
  60. base::Value RestoreData::ConvertToValue() const {
  61. base::Value restore_data_dict(base::Value::Type::DICTIONARY);
  62. for (const auto& it : app_id_to_launch_list_) {
  63. if (it.second.empty())
  64. continue;
  65. base::Value info_dict(base::Value::Type::DICTIONARY);
  66. for (const auto& data : it.second) {
  67. info_dict.SetKey(base::NumberToString(data.first),
  68. data.second->ConvertToValue());
  69. }
  70. restore_data_dict.SetKey(it.first, std::move(info_dict));
  71. }
  72. return restore_data_dict;
  73. }
  74. bool RestoreData::HasAppTypeBrowser() const {
  75. auto it = app_id_to_launch_list_.find(app_constants::kChromeAppId);
  76. if (it == app_id_to_launch_list_.end())
  77. return false;
  78. for (const auto& data : it->second) {
  79. if (data.second->app_type_browser.has_value() &&
  80. data.second->app_type_browser.value()) {
  81. return true;
  82. }
  83. }
  84. return false;
  85. }
  86. bool RestoreData::HasBrowser() const {
  87. auto it = app_id_to_launch_list_.find(app_constants::kChromeAppId);
  88. if (it == app_id_to_launch_list_.end())
  89. return false;
  90. for (const auto& data : it->second) {
  91. if (!data.second->app_type_browser.has_value() ||
  92. !data.second->app_type_browser.value()) {
  93. return true;
  94. }
  95. }
  96. return false;
  97. }
  98. bool RestoreData::HasAppRestoreData(const std::string& app_id,
  99. int32_t window_id) {
  100. return GetAppRestoreData(app_id, window_id) != nullptr;
  101. }
  102. void RestoreData::AddAppLaunchInfo(
  103. std::unique_ptr<AppLaunchInfo> app_launch_info) {
  104. if (!app_launch_info || !app_launch_info->window_id.has_value())
  105. return;
  106. const std::string app_id = app_launch_info->app_id;
  107. const int32_t window_id = app_launch_info->window_id.value();
  108. app_id_to_launch_list_[app_id][window_id] =
  109. std::make_unique<AppRestoreData>(std::move(app_launch_info));
  110. }
  111. void RestoreData::ModifyWindowId(const std::string& app_id,
  112. int32_t old_window_id,
  113. int32_t new_window_id) {
  114. auto it = app_id_to_launch_list_.find(app_id);
  115. if (it == app_id_to_launch_list_.end())
  116. return;
  117. auto data_it = it->second.find(old_window_id);
  118. if (data_it == it->second.end())
  119. return;
  120. it->second[new_window_id] = std::move(data_it->second);
  121. it->second.erase(data_it);
  122. }
  123. void RestoreData::ModifyWindowInfo(const std::string& app_id,
  124. int32_t window_id,
  125. const WindowInfo& window_info) {
  126. auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
  127. if (app_restore_data)
  128. app_restore_data->ModifyWindowInfo(window_info);
  129. }
  130. void RestoreData::ModifyThemeColor(const std::string& app_id,
  131. int32_t window_id,
  132. uint32_t primary_color,
  133. uint32_t status_bar_color) {
  134. auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
  135. if (app_restore_data)
  136. app_restore_data->ModifyThemeColor(primary_color, status_bar_color);
  137. }
  138. void RestoreData::SetNextRestoreWindowIdForChromeApp(
  139. const std::string& app_id) {
  140. auto it = app_id_to_launch_list_.find(app_id);
  141. if (it == app_id_to_launch_list_.end())
  142. return;
  143. chrome_app_id_to_current_window_id_[app_id] = it->second.begin()->first;
  144. if (it->second.size() == 1)
  145. return;
  146. // When a chrome app has multiple windows, all windows will be sent to the
  147. // background.
  148. for (auto& data_it : it->second)
  149. data_it.second->activation_index = INT32_MAX;
  150. }
  151. void RestoreData::RemoveAppRestoreData(const std::string& app_id,
  152. int window_id) {
  153. if (app_id_to_launch_list_.find(app_id) == app_id_to_launch_list_.end())
  154. return;
  155. app_id_to_launch_list_[app_id].erase(window_id);
  156. if (app_id_to_launch_list_[app_id].empty())
  157. app_id_to_launch_list_.erase(app_id);
  158. }
  159. void RestoreData::SendWindowToBackground(const std::string& app_id,
  160. int window_id) {
  161. auto* app_restore_data = GetAppRestoreDataMutable(app_id, window_id);
  162. if (app_restore_data)
  163. app_restore_data->activation_index = INT32_MAX;
  164. }
  165. void RestoreData::RemoveApp(const std::string& app_id) {
  166. app_id_to_launch_list_.erase(app_id);
  167. chrome_app_id_to_current_window_id_.erase(app_id);
  168. }
  169. std::unique_ptr<AppLaunchInfo> RestoreData::GetAppLaunchInfo(
  170. const std::string& app_id,
  171. int window_id) {
  172. auto* app_restore_data = GetAppRestoreData(app_id, window_id);
  173. return app_restore_data
  174. ? app_restore_data->GetAppLaunchInfo(app_id, window_id)
  175. : nullptr;
  176. }
  177. std::unique_ptr<WindowInfo> RestoreData::GetWindowInfo(
  178. const std::string& app_id,
  179. int window_id) {
  180. auto* app_restore_data = GetAppRestoreData(app_id, window_id);
  181. return app_restore_data ? app_restore_data->GetWindowInfo() : nullptr;
  182. }
  183. int32_t RestoreData::FetchRestoreWindowId(const std::string& app_id) {
  184. auto it = app_id_to_launch_list_.find(app_id);
  185. if (it == app_id_to_launch_list_.end())
  186. return 0;
  187. if (chrome_app_id_to_current_window_id_.find(app_id) ==
  188. chrome_app_id_to_current_window_id_.end()) {
  189. return 0;
  190. }
  191. int window_id = chrome_app_id_to_current_window_id_[app_id];
  192. // Move to the next window_id.
  193. auto data_it = it->second.find(window_id);
  194. DCHECK(data_it != it->second.end());
  195. ++data_it;
  196. if (data_it == it->second.end())
  197. chrome_app_id_to_current_window_id_.erase(app_id);
  198. else
  199. chrome_app_id_to_current_window_id_[app_id] = data_it->first;
  200. return window_id;
  201. }
  202. const AppRestoreData* RestoreData::GetAppRestoreData(const std::string& app_id,
  203. int window_id) const {
  204. auto it = app_id_to_launch_list_.find(app_id);
  205. if (it == app_id_to_launch_list_.end())
  206. return nullptr;
  207. auto data_it = it->second.find(window_id);
  208. if (data_it == it->second.end())
  209. return nullptr;
  210. return data_it->second.get();
  211. }
  212. void RestoreData::SetDeskIndex(int desk_index) {
  213. for (auto& [app_id, launch_list] : app_id_to_launch_list_) {
  214. for (auto& [window_id, app_restore_data] : launch_list) {
  215. app_restore_data->desk_id = desk_index;
  216. }
  217. }
  218. }
  219. void RestoreData::MakeWindowIdsUniqueForDeskTemplate() {
  220. for (auto& [app_id, launch_list] : app_id_to_launch_list_) {
  221. // We don't want to do in-place updates of the launch list since it
  222. // complicates traversal. We'll therefore build a new LaunchList and pilfer
  223. // the old one for AppRestoreData.
  224. LaunchList new_launch_list;
  225. for (auto& [window_id, app_restore_data] : launch_list) {
  226. new_launch_list[--g_desk_template_window_restore_id] =
  227. std::move(app_restore_data);
  228. }
  229. launch_list = std::move(new_launch_list);
  230. }
  231. }
  232. std::string RestoreData::ToString() const {
  233. if (app_id_to_launch_list_.empty())
  234. return "empty";
  235. std::string result = "( ";
  236. for (const auto& entry : app_id_to_launch_list_) {
  237. result += base::StringPrintf(
  238. "(App ID: %s, Count: %s)", entry.first.c_str(),
  239. base::UTF16ToUTF8(base::FormatNumber(entry.second.size())).c_str());
  240. for (const auto& windows : entry.second) {
  241. result +=
  242. base::StringPrintf(
  243. "(Window ID: %s)",
  244. base::UTF16ToUTF8(base::FormatNumber(windows.first)).c_str()) +
  245. windows.second->GetWindowInfo()->ToString();
  246. }
  247. }
  248. return result + " )";
  249. }
  250. AppRestoreData* RestoreData::GetAppRestoreDataMutable(const std::string& app_id,
  251. int window_id) {
  252. return const_cast<AppRestoreData*>(GetAppRestoreData(app_id, window_id));
  253. }
  254. } // namespace app_restore