OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | 5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "ash/ash_switches.h" | 11 #include "ash/ash_switches.h" |
12 #include "ash/desktop_background/desktop_background_controller.h" | 12 #include "ash/desktop_background/desktop_background_controller.h" |
13 #include "ash/multi_profile_uma.h" | 13 #include "ash/multi_profile_uma.h" |
14 #include "ash/root_window_controller.h" | 14 #include "ash/root_window_controller.h" |
15 #include "ash/shelf/shelf.h" | 15 #include "ash/shelf/shelf.h" |
16 #include "ash/shelf/shelf_item_delegate_manager.h" | 16 #include "ash/shelf/shelf_item_delegate_manager.h" |
17 #include "ash/shelf/shelf_model.h" | 17 #include "ash/shelf/shelf_model.h" |
18 #include "ash/shell.h" | 18 #include "ash/shell.h" |
19 #include "ash/system/tray/system_tray_delegate.h" | 19 #include "ash/system/tray/system_tray_delegate.h" |
20 #include "ash/wm/window_util.h" | 20 #include "ash/wm/window_util.h" |
21 #include "base/command_line.h" | 21 #include "base/command_line.h" |
22 #include "base/macros.h" | 22 #include "base/macros.h" |
23 #include "base/strings/pattern.h" | 23 #include "base/strings/pattern.h" |
24 #include "base/strings/string_number_conversions.h" | |
25 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
26 #include "base/strings/utf_string_conversions.h" | 25 #include "base/strings/utf_string_conversions.h" |
27 #include "base/values.h" | 26 #include "base/values.h" |
28 #include "build/build_config.h" | 27 #include "build/build_config.h" |
29 #include "chrome/browser/app_mode/app_mode_utils.h" | |
30 #include "chrome/browser/chrome_notification_types.h" | 28 #include "chrome/browser/chrome_notification_types.h" |
31 #include "chrome/browser/defaults.h" | 29 #include "chrome/browser/defaults.h" |
32 #include "chrome/browser/extensions/extension_app_icon_loader.h" | 30 #include "chrome/browser/extensions/extension_app_icon_loader.h" |
33 #include "chrome/browser/extensions/extension_util.h" | 31 #include "chrome/browser/extensions/extension_util.h" |
34 #include "chrome/browser/extensions/launch_util.h" | 32 #include "chrome/browser/extensions/launch_util.h" |
35 #include "chrome/browser/prefs/incognito_mode_prefs.h" | 33 #include "chrome/browser/prefs/incognito_mode_prefs.h" |
36 #include "chrome/browser/prefs/pref_service_syncable_util.h" | 34 #include "chrome/browser/prefs/pref_service_syncable_util.h" |
37 #include "chrome/browser/profiles/profile.h" | 35 #include "chrome/browser/profiles/profile.h" |
38 #include "chrome/browser/profiles/profile_manager.h" | 36 #include "chrome/browser/profiles/profile_manager.h" |
39 #include "chrome/browser/ui/ash/app_sync_ui_state.h" | 37 #include "chrome/browser/ui/ash/app_sync_ui_state.h" |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 // static | 115 // static |
118 ChromeLauncherController* ChromeLauncherController::instance_ = NULL; | 116 ChromeLauncherController* ChromeLauncherController::instance_ = NULL; |
119 | 117 |
120 namespace { | 118 namespace { |
121 | 119 |
122 // This will be used as placeholder in the list of the pinned applciatons. | 120 // This will be used as placeholder in the list of the pinned applciatons. |
123 // Note that this is NOT a valid extension identifier so that pre M31 versions | 121 // Note that this is NOT a valid extension identifier so that pre M31 versions |
124 // will ignore it. | 122 // will ignore it. |
125 const char kAppShelfIdPlaceholder[] = "AppShelfIDPlaceholder--------"; | 123 const char kAppShelfIdPlaceholder[] = "AppShelfIDPlaceholder--------"; |
126 | 124 |
127 std::string GetPrefKeyForRootWindow(aura::Window* root_window) { | 125 int64_t GetDisplayIDForShelf(ash::Shelf* shelf) { |
| 126 aura::Window* root_window = |
| 127 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); |
128 gfx::Display display = | 128 gfx::Display display = |
129 gfx::Screen::GetScreen()->GetDisplayNearestWindow(root_window); | 129 gfx::Screen::GetScreen()->GetDisplayNearestWindow(root_window); |
130 DCHECK(display.is_valid()); | 130 DCHECK(display.is_valid()); |
131 | 131 return display.id(); |
132 return base::Int64ToString(display.id()); | |
133 } | |
134 | |
135 void UpdatePerDisplayPref(PrefService* pref_service, | |
136 aura::Window* root_window, | |
137 const char* pref_key, | |
138 const std::string& value) { | |
139 std::string key = GetPrefKeyForRootWindow(root_window); | |
140 if (key.empty()) | |
141 return; | |
142 | |
143 DictionaryPrefUpdate update(pref_service, prefs::kShelfPreferences); | |
144 base::DictionaryValue* shelf_prefs = update.Get(); | |
145 base::DictionaryValue* prefs = NULL; | |
146 if (!shelf_prefs->GetDictionary(key, &prefs)) { | |
147 prefs = new base::DictionaryValue(); | |
148 shelf_prefs->Set(key, prefs); | |
149 } | |
150 prefs->SetStringWithoutPathExpansion(pref_key, value); | |
151 } | |
152 | |
153 // Returns a pref value in |pref_service| for the display of |root_window|. The | |
154 // pref value is stored in |local_path| and |path|, but |pref_service| may have | |
155 // per-display preferences and the value can be specified by policy. Here is | |
156 // the priority: | |
157 // * A value managed by policy. This is a single value that applies to all | |
158 // displays. | |
159 // * A user-set value for the specified display. | |
160 // * A user-set value in |local_path| or |path|, if no per-display settings are | |
161 // ever specified (see http://crbug.com/173719 for why). |local_path| is | |
162 // preferred. See comment in |kShelfAlignment| as to why we consider two | |
163 // prefs and why |local_path| is preferred. | |
164 // * A value recommended by policy. This is a single value that applies to all | |
165 // root windows. | |
166 // * The default value for |local_path| if the value is not recommended by | |
167 // policy. | |
168 std::string GetPrefForRootWindow(PrefService* pref_service, | |
169 aura::Window* root_window, | |
170 const char* local_path, | |
171 const char* path) { | |
172 const PrefService::Preference* local_pref = | |
173 pref_service->FindPreference(local_path); | |
174 const std::string value(pref_service->GetString(local_path)); | |
175 if (local_pref->IsManaged()) | |
176 return value; | |
177 | |
178 std::string pref_key = GetPrefKeyForRootWindow(root_window); | |
179 bool has_per_display_prefs = false; | |
180 if (!pref_key.empty()) { | |
181 const base::DictionaryValue* shelf_prefs = pref_service->GetDictionary( | |
182 prefs::kShelfPreferences); | |
183 const base::DictionaryValue* display_pref = NULL; | |
184 std::string per_display_value; | |
185 if (shelf_prefs->GetDictionary(pref_key, &display_pref) && | |
186 display_pref->GetString(path, &per_display_value)) | |
187 return per_display_value; | |
188 | |
189 // If the pref for the specified display is not found, scan the whole prefs | |
190 // and check if the prefs for other display is already specified. | |
191 std::string unused_value; | |
192 for (base::DictionaryValue::Iterator iter(*shelf_prefs); | |
193 !iter.IsAtEnd(); iter.Advance()) { | |
194 const base::DictionaryValue* display_pref = NULL; | |
195 if (iter.value().GetAsDictionary(&display_pref) && | |
196 display_pref->GetString(path, &unused_value)) { | |
197 has_per_display_prefs = true; | |
198 break; | |
199 } | |
200 } | |
201 } | |
202 | |
203 if (local_pref->IsRecommended() || !has_per_display_prefs) | |
204 return value; | |
205 | |
206 const base::Value* default_value = | |
207 pref_service->GetDefaultPrefValue(local_path); | |
208 std::string default_string; | |
209 default_value->GetAsString(&default_string); | |
210 return default_string; | |
211 } | |
212 | |
213 // Gets the shelf auto hide behavior from prefs for a root window. | |
214 ash::ShelfAutoHideBehavior GetShelfAutoHideBehaviorFromPrefs( | |
215 Profile* profile, | |
216 aura::Window* root_window) { | |
217 DCHECK(profile); | |
218 | |
219 // Don't show the shelf in app mode. | |
220 if (chrome::IsRunningInAppMode()) | |
221 return ash::SHELF_AUTO_HIDE_ALWAYS_HIDDEN; | |
222 | |
223 // See comment in |kShelfAlignment| as to why we consider two prefs. | |
224 return ash::AutoHideBehaviorFromPref(GetPrefForRootWindow( | |
225 profile->GetPrefs(), root_window, prefs::kShelfAutoHideBehaviorLocal, | |
226 prefs::kShelfAutoHideBehavior)); | |
227 } | |
228 | |
229 // Gets the shelf alignment from prefs for a root window. | |
230 ash::ShelfAlignment GetShelfAlignmentFromPrefs(Profile* profile, | |
231 aura::Window* root_window) { | |
232 DCHECK(profile); | |
233 | |
234 // See comment in |kShelfAlignment| as to why we consider two prefs. | |
235 return ash::AlignmentFromPref(GetPrefForRootWindow( | |
236 profile->GetPrefs(), root_window, prefs::kShelfAlignmentLocal, | |
237 prefs::kShelfAlignment)); | |
238 } | 132 } |
239 | 133 |
240 // If prefs have synced and no user-set value exists at |local_path|, the value | 134 // If prefs have synced and no user-set value exists at |local_path|, the value |
241 // from |synced_path| is copied to |local_path|. | 135 // from |synced_path| is copied to |local_path|. |
242 void MaybePropagatePrefToLocal( | 136 void MaybePropagatePrefToLocal( |
243 syncable_prefs::PrefServiceSyncable* pref_service, | 137 syncable_prefs::PrefServiceSyncable* pref_service, |
244 const char* local_path, | 138 const char* local_path, |
245 const char* synced_path) { | 139 const char* synced_path) { |
246 if (!pref_service->FindPreference(local_path)->HasUserSetting() && | 140 if (!pref_service->FindPreference(local_path)->HasUserSetting() && |
247 pref_service->IsSyncing()) { | 141 pref_service->IsSyncing()) { |
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1115 window->Minimize(); | 1009 window->Minimize(); |
1116 return ash::ShelfItemDelegate::kNoAction; | 1010 return ash::ShelfItemDelegate::kNoAction; |
1117 } | 1011 } |
1118 | 1012 |
1119 window->Show(); | 1013 window->Show(); |
1120 window->Activate(); | 1014 window->Activate(); |
1121 return ash::ShelfItemDelegate::kExistingWindowActivated; | 1015 return ash::ShelfItemDelegate::kExistingWindowActivated; |
1122 } | 1016 } |
1123 | 1017 |
1124 void ChromeLauncherController::OnShelfCreated(ash::Shelf* shelf) { | 1018 void ChromeLauncherController::OnShelfCreated(ash::Shelf* shelf) { |
1125 aura::Window* root_window = | 1019 const int64_t display = GetDisplayIDForShelf(shelf); |
1126 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); | |
1127 | |
1128 shelf->SetAutoHideBehavior( | 1020 shelf->SetAutoHideBehavior( |
1129 GetShelfAutoHideBehaviorFromPrefs(profile_, root_window)); | 1021 ash::GetShelfAutoHideBehaviorPref(profile_, display)); |
1130 | 1022 |
1131 if (ash::ShelfWidget::ShelfAlignmentAllowed()) | 1023 if (ash::ShelfWidget::ShelfAlignmentAllowed()) |
1132 shelf->SetAlignment(GetShelfAlignmentFromPrefs(profile_, root_window)); | 1024 shelf->SetAlignment(ash::GetShelfAlignmentPref(profile_, display)); |
1133 } | 1025 } |
1134 | 1026 |
1135 void ChromeLauncherController::OnShelfDestroyed(ash::Shelf* shelf) {} | 1027 void ChromeLauncherController::OnShelfDestroyed(ash::Shelf* shelf) {} |
1136 | 1028 |
1137 void ChromeLauncherController::OnShelfAlignmentChanged(ash::Shelf* shelf) { | 1029 void ChromeLauncherController::OnShelfAlignmentChanged(ash::Shelf* shelf) { |
1138 const char* value = ash::AlignmentToPref(shelf->GetAlignment()); | 1030 ash::SetShelfAlignmentPref(profile_, GetDisplayIDForShelf(shelf), |
1139 aura::Window* root_window = | 1031 shelf->GetAlignment()); |
1140 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); | |
1141 | |
1142 UpdatePerDisplayPref(profile_->GetPrefs(), root_window, | |
1143 prefs::kShelfAlignment, value); | |
1144 | |
1145 if (root_window == ash::Shell::GetPrimaryRootWindow()) { | |
1146 // See comment in |kShelfAlignment| about why we have two prefs here. | |
1147 profile_->GetPrefs()->SetString(prefs::kShelfAlignmentLocal, value); | |
1148 profile_->GetPrefs()->SetString(prefs::kShelfAlignment, value); | |
1149 } | |
1150 } | 1032 } |
1151 | 1033 |
1152 void ChromeLauncherController::OnShelfAutoHideBehaviorChanged( | 1034 void ChromeLauncherController::OnShelfAutoHideBehaviorChanged( |
1153 ash::Shelf* shelf) { | 1035 ash::Shelf* shelf) { |
1154 const char* value = ash::AutoHideBehaviorToPref(shelf->GetAutoHideBehavior()); | 1036 ash::SetShelfAutoHideBehaviorPref(profile_, GetDisplayIDForShelf(shelf), |
1155 if (!value) | 1037 shelf->auto_hide_behavior()); |
1156 return; | |
1157 | |
1158 aura::Window* root_window = | |
1159 shelf->shelf_widget()->GetNativeWindow()->GetRootWindow(); | |
1160 | |
1161 UpdatePerDisplayPref(profile_->GetPrefs(), root_window, | |
1162 prefs::kShelfAutoHideBehavior, value); | |
1163 | |
1164 if (root_window == ash::Shell::GetPrimaryRootWindow()) { | |
1165 // See comment in |kShelfAlignment| about why we have two prefs here. | |
1166 profile_->GetPrefs()->SetString(prefs::kShelfAutoHideBehaviorLocal, value); | |
1167 profile_->GetPrefs()->SetString(prefs::kShelfAutoHideBehavior, value); | |
1168 } | |
1169 } | 1038 } |
1170 | 1039 |
1171 void ChromeLauncherController::ShelfItemAdded(int index) { | 1040 void ChromeLauncherController::ShelfItemAdded(int index) { |
1172 // The app list launcher can get added to the shelf after we applied the | 1041 // The app list launcher can get added to the shelf after we applied the |
1173 // preferences. In that case the item might be at the wrong spot. As such we | 1042 // preferences. In that case the item might be at the wrong spot. As such we |
1174 // call the function again. | 1043 // call the function again. |
1175 if (model_->items()[index].type == ash::TYPE_APP_LIST) | 1044 if (model_->items()[index].type == ash::TYPE_APP_LIST) |
1176 UpdateAppLaunchersFromPref(); | 1045 UpdateAppLaunchersFromPref(); |
1177 } | 1046 } |
1178 | 1047 |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 bool ChromeLauncherController::IsBrowserFromActiveUser(Browser* browser) { | 1385 bool ChromeLauncherController::IsBrowserFromActiveUser(Browser* browser) { |
1517 // If running multi user mode with separate desktops, we have to check if the | 1386 // If running multi user mode with separate desktops, we have to check if the |
1518 // browser is from the active user. | 1387 // browser is from the active user. |
1519 if (chrome::MultiUserWindowManager::GetMultiProfileMode() != | 1388 if (chrome::MultiUserWindowManager::GetMultiProfileMode() != |
1520 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) | 1389 chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED) |
1521 return true; | 1390 return true; |
1522 return multi_user_util::IsProfileFromActiveUser(browser->profile()); | 1391 return multi_user_util::IsProfileFromActiveUser(browser->profile()); |
1523 } | 1392 } |
1524 | 1393 |
1525 bool ChromeLauncherController::ShelfBoundsChangesProbablyWithUser( | 1394 bool ChromeLauncherController::ShelfBoundsChangesProbablyWithUser( |
1526 aura::Window* root_window, | 1395 ash::Shelf* shelf, |
1527 const std::string& user_id) const { | 1396 const std::string& user_id) const { |
1528 Profile* other_profile = multi_user_util::GetProfileFromAccountId( | 1397 Profile* other_profile = multi_user_util::GetProfileFromAccountId( |
1529 AccountId::FromUserEmail(user_id)); | 1398 AccountId::FromUserEmail(user_id)); |
1530 if (other_profile == profile_) | 1399 if (other_profile == profile_) |
1531 return false; | 1400 return false; |
1532 | 1401 |
1533 // Note: The Auto hide state from preferences is not the same as the actual | 1402 // Note: The Auto hide state from preferences is not the same as the actual |
1534 // visibility of the shelf. Depending on all the various states (full screen, | 1403 // visibility of the shelf. Depending on all the various states (full screen, |
1535 // no window on desktop, multi user, ..) the shelf could be shown - or not. | 1404 // no window on desktop, multi user, ..) the shelf could be shown - or not. |
| 1405 const int64_t display = GetDisplayIDForShelf(shelf); |
1536 bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == | 1406 bool currently_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == |
1537 GetShelfAutoHideBehaviorFromPrefs(profile_, root_window); | 1407 ash::GetShelfAutoHideBehaviorPref(profile_, display); |
1538 bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == | 1408 bool other_shown = ash::SHELF_AUTO_HIDE_BEHAVIOR_NEVER == |
1539 GetShelfAutoHideBehaviorFromPrefs(other_profile, root_window); | 1409 ash::GetShelfAutoHideBehaviorPref(other_profile, display); |
1540 | 1410 |
1541 return currently_shown != other_shown || | 1411 return currently_shown != other_shown || |
1542 GetShelfAlignmentFromPrefs(profile_, root_window) != | 1412 ash::GetShelfAlignmentPref(profile_, display) != |
1543 GetShelfAlignmentFromPrefs(other_profile, root_window); | 1413 ash::GetShelfAlignmentPref(other_profile, display); |
1544 } | 1414 } |
1545 | 1415 |
1546 void ChromeLauncherController::OnUserProfileReadyToSwitch(Profile* profile) { | 1416 void ChromeLauncherController::OnUserProfileReadyToSwitch(Profile* profile) { |
1547 #if defined(OS_CHROMEOS) | 1417 #if defined(OS_CHROMEOS) |
1548 if (user_switch_observer_.get()) | 1418 if (user_switch_observer_.get()) |
1549 user_switch_observer_->OnUserProfileReadyToSwitch(profile); | 1419 user_switch_observer_->OnUserProfileReadyToSwitch(profile); |
1550 #endif | 1420 #endif |
1551 } | 1421 } |
1552 | 1422 |
1553 void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) { | 1423 void ChromeLauncherController::LauncherItemClosed(ash::ShelfID id) { |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1763 MoveChromeOrApplistToFinalPosition( | 1633 MoveChromeOrApplistToFinalPosition( |
1764 is_chrome, is_app_list, target_index, &chrome_index, &app_list_index); | 1634 is_chrome, is_app_list, target_index, &chrome_index, &app_list_index); |
1765 } | 1635 } |
1766 } | 1636 } |
1767 } | 1637 } |
1768 | 1638 |
1769 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { | 1639 void ChromeLauncherController::SetShelfAutoHideBehaviorFromPrefs() { |
1770 for (auto* window : ash::Shell::GetAllRootWindows()) { | 1640 for (auto* window : ash::Shell::GetAllRootWindows()) { |
1771 ash::Shelf* shelf = ash::Shelf::ForWindow(window); | 1641 ash::Shelf* shelf = ash::Shelf::ForWindow(window); |
1772 if (shelf) { | 1642 if (shelf) { |
1773 shelf->SetAutoHideBehavior( | 1643 shelf->SetAutoHideBehavior(ash::GetShelfAutoHideBehaviorPref( |
1774 GetShelfAutoHideBehaviorFromPrefs(profile_, window)); | 1644 profile_, GetDisplayIDForShelf(shelf))); |
1775 } | 1645 } |
1776 } | 1646 } |
1777 } | 1647 } |
1778 | 1648 |
1779 void ChromeLauncherController::SetShelfAlignmentFromPrefs() { | 1649 void ChromeLauncherController::SetShelfAlignmentFromPrefs() { |
1780 if (!ash::ShelfWidget::ShelfAlignmentAllowed()) | 1650 if (!ash::ShelfWidget::ShelfAlignmentAllowed()) |
1781 return; | 1651 return; |
1782 | 1652 |
1783 for (auto* window : ash::Shell::GetAllRootWindows()) { | 1653 for (auto* window : ash::Shell::GetAllRootWindows()) { |
1784 ash::Shelf* shelf = ash::Shelf::ForWindow(window); | 1654 ash::Shelf* shelf = ash::Shelf::ForWindow(window); |
1785 if (shelf) | 1655 if (shelf) { |
1786 shelf->SetAlignment(GetShelfAlignmentFromPrefs(profile_, window)); | 1656 shelf->SetAlignment( |
| 1657 ash::GetShelfAlignmentPref(profile_, GetDisplayIDForShelf(shelf))); |
| 1658 } |
1787 } | 1659 } |
1788 } | 1660 } |
1789 | 1661 |
1790 void ChromeLauncherController::SetShelfBehaviorsFromPrefs() { | 1662 void ChromeLauncherController::SetShelfBehaviorsFromPrefs() { |
1791 SetShelfAutoHideBehaviorFromPrefs(); | 1663 SetShelfAutoHideBehaviorFromPrefs(); |
1792 SetShelfAlignmentFromPrefs(); | 1664 SetShelfAlignmentFromPrefs(); |
1793 } | 1665 } |
1794 | 1666 |
1795 #if defined(OS_CHROMEOS) | 1667 #if defined(OS_CHROMEOS) |
1796 void ChromeLauncherController::SetVirtualKeyboardBehaviorFromPrefs() { | 1668 void ChromeLauncherController::SetVirtualKeyboardBehaviorFromPrefs() { |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2187 | 2059 |
2188 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp( | 2060 AppIconLoader* ChromeLauncherController::GetAppIconLoaderForApp( |
2189 const std::string& app_id) { | 2061 const std::string& app_id) { |
2190 for (const auto& app_icon_loader : app_icon_loaders_) { | 2062 for (const auto& app_icon_loader : app_icon_loaders_) { |
2191 if (app_icon_loader->CanLoadImageForApp(app_id)) | 2063 if (app_icon_loader->CanLoadImageForApp(app_id)) |
2192 return app_icon_loader.get(); | 2064 return app_icon_loader.get(); |
2193 } | 2065 } |
2194 | 2066 |
2195 return nullptr; | 2067 return nullptr; |
2196 } | 2068 } |
OLD | NEW |