arc_save_handler.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. // Copyright 2021 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/arc_save_handler.h"
  5. #include "base/containers/contains.h"
  6. #include "components/app_restore/app_launch_info.h"
  7. #include "components/app_restore/app_restore_info.h"
  8. #include "components/app_restore/app_restore_utils.h"
  9. #include "components/app_restore/full_restore_save_handler.h"
  10. #include "components/app_restore/window_info.h"
  11. #include "components/app_restore/window_properties.h"
  12. #include "ui/aura/window.h"
  13. namespace full_restore {
  14. namespace {
  15. // Repeat timer interval between each checking that whether a task is created
  16. // for each app launching.
  17. constexpr base::TimeDelta kCheckCycleInterval = base::Seconds(600);
  18. } // namespace
  19. ArcSaveHandler::ArcSaveHandler(const base::FilePath& profile_path)
  20. : profile_path_(profile_path) {}
  21. ArcSaveHandler::~ArcSaveHandler() = default;
  22. void ArcSaveHandler::SaveAppLaunchInfo(AppLaunchInfoPtr app_launch_info) {
  23. DCHECK(app_launch_info->arc_session_id.has_value());
  24. // Save |app_launch_info| to |session_id_to_app_launch_info_|, and wait for
  25. // the ARC task to be created.
  26. int32_t session_id = app_launch_info->arc_session_id.value();
  27. // If the ghost window has been created for `session_id`, and the launch info
  28. // hasn't been added yet, add `app_launch_info` to the restore data.
  29. if (base::Contains(ghost_window_session_id_to_app_id_, session_id)) {
  30. if (!FullRestoreSaveHandler::GetInstance()->HasAppRestoreData(
  31. profile_path_, app_launch_info->app_id, session_id)) {
  32. app_launch_info->window_id = session_id;
  33. FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo(
  34. profile_path_, std::move(app_launch_info));
  35. // Go through `arc_window_candidates_`. If the window for `session_id` has
  36. // been created, call OnAppLaunched to save the window info.
  37. auto window_it = std::find_if(
  38. arc_window_candidates_.begin(), arc_window_candidates_.end(),
  39. [session_id](aura::Window* window) {
  40. return window->GetProperty(app_restore::kGhostWindowSessionIdKey) ==
  41. session_id;
  42. });
  43. if (window_it != arc_window_candidates_.end()) {
  44. app_restore::AppRestoreInfo::GetInstance()->OnAppLaunched(*window_it);
  45. arc_window_candidates_.erase(*window_it);
  46. }
  47. }
  48. return;
  49. }
  50. session_id_to_app_launch_info_[session_id] =
  51. std::make_pair(std::move(app_launch_info), base::TimeTicks::Now());
  52. MaybeStartCheckTimer();
  53. }
  54. void ArcSaveHandler::ModifyWindowInfo(
  55. const app_restore::WindowInfo& window_info) {
  56. aura::Window* window = window_info.window;
  57. int32_t task_id = window->GetProperty(app_restore::kWindowIdKey);
  58. auto task_it = task_id_to_app_id_.find(task_id);
  59. if (task_it != task_id_to_app_id_.end()) {
  60. FullRestoreSaveHandler::GetInstance()->ModifyWindowInfo(
  61. profile_path_, task_it->second, task_id, window_info);
  62. return;
  63. }
  64. // For the ghost window, modify the window info with `session_id` as the
  65. // window id.
  66. int32_t session_id =
  67. window->GetProperty(app_restore::kGhostWindowSessionIdKey);
  68. auto it = ghost_window_session_id_to_app_id_.find(session_id);
  69. if (it != ghost_window_session_id_to_app_id_.end()) {
  70. FullRestoreSaveHandler::GetInstance()->ModifyWindowInfo(
  71. profile_path_, it->second, session_id, window_info);
  72. }
  73. }
  74. void ArcSaveHandler::OnWindowInitialized(aura::Window* window) {
  75. int32_t task_id = window->GetProperty(app_restore::kWindowIdKey);
  76. if (!base::Contains(task_id_to_app_id_, task_id)) {
  77. // Check `session_id` to see whether this is a ghost window.
  78. int32_t session_id =
  79. window->GetProperty(app_restore::kGhostWindowSessionIdKey);
  80. if (session_id < app_restore::kArcSessionIdOffsetForRestoredLaunching) {
  81. // If the task hasn't been created, and this is not a ghost window, add
  82. // `window` to `arc_window_candidates_` to wait for the task to be
  83. // created.
  84. arc_window_candidates_.insert(window);
  85. return;
  86. }
  87. // Save `session_id` for the ghost window, to wait for the task created to
  88. // replace the window id with the task id in the restore data.
  89. const std::string* app_id = window->GetProperty(app_restore::kAppIdKey);
  90. DCHECK(app_id);
  91. ghost_window_session_id_to_app_id_[session_id] = *app_id;
  92. auto it = session_id_to_app_launch_info_.find(session_id);
  93. if (it == session_id_to_app_launch_info_.end()) {
  94. arc_window_candidates_.insert(window);
  95. return;
  96. }
  97. // If there is `app_launch_info`, add it to the restore data using
  98. // `session_id` as `window_id`.
  99. auto app_launch_info = std::move(it->second.first);
  100. session_id_to_app_launch_info_.erase(it);
  101. if (session_id_to_app_launch_info_.empty())
  102. check_timer_.Stop();
  103. app_launch_info->window_id = session_id;
  104. FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo(
  105. profile_path_, std::move(app_launch_info));
  106. return;
  107. }
  108. // If the task has been created, call OnAppLaunched to save the window
  109. // information.
  110. app_restore::AppRestoreInfo::GetInstance()->OnAppLaunched(window);
  111. }
  112. void ArcSaveHandler::OnWindowDestroyed(aura::Window* window) {
  113. arc_window_candidates_.erase(window);
  114. int32_t task_id = window->GetProperty(app_restore::kWindowIdKey);
  115. auto task_it = task_id_to_app_id_.find(task_id);
  116. if (task_it != task_id_to_app_id_.end()) {
  117. // Wait for the task to be destroyed to remove the full restore data for
  118. // the task. Don't remove the window info, because it might affect the ghost
  119. // window creating due to no window bounds. Send the window to background.
  120. if (is_connection_ready_) {
  121. FullRestoreSaveHandler::GetInstance()->SendWindowToBackground(
  122. profile_path_, task_it->second, task_id);
  123. }
  124. return;
  125. }
  126. // If the ghost window has been created for `session_id`, remove
  127. // `app_launch_info` from the restore data with `session_id` as the window id.
  128. int32_t session_id =
  129. window->GetProperty(app_restore::kGhostWindowSessionIdKey);
  130. auto it = ghost_window_session_id_to_app_id_.find(session_id);
  131. if (it != ghost_window_session_id_to_app_id_.end()) {
  132. // For ghost windows, we don't need to wait for OnTaskDestroyed, so remove
  133. // AppRestoreData for `session_id`.
  134. FullRestoreSaveHandler::GetInstance()->RemoveAppRestoreData(
  135. profile_path_, it->second, session_id);
  136. ghost_window_session_id_to_app_id_.erase(it);
  137. }
  138. }
  139. void ArcSaveHandler::OnTaskCreated(const std::string& app_id,
  140. int32_t task_id,
  141. int32_t session_id) {
  142. auto it = session_id_to_app_launch_info_.find(session_id);
  143. if (it == session_id_to_app_launch_info_.end()) {
  144. auto session_it = ghost_window_session_id_to_app_id_.find(session_id);
  145. if (session_it == ghost_window_session_id_to_app_id_.end())
  146. return;
  147. // For the ghost window, modify the window id from `session_id` to
  148. // `task_id`.
  149. FullRestoreSaveHandler::GetInstance()->ModifyWindowId(
  150. profile_path_, session_it->second, session_id, task_id);
  151. ghost_window_session_id_to_app_id_.erase(session_it);
  152. task_id_to_app_id_[task_id] = app_id;
  153. return;
  154. }
  155. task_id_to_app_id_[task_id] = app_id;
  156. auto app_launch_info = std::move(it->second.first);
  157. session_id_to_app_launch_info_.erase(it);
  158. if (session_id_to_app_launch_info_.empty())
  159. check_timer_.Stop();
  160. app_launch_info->window_id = task_id;
  161. FullRestoreSaveHandler::GetInstance()->AddAppLaunchInfo(
  162. profile_path_, std::move(app_launch_info));
  163. // Go through |arc_window_candidates_|. If the window for |task_id| has been
  164. // created, call OnAppLaunched to save the window info.
  165. auto window_it = std::find_if(
  166. arc_window_candidates_.begin(), arc_window_candidates_.end(),
  167. [task_id](aura::Window* window) {
  168. return window->GetProperty(app_restore::kWindowIdKey) == task_id;
  169. });
  170. if (window_it != arc_window_candidates_.end()) {
  171. app_restore::AppRestoreInfo::GetInstance()->OnAppLaunched(*window_it);
  172. arc_window_candidates_.erase(*window_it);
  173. }
  174. }
  175. void ArcSaveHandler::OnTaskDestroyed(int32_t task_id) {
  176. auto it = task_id_to_app_id_.find(task_id);
  177. if (it == task_id_to_app_id_.end())
  178. return;
  179. FullRestoreSaveHandler::GetInstance()->RemoveAppRestoreData(
  180. profile_path_, it->second, task_id);
  181. task_id_to_app_id_.erase(task_id);
  182. }
  183. void ArcSaveHandler::OnArcPlayStoreEnabledChanged(bool enabled) {
  184. if (!enabled)
  185. task_id_to_app_id_.clear();
  186. }
  187. void ArcSaveHandler::OnTaskThemeColorUpdated(int32_t task_id,
  188. uint32_t primary_color,
  189. uint32_t status_bar_color) {
  190. auto it = task_id_to_app_id_.find(task_id);
  191. if (it == task_id_to_app_id_.end())
  192. return;
  193. FullRestoreSaveHandler::GetInstance()->ModifyThemeColor(
  194. profile_path_, it->second, task_id, primary_color, status_bar_color);
  195. }
  196. int32_t ArcSaveHandler::GetArcSessionId() {
  197. if (session_id_ >= app_restore::kArcSessionIdOffsetForRestoredLaunching) {
  198. LOG(WARNING) << "ARC session id is too large: " << session_id_;
  199. session_id_ = 0;
  200. }
  201. return ++session_id_;
  202. }
  203. std::string ArcSaveHandler::GetAppId(aura::Window* window) {
  204. // First check |task_id_to_app_id_| to see if we can find app id there.
  205. const int32_t task_id = window->GetProperty(app_restore::kWindowIdKey);
  206. auto task_iter = task_id_to_app_id_.find(task_id);
  207. if (task_iter != task_id_to_app_id_.end())
  208. return task_iter->second;
  209. // If not, try to search in |ghost_window_session_id_to_app_id_|.
  210. const int32_t session_id =
  211. window->GetProperty(app_restore::kGhostWindowSessionIdKey);
  212. auto ghost_iter = ghost_window_session_id_to_app_id_.find(session_id);
  213. return ghost_iter != ghost_window_session_id_to_app_id_.end()
  214. ? ghost_iter->second
  215. : std::string();
  216. }
  217. void ArcSaveHandler::MaybeStartCheckTimer() {
  218. if (!check_timer_.IsRunning()) {
  219. check_timer_.Start(
  220. FROM_HERE, kCheckCycleInterval,
  221. base::BindRepeating(&ArcSaveHandler::CheckTasksForAppLaunching,
  222. weak_factory_.GetWeakPtr()));
  223. }
  224. }
  225. void ArcSaveHandler::CheckTasksForAppLaunching() {
  226. std::set<int32_t> session_ids;
  227. for (const auto& it : session_id_to_app_launch_info_) {
  228. base::TimeDelta time_delta = base::TimeTicks::Now() - it.second.second;
  229. if (time_delta > kCheckCycleInterval)
  230. session_ids.insert(it.first);
  231. }
  232. for (auto id : session_ids)
  233. session_id_to_app_launch_info_.erase(id);
  234. if (session_id_to_app_launch_info_.empty())
  235. check_timer_.Stop();
  236. }
  237. } // namespace full_restore