| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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/chromeos/login/users/wallpaper/wallpaper_manager.h" | 5 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" |
| 6 | 6 |
| 7 #include <numeric> | 7 #include <numeric> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "ash/ash_constants.h" | 10 #include "ash/ash_constants.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
| 27 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
| 28 #include "base/sys_info.h" | 28 #include "base/sys_info.h" |
| 29 #include "base/threading/worker_pool.h" | 29 #include "base/threading/worker_pool.h" |
| 30 #include "base/time/time.h" | 30 #include "base/time/time.h" |
| 31 #include "base/values.h" | 31 #include "base/values.h" |
| 32 #include "chrome/browser/browser_process.h" | 32 #include "chrome/browser/browser_process.h" |
| 33 #include "chrome/browser/chrome_notification_types.h" | 33 #include "chrome/browser/chrome_notification_types.h" |
| 34 #include "chrome/browser/chromeos/customization_document.h" | 34 #include "chrome/browser/chromeos/customization_document.h" |
| 35 #include "chrome/browser/chromeos/login/startup_utils.h" | 35 #include "chrome/browser/chromeos/login/startup_utils.h" |
| 36 #include "chrome/browser/chromeos/login/users/user.h" | |
| 37 #include "chrome/browser/chromeos/login/users/user_manager.h" | 36 #include "chrome/browser/chromeos/login/users/user_manager.h" |
| 38 #include "chrome/browser/chromeos/login/wizard_controller.h" | 37 #include "chrome/browser/chromeos/login/wizard_controller.h" |
| 39 #include "chrome/browser/chromeos/settings/cros_settings.h" | 38 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 40 #include "chrome/common/chrome_paths.h" | 39 #include "chrome/common/chrome_paths.h" |
| 41 #include "chrome/common/chrome_switches.h" | 40 #include "chrome/common/chrome_switches.h" |
| 42 #include "chrome/common/pref_names.h" | 41 #include "chrome/common/pref_names.h" |
| 43 #include "chromeos/chromeos_switches.h" | 42 #include "chromeos/chromeos_switches.h" |
| 44 #include "chromeos/dbus/dbus_thread_manager.h" | 43 #include "chromeos/dbus/dbus_thread_manager.h" |
| 45 #include "chromeos/login/user_names.h" | 44 #include "chromeos/login/user_names.h" |
| 45 #include "components/user_manager/user.h" |
| 46 #include "components/user_manager/user_image/user_image.h" | 46 #include "components/user_manager/user_image/user_image.h" |
| 47 #include "components/user_manager/user_type.h" | 47 #include "components/user_manager/user_type.h" |
| 48 #include "content/public/browser/browser_thread.h" | 48 #include "content/public/browser/browser_thread.h" |
| 49 #include "content/public/browser/notification_service.h" | 49 #include "content/public/browser/notification_service.h" |
| 50 #include "third_party/skia/include/core/SkColor.h" | 50 #include "third_party/skia/include/core/SkColor.h" |
| 51 #include "ui/gfx/codec/jpeg_codec.h" | 51 #include "ui/gfx/codec/jpeg_codec.h" |
| 52 #include "ui/gfx/image/image_skia_operations.h" | 52 #include "ui/gfx/image/image_skia_operations.h" |
| 53 #include "ui/gfx/skia_util.h" | 53 #include "ui/gfx/skia_util.h" |
| 54 | 54 |
| 55 using content::BrowserThread; | 55 using content::BrowserThread; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 // Returns true on success. | 200 // Returns true on success. |
| 201 bool SaveWallpaperInternal(const base::FilePath& path, | 201 bool SaveWallpaperInternal(const base::FilePath& path, |
| 202 const char* data, | 202 const char* data, |
| 203 int size) { | 203 int size) { |
| 204 int written_bytes = base::WriteFile(path, data, size); | 204 int written_bytes = base::WriteFile(path, data, size); |
| 205 return written_bytes == size; | 205 return written_bytes == size; |
| 206 } | 206 } |
| 207 | 207 |
| 208 // Returns index of the first public session user found in |users| | 208 // Returns index of the first public session user found in |users| |
| 209 // or -1 otherwise. | 209 // or -1 otherwise. |
| 210 int FindPublicSession(const chromeos::UserList& users) { | 210 int FindPublicSession(const user_manager::UserList& users) { |
| 211 int index = -1; | 211 int index = -1; |
| 212 int i = 0; | 212 int i = 0; |
| 213 for (UserList::const_iterator it = users.begin(); | 213 for (user_manager::UserList::const_iterator it = users.begin(); |
| 214 it != users.end(); ++it, ++i) { | 214 it != users.end(); |
| 215 ++it, ++i) { |
| 215 if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) { | 216 if ((*it)->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT) { |
| 216 index = i; | 217 index = i; |
| 217 break; | 218 break; |
| 218 } | 219 } |
| 219 } | 220 } |
| 220 | 221 |
| 221 return index; | 222 return index; |
| 222 } | 223 } |
| 223 | 224 |
| 224 } // namespace | 225 } // namespace |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 return; | 548 return; |
| 548 } | 549 } |
| 549 SetUserWallpaperNow(UserManager::Get()->GetLoggedInUser()->email()); | 550 SetUserWallpaperNow(UserManager::Get()->GetLoggedInUser()->email()); |
| 550 } | 551 } |
| 551 | 552 |
| 552 void WallpaperManager::ClearDisposableWallpaperCache() { | 553 void WallpaperManager::ClearDisposableWallpaperCache() { |
| 553 // Cancel callback for previous cache requests. | 554 // Cancel callback for previous cache requests. |
| 554 weak_factory_.InvalidateWeakPtrs(); | 555 weak_factory_.InvalidateWeakPtrs(); |
| 555 // Keep the wallpaper of logged in users in cache at multi-profile mode. | 556 // Keep the wallpaper of logged in users in cache at multi-profile mode. |
| 556 std::set<std::string> logged_in_users_names; | 557 std::set<std::string> logged_in_users_names; |
| 557 const UserList& logged_users = UserManager::Get()->GetLoggedInUsers(); | 558 const user_manager::UserList& logged_users = |
| 558 for (UserList::const_iterator it = logged_users.begin(); | 559 UserManager::Get()->GetLoggedInUsers(); |
| 560 for (user_manager::UserList::const_iterator it = logged_users.begin(); |
| 559 it != logged_users.end(); | 561 it != logged_users.end(); |
| 560 ++it) { | 562 ++it) { |
| 561 logged_in_users_names.insert((*it)->email()); | 563 logged_in_users_names.insert((*it)->email()); |
| 562 } | 564 } |
| 563 | 565 |
| 564 CustomWallpaperMap logged_in_users_cache; | 566 CustomWallpaperMap logged_in_users_cache; |
| 565 for (CustomWallpaperMap::iterator it = wallpaper_cache_.begin(); | 567 for (CustomWallpaperMap::iterator it = wallpaper_cache_.begin(); |
| 566 it != wallpaper_cache_.end(); ++it) { | 568 it != wallpaper_cache_.end(); ++it) { |
| 567 if (logged_in_users_names.find(it->first) != | 569 if (logged_in_users_names.find(it->first) != |
| 568 logged_in_users_names.end()) { | 570 logged_in_users_names.end()) { |
| 569 logged_in_users_cache.insert(*it); | 571 logged_in_users_cache.insert(*it); |
| 570 } | 572 } |
| 571 } | 573 } |
| 572 wallpaper_cache_ = logged_in_users_cache; | 574 wallpaper_cache_ = logged_in_users_cache; |
| 573 } | 575 } |
| 574 | 576 |
| 575 bool WallpaperManager::GetLoggedInUserWallpaperInfo(WallpaperInfo* info) { | 577 bool WallpaperManager::GetLoggedInUserWallpaperInfo(WallpaperInfo* info) { |
| 576 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 577 | 579 |
| 578 if (UserManager::Get()->IsLoggedInAsStub()) { | 580 if (UserManager::Get()->IsLoggedInAsStub()) { |
| 579 info->file = current_user_wallpaper_info_.file = ""; | 581 info->file = current_user_wallpaper_info_.file = ""; |
| 580 info->layout = current_user_wallpaper_info_.layout = | 582 info->layout = current_user_wallpaper_info_.layout = |
| 581 ash::WALLPAPER_LAYOUT_CENTER_CROPPED; | 583 ash::WALLPAPER_LAYOUT_CENTER_CROPPED; |
| 582 info->type = current_user_wallpaper_info_.type = User::DEFAULT; | 584 info->type = current_user_wallpaper_info_.type = |
| 585 user_manager::User::DEFAULT; |
| 583 info->date = current_user_wallpaper_info_.date = | 586 info->date = current_user_wallpaper_info_.date = |
| 584 base::Time::Now().LocalMidnight(); | 587 base::Time::Now().LocalMidnight(); |
| 585 return true; | 588 return true; |
| 586 } | 589 } |
| 587 | 590 |
| 588 return GetUserWallpaperInfo(UserManager::Get()->GetLoggedInUser()->email(), | 591 return GetUserWallpaperInfo(UserManager::Get()->GetLoggedInUser()->email(), |
| 589 info); | 592 info); |
| 590 } | 593 } |
| 591 | 594 |
| 592 void WallpaperManager::InitializeWallpaper() { | 595 void WallpaperManager::InitializeWallpaper() { |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 770 return SaveWallpaperInternal( | 773 return SaveWallpaperInternal( |
| 771 path, reinterpret_cast<const char*>(data->front()), data->size()); | 774 path, reinterpret_cast<const char*>(data->front()), data->size()); |
| 772 } | 775 } |
| 773 return false; | 776 return false; |
| 774 } | 777 } |
| 775 | 778 |
| 776 bool WallpaperManager::IsPolicyControlled(const std::string& user_id) const { | 779 bool WallpaperManager::IsPolicyControlled(const std::string& user_id) const { |
| 777 chromeos::WallpaperInfo info; | 780 chromeos::WallpaperInfo info; |
| 778 if (!GetUserWallpaperInfo(user_id, &info)) | 781 if (!GetUserWallpaperInfo(user_id, &info)) |
| 779 return false; | 782 return false; |
| 780 return info.type == chromeos::User::POLICY; | 783 return info.type == user_manager::User::POLICY; |
| 781 } | 784 } |
| 782 | 785 |
| 783 void WallpaperManager::OnPolicySet(const std::string& policy, | 786 void WallpaperManager::OnPolicySet(const std::string& policy, |
| 784 const std::string& user_id) { | 787 const std::string& user_id) { |
| 785 WallpaperInfo info; | 788 WallpaperInfo info; |
| 786 GetUserWallpaperInfo(user_id, &info); | 789 GetUserWallpaperInfo(user_id, &info); |
| 787 info.type = User::POLICY; | 790 info.type = user_manager::User::POLICY; |
| 788 SetUserWallpaperInfo(user_id, info, true /* is_persistent */); | 791 SetUserWallpaperInfo(user_id, info, true /* is_persistent */); |
| 789 } | 792 } |
| 790 | 793 |
| 791 void WallpaperManager::OnPolicyCleared(const std::string& policy, | 794 void WallpaperManager::OnPolicyCleared(const std::string& policy, |
| 792 const std::string& user_id) { | 795 const std::string& user_id) { |
| 793 WallpaperInfo info; | 796 WallpaperInfo info; |
| 794 GetUserWallpaperInfo(user_id, &info); | 797 GetUserWallpaperInfo(user_id, &info); |
| 795 info.type = User::DEFAULT; | 798 info.type = user_manager::User::DEFAULT; |
| 796 SetUserWallpaperInfo(user_id, info, true /* is_persistent */); | 799 SetUserWallpaperInfo(user_id, info, true /* is_persistent */); |
| 797 SetDefaultWallpaperNow(user_id); | 800 SetDefaultWallpaperNow(user_id); |
| 798 } | 801 } |
| 799 | 802 |
| 800 void WallpaperManager::OnPolicyFetched(const std::string& policy, | 803 void WallpaperManager::OnPolicyFetched(const std::string& policy, |
| 801 const std::string& user_id, | 804 const std::string& user_id, |
| 802 scoped_ptr<std::string> data) { | 805 scoped_ptr<std::string> data) { |
| 803 if (!data) | 806 if (!data) |
| 804 return; | 807 return; |
| 805 | 808 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 828 const char* sub_dir, | 831 const char* sub_dir, |
| 829 const std::string& user_id_hash, | 832 const std::string& user_id_hash, |
| 830 const std::string& file) { | 833 const std::string& file) { |
| 831 base::FilePath custom_wallpaper_path = GetCustomWallpaperDir(sub_dir); | 834 base::FilePath custom_wallpaper_path = GetCustomWallpaperDir(sub_dir); |
| 832 return custom_wallpaper_path.Append(user_id_hash).Append(file); | 835 return custom_wallpaper_path.Append(user_id_hash).Append(file); |
| 833 } | 836 } |
| 834 | 837 |
| 835 void WallpaperManager::SetPolicyControlledWallpaper( | 838 void WallpaperManager::SetPolicyControlledWallpaper( |
| 836 const std::string& user_id, | 839 const std::string& user_id, |
| 837 const user_manager::UserImage& user_image) { | 840 const user_manager::UserImage& user_image) { |
| 838 const User *user = chromeos::UserManager::Get()->FindUser(user_id); | 841 const user_manager::User* user = |
| 842 chromeos::UserManager::Get()->FindUser(user_id); |
| 839 if (!user) { | 843 if (!user) { |
| 840 NOTREACHED() << "Unknown user."; | 844 NOTREACHED() << "Unknown user."; |
| 841 return; | 845 return; |
| 842 } | 846 } |
| 843 SetCustomWallpaper(user_id, | 847 SetCustomWallpaper(user_id, |
| 844 user->username_hash(), | 848 user->username_hash(), |
| 845 "policy-controlled.jpeg", | 849 "policy-controlled.jpeg", |
| 846 ash::WALLPAPER_LAYOUT_CENTER_CROPPED, | 850 ash::WALLPAPER_LAYOUT_CENTER_CROPPED, |
| 847 User::POLICY, | 851 user_manager::User::POLICY, |
| 848 user_image.image(), | 852 user_image.image(), |
| 849 true /* update wallpaper */); | 853 true /* update wallpaper */); |
| 850 } | 854 } |
| 851 | 855 |
| 852 void WallpaperManager::SetCustomWallpaper(const std::string& user_id, | 856 void WallpaperManager::SetCustomWallpaper( |
| 853 const std::string& user_id_hash, | 857 const std::string& user_id, |
| 854 const std::string& file, | 858 const std::string& user_id_hash, |
| 855 ash::WallpaperLayout layout, | 859 const std::string& file, |
| 856 User::WallpaperType type, | 860 ash::WallpaperLayout layout, |
| 857 const gfx::ImageSkia& image, | 861 user_manager::User::WallpaperType type, |
| 858 bool update_wallpaper) { | 862 const gfx::ImageSkia& image, |
| 863 bool update_wallpaper) { |
| 859 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 864 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 860 DCHECK(UserManager::Get()->IsUserLoggedIn()); | 865 DCHECK(UserManager::Get()->IsUserLoggedIn()); |
| 861 | 866 |
| 862 // There is no visible background in kiosk mode. | 867 // There is no visible background in kiosk mode. |
| 863 if (UserManager::Get()->IsLoggedInAsKioskApp()) | 868 if (UserManager::Get()->IsLoggedInAsKioskApp()) |
| 864 return; | 869 return; |
| 865 | 870 |
| 866 // Don't allow custom wallpapers while policy is in effect. | 871 // Don't allow custom wallpapers while policy is in effect. |
| 867 if (type != User::POLICY && IsPolicyControlled(user_id)) | 872 if (type != user_manager::User::POLICY && IsPolicyControlled(user_id)) |
| 868 return; | 873 return; |
| 869 | 874 |
| 870 base::FilePath wallpaper_path = | 875 base::FilePath wallpaper_path = |
| 871 GetCustomWallpaperPath(kOriginalWallpaperSubDir, user_id_hash, file); | 876 GetCustomWallpaperPath(kOriginalWallpaperSubDir, user_id_hash, file); |
| 872 | 877 |
| 873 // If decoded wallpaper is empty, we have probably failed to decode the file. | 878 // If decoded wallpaper is empty, we have probably failed to decode the file. |
| 874 // Use default wallpaper in this case. | 879 // Use default wallpaper in this case. |
| 875 if (image.isNull()) { | 880 if (image.isNull()) { |
| 876 SetDefaultWallpaperDelayed(user_id); | 881 SetDefaultWallpaperDelayed(user_id); |
| 877 return; | 882 return; |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 // 1x1 wallpaper is actually solid color, so it should be stretched. | 981 // 1x1 wallpaper is actually solid color, so it should be stretched. |
| 977 if (default_wallpaper_image_->image().width() == 1 && | 982 if (default_wallpaper_image_->image().width() == 1 && |
| 978 default_wallpaper_image_->image().height() == 1) | 983 default_wallpaper_image_->image().height() == 1) |
| 979 layout = ash::WALLPAPER_LAYOUT_STRETCH; | 984 layout = ash::WALLPAPER_LAYOUT_STRETCH; |
| 980 | 985 |
| 981 ash::Shell::GetInstance()->desktop_background_controller()->SetWallpaperImage( | 986 ash::Shell::GetInstance()->desktop_background_controller()->SetWallpaperImage( |
| 982 default_wallpaper_image_->image(), layout); | 987 default_wallpaper_image_->image(), layout); |
| 983 } | 988 } |
| 984 | 989 |
| 985 // static | 990 // static |
| 986 void WallpaperManager::RecordUma(User::WallpaperType type, int index) { | 991 void WallpaperManager::RecordUma(user_manager::User::WallpaperType type, |
| 992 int index) { |
| 987 UMA_HISTOGRAM_ENUMERATION( | 993 UMA_HISTOGRAM_ENUMERATION( |
| 988 "Ash.Wallpaper.Type", type, User::WALLPAPER_TYPE_COUNT); | 994 "Ash.Wallpaper.Type", type, user_manager::User::WALLPAPER_TYPE_COUNT); |
| 989 } | 995 } |
| 990 | 996 |
| 991 // static | 997 // static |
| 992 void WallpaperManager::SaveCustomWallpaper(const std::string& user_id_hash, | 998 void WallpaperManager::SaveCustomWallpaper(const std::string& user_id_hash, |
| 993 const base::FilePath& original_path, | 999 const base::FilePath& original_path, |
| 994 ash::WallpaperLayout layout, | 1000 ash::WallpaperLayout layout, |
| 995 scoped_ptr<gfx::ImageSkia> image) { | 1001 scoped_ptr<gfx::ImageSkia> image) { |
| 996 EnsureCustomWallpaperDirectories(user_id_hash); | 1002 EnsureCustomWallpaperDirectories(user_id_hash); |
| 997 std::string file_name = original_path.BaseName().value(); | 1003 std::string file_name = original_path.BaseName().value(); |
| 998 base::FilePath small_wallpaper_path = | 1004 base::FilePath small_wallpaper_path = |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 update_wallpaper, | 1102 update_wallpaper, |
| 1097 valid_path, | 1103 valid_path, |
| 1098 base::Passed(on_finish.Pass()))); | 1104 base::Passed(on_finish.Pass()))); |
| 1099 } | 1105 } |
| 1100 } | 1106 } |
| 1101 | 1107 |
| 1102 void WallpaperManager::InitInitialUserWallpaper(const std::string& user_id, | 1108 void WallpaperManager::InitInitialUserWallpaper(const std::string& user_id, |
| 1103 bool is_persistent) { | 1109 bool is_persistent) { |
| 1104 current_user_wallpaper_info_.file = ""; | 1110 current_user_wallpaper_info_.file = ""; |
| 1105 current_user_wallpaper_info_.layout = ash::WALLPAPER_LAYOUT_CENTER_CROPPED; | 1111 current_user_wallpaper_info_.layout = ash::WALLPAPER_LAYOUT_CENTER_CROPPED; |
| 1106 current_user_wallpaper_info_.type = User::DEFAULT; | 1112 current_user_wallpaper_info_.type = user_manager::User::DEFAULT; |
| 1107 current_user_wallpaper_info_.date = base::Time::Now().LocalMidnight(); | 1113 current_user_wallpaper_info_.date = base::Time::Now().LocalMidnight(); |
| 1108 | 1114 |
| 1109 WallpaperInfo info = current_user_wallpaper_info_; | 1115 WallpaperInfo info = current_user_wallpaper_info_; |
| 1110 SetUserWallpaperInfo(user_id, info, is_persistent); | 1116 SetUserWallpaperInfo(user_id, info, is_persistent); |
| 1111 } | 1117 } |
| 1112 | 1118 |
| 1113 void WallpaperManager::SetUserWallpaperInfo(const std::string& user_id, | 1119 void WallpaperManager::SetUserWallpaperInfo(const std::string& user_id, |
| 1114 const WallpaperInfo& info, | 1120 const WallpaperInfo& info, |
| 1115 bool is_persistent) { | 1121 bool is_persistent) { |
| 1116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1142 void WallpaperManager::ScheduleSetUserWallpaper(const std::string& user_id, | 1148 void WallpaperManager::ScheduleSetUserWallpaper(const std::string& user_id, |
| 1143 bool delayed) { | 1149 bool delayed) { |
| 1144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1145 // Some unit tests come here without a UserManager or without a pref system. | 1151 // Some unit tests come here without a UserManager or without a pref system. |
| 1146 if (!UserManager::IsInitialized() || !g_browser_process->local_state()) | 1152 if (!UserManager::IsInitialized() || !g_browser_process->local_state()) |
| 1147 return; | 1153 return; |
| 1148 // There is no visible background in kiosk mode. | 1154 // There is no visible background in kiosk mode. |
| 1149 if (UserManager::Get()->IsLoggedInAsKioskApp()) | 1155 if (UserManager::Get()->IsLoggedInAsKioskApp()) |
| 1150 return; | 1156 return; |
| 1151 // Guest user, regular user in ephemeral mode, or kiosk app. | 1157 // Guest user, regular user in ephemeral mode, or kiosk app. |
| 1152 const User* user = UserManager::Get()->FindUser(user_id); | 1158 const user_manager::User* user = UserManager::Get()->FindUser(user_id); |
| 1153 if (UserManager::Get()->IsUserNonCryptohomeDataEphemeral(user_id) || | 1159 if (UserManager::Get()->IsUserNonCryptohomeDataEphemeral(user_id) || |
| 1154 (user != NULL && user->GetType() == user_manager::USER_TYPE_KIOSK_APP)) { | 1160 (user != NULL && user->GetType() == user_manager::USER_TYPE_KIOSK_APP)) { |
| 1155 InitInitialUserWallpaper(user_id, false); | 1161 InitInitialUserWallpaper(user_id, false); |
| 1156 GetPendingWallpaper(user_id, delayed)->ResetSetDefaultWallpaper(); | 1162 GetPendingWallpaper(user_id, delayed)->ResetSetDefaultWallpaper(); |
| 1157 return; | 1163 return; |
| 1158 } | 1164 } |
| 1159 | 1165 |
| 1160 if (!UserManager::Get()->IsKnownUser(user_id)) | 1166 if (!UserManager::Get()->IsKnownUser(user_id)) |
| 1161 return; | 1167 return; |
| 1162 | 1168 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1175 GetPendingWallpaper(user_id, delayed) | 1181 GetPendingWallpaper(user_id, delayed) |
| 1176 ->ResetSetWallpaperImage(user_wallpaper, info); | 1182 ->ResetSetWallpaperImage(user_wallpaper, info); |
| 1177 } else { | 1183 } else { |
| 1178 if (info.file.empty()) { | 1184 if (info.file.empty()) { |
| 1179 // Uses default built-in wallpaper when file is empty. Eventually, we | 1185 // Uses default built-in wallpaper when file is empty. Eventually, we |
| 1180 // will only ship one built-in wallpaper in ChromeOS image. | 1186 // will only ship one built-in wallpaper in ChromeOS image. |
| 1181 GetPendingWallpaper(user_id, delayed)->ResetSetDefaultWallpaper(); | 1187 GetPendingWallpaper(user_id, delayed)->ResetSetDefaultWallpaper(); |
| 1182 return; | 1188 return; |
| 1183 } | 1189 } |
| 1184 | 1190 |
| 1185 if (info.type == User::CUSTOMIZED || info.type == User::POLICY) { | 1191 if (info.type == user_manager::User::CUSTOMIZED || |
| 1192 info.type == user_manager::User::POLICY) { |
| 1186 const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); | 1193 const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); |
| 1187 // Wallpaper is not resized when layout is ash::WALLPAPER_LAYOUT_CENTER. | 1194 // Wallpaper is not resized when layout is ash::WALLPAPER_LAYOUT_CENTER. |
| 1188 // Original wallpaper should be used in this case. | 1195 // Original wallpaper should be used in this case. |
| 1189 // TODO(bshe): Generates cropped custom wallpaper for CENTER layout. | 1196 // TODO(bshe): Generates cropped custom wallpaper for CENTER layout. |
| 1190 if (info.layout == ash::WALLPAPER_LAYOUT_CENTER) | 1197 if (info.layout == ash::WALLPAPER_LAYOUT_CENTER) |
| 1191 sub_dir = kOriginalWallpaperSubDir; | 1198 sub_dir = kOriginalWallpaperSubDir; |
| 1192 base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); | 1199 base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); |
| 1193 wallpaper_path = wallpaper_path.Append(info.file); | 1200 wallpaper_path = wallpaper_path.Append(info.file); |
| 1194 if (current_wallpaper_path_ == wallpaper_path) | 1201 if (current_wallpaper_path_ == wallpaper_path) |
| 1195 return; | 1202 return; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1262 CustomWallpaperMap::const_iterator it = wallpaper_cache_.find(user_id); | 1269 CustomWallpaperMap::const_iterator it = wallpaper_cache_.find(user_id); |
| 1263 if (it != wallpaper_cache_.end()) { | 1270 if (it != wallpaper_cache_.end()) { |
| 1264 *image = (*it).second; | 1271 *image = (*it).second; |
| 1265 return true; | 1272 return true; |
| 1266 } | 1273 } |
| 1267 return false; | 1274 return false; |
| 1268 } | 1275 } |
| 1269 | 1276 |
| 1270 void WallpaperManager::CacheUsersWallpapers() { | 1277 void WallpaperManager::CacheUsersWallpapers() { |
| 1271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1272 UserList users = UserManager::Get()->GetUsers(); | 1279 user_manager::UserList users = UserManager::Get()->GetUsers(); |
| 1273 | 1280 |
| 1274 if (!users.empty()) { | 1281 if (!users.empty()) { |
| 1275 UserList::const_iterator it = users.begin(); | 1282 user_manager::UserList::const_iterator it = users.begin(); |
| 1276 // Skip the wallpaper of first user in the list. It should have been cached. | 1283 // Skip the wallpaper of first user in the list. It should have been cached. |
| 1277 it++; | 1284 it++; |
| 1278 for (int cached = 0; | 1285 for (int cached = 0; |
| 1279 it != users.end() && cached < kMaxWallpapersToCache; | 1286 it != users.end() && cached < kMaxWallpapersToCache; |
| 1280 ++it, ++cached) { | 1287 ++it, ++cached) { |
| 1281 std::string user_id = (*it)->email(); | 1288 std::string user_id = (*it)->email(); |
| 1282 CacheUserWallpaper(user_id); | 1289 CacheUserWallpaper(user_id); |
| 1283 } | 1290 } |
| 1284 } | 1291 } |
| 1285 } | 1292 } |
| 1286 | 1293 |
| 1287 void WallpaperManager::CacheUserWallpaper(const std::string& user_id) { | 1294 void WallpaperManager::CacheUserWallpaper(const std::string& user_id) { |
| 1288 if (wallpaper_cache_.find(user_id) != wallpaper_cache_.end()) | 1295 if (wallpaper_cache_.find(user_id) != wallpaper_cache_.end()) |
| 1289 return; | 1296 return; |
| 1290 WallpaperInfo info; | 1297 WallpaperInfo info; |
| 1291 if (GetUserWallpaperInfo(user_id, &info)) { | 1298 if (GetUserWallpaperInfo(user_id, &info)) { |
| 1292 if (info.file.empty()) | 1299 if (info.file.empty()) |
| 1293 return; | 1300 return; |
| 1294 | 1301 |
| 1295 base::FilePath wallpaper_dir; | 1302 base::FilePath wallpaper_dir; |
| 1296 base::FilePath wallpaper_path; | 1303 base::FilePath wallpaper_path; |
| 1297 if (info.type == User::CUSTOMIZED || info.type == User::POLICY) { | 1304 if (info.type == user_manager::User::CUSTOMIZED || |
| 1305 info.type == user_manager::User::POLICY) { |
| 1298 const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); | 1306 const char* sub_dir = GetCustomWallpaperSubdirForCurrentResolution(); |
| 1299 base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); | 1307 base::FilePath wallpaper_path = GetCustomWallpaperDir(sub_dir); |
| 1300 wallpaper_path = wallpaper_path.Append(info.file); | 1308 wallpaper_path = wallpaper_path.Append(info.file); |
| 1301 task_runner_->PostTask( | 1309 task_runner_->PostTask( |
| 1302 FROM_HERE, | 1310 FROM_HERE, |
| 1303 base::Bind(&WallpaperManager::GetCustomWallpaperInternal, | 1311 base::Bind(&WallpaperManager::GetCustomWallpaperInternal, |
| 1304 user_id, | 1312 user_id, |
| 1305 info, | 1313 info, |
| 1306 wallpaper_path, | 1314 wallpaper_path, |
| 1307 false /* do not update wallpaper */, | 1315 false /* do not update wallpaper */, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1376 if (UserManager::Get()->IsUserLoggedIn()) | 1384 if (UserManager::Get()->IsUserLoggedIn()) |
| 1377 return; | 1385 return; |
| 1378 | 1386 |
| 1379 bool disable_boot_animation = | 1387 bool disable_boot_animation = |
| 1380 GetCommandLine()->HasSwitch(switches::kDisableBootAnimation); | 1388 GetCommandLine()->HasSwitch(switches::kDisableBootAnimation); |
| 1381 bool show_users = true; | 1389 bool show_users = true; |
| 1382 bool result = CrosSettings::Get()->GetBoolean( | 1390 bool result = CrosSettings::Get()->GetBoolean( |
| 1383 kAccountsPrefShowUserNamesOnSignIn, &show_users); | 1391 kAccountsPrefShowUserNamesOnSignIn, &show_users); |
| 1384 DCHECK(result) << "Unable to fetch setting " | 1392 DCHECK(result) << "Unable to fetch setting " |
| 1385 << kAccountsPrefShowUserNamesOnSignIn; | 1393 << kAccountsPrefShowUserNamesOnSignIn; |
| 1386 const chromeos::UserList& users = UserManager::Get()->GetUsers(); | 1394 const user_manager::UserList& users = UserManager::Get()->GetUsers(); |
| 1387 int public_session_user_index = FindPublicSession(users); | 1395 int public_session_user_index = FindPublicSession(users); |
| 1388 if ((!show_users && public_session_user_index == -1) || users.empty()) { | 1396 if ((!show_users && public_session_user_index == -1) || users.empty()) { |
| 1389 // Boot into sign in form, preload default wallpaper. | 1397 // Boot into sign in form, preload default wallpaper. |
| 1390 SetDefaultWallpaperDelayed(chromeos::login::kSignInUser); | 1398 SetDefaultWallpaperDelayed(chromeos::login::kSignInUser); |
| 1391 return; | 1399 return; |
| 1392 } | 1400 } |
| 1393 | 1401 |
| 1394 if (!disable_boot_animation) { | 1402 if (!disable_boot_animation) { |
| 1395 int index = public_session_user_index != -1 ? public_session_user_index : 0; | 1403 int index = public_session_user_index != -1 ? public_session_user_index : 0; |
| 1396 // Normal boot, load user wallpaper. | 1404 // Normal boot, load user wallpaper. |
| 1397 // If normal boot animation is disabled wallpaper would be set | 1405 // If normal boot animation is disabled wallpaper would be set |
| 1398 // asynchronously once user pods are loaded. | 1406 // asynchronously once user pods are loaded. |
| 1399 SetUserWallpaperDelayed(users[index]->email()); | 1407 SetUserWallpaperDelayed(users[index]->email()); |
| 1400 } | 1408 } |
| 1401 } | 1409 } |
| 1402 | 1410 |
| 1403 void WallpaperManager::LoadWallpaper(const std::string& user_id, | 1411 void WallpaperManager::LoadWallpaper(const std::string& user_id, |
| 1404 const WallpaperInfo& info, | 1412 const WallpaperInfo& info, |
| 1405 bool update_wallpaper, | 1413 bool update_wallpaper, |
| 1406 MovableOnDestroyCallbackHolder on_finish) { | 1414 MovableOnDestroyCallbackHolder on_finish) { |
| 1407 base::FilePath wallpaper_dir; | 1415 base::FilePath wallpaper_dir; |
| 1408 base::FilePath wallpaper_path; | 1416 base::FilePath wallpaper_path; |
| 1409 | 1417 |
| 1410 // Do a sanity check that file path information is not empty. | 1418 // Do a sanity check that file path information is not empty. |
| 1411 if (info.type == User::ONLINE || info.type == User::DEFAULT) { | 1419 if (info.type == user_manager::User::ONLINE || |
| 1420 info.type == user_manager::User::DEFAULT) { |
| 1412 if (info.file.empty()) { | 1421 if (info.file.empty()) { |
| 1413 if (base::SysInfo::IsRunningOnChromeOS()) { | 1422 if (base::SysInfo::IsRunningOnChromeOS()) { |
| 1414 NOTREACHED() << "User wallpaper info appears to be broken: " << user_id; | 1423 NOTREACHED() << "User wallpaper info appears to be broken: " << user_id; |
| 1415 } else { | 1424 } else { |
| 1416 // Filename might be empty on debug configurations when stub users | 1425 // Filename might be empty on debug configurations when stub users |
| 1417 // were created directly in Local State (for testing). Ignore such | 1426 // were created directly in Local State (for testing). Ignore such |
| 1418 // errors i.e. allowsuch type of debug configurations on the desktop. | 1427 // errors i.e. allowsuch type of debug configurations on the desktop. |
| 1419 LOG(WARNING) << "User wallpaper info is empty: " << user_id; | 1428 LOG(WARNING) << "User wallpaper info is empty: " << user_id; |
| 1420 | 1429 |
| 1421 // |on_finish| callback will get called on destruction. | 1430 // |on_finish| callback will get called on destruction. |
| 1422 return; | 1431 return; |
| 1423 } | 1432 } |
| 1424 } | 1433 } |
| 1425 } | 1434 } |
| 1426 | 1435 |
| 1427 if (info.type == User::ONLINE) { | 1436 if (info.type == user_manager::User::ONLINE) { |
| 1428 std::string file_name = GURL(info.file).ExtractFileName(); | 1437 std::string file_name = GURL(info.file).ExtractFileName(); |
| 1429 WallpaperResolution resolution = GetAppropriateResolution(); | 1438 WallpaperResolution resolution = GetAppropriateResolution(); |
| 1430 // Only solid color wallpapers have stretch layout and they have only one | 1439 // Only solid color wallpapers have stretch layout and they have only one |
| 1431 // resolution. | 1440 // resolution. |
| 1432 if (info.layout != ash::WALLPAPER_LAYOUT_STRETCH && | 1441 if (info.layout != ash::WALLPAPER_LAYOUT_STRETCH && |
| 1433 resolution == WALLPAPER_RESOLUTION_SMALL) { | 1442 resolution == WALLPAPER_RESOLUTION_SMALL) { |
| 1434 file_name = base::FilePath(file_name).InsertBeforeExtension( | 1443 file_name = base::FilePath(file_name).InsertBeforeExtension( |
| 1435 kSmallWallpaperSuffix).value(); | 1444 kSmallWallpaperSuffix).value(); |
| 1436 } | 1445 } |
| 1437 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir)); | 1446 CHECK(PathService::Get(chrome::DIR_CHROMEOS_WALLPAPERS, &wallpaper_dir)); |
| 1438 wallpaper_path = wallpaper_dir.Append(file_name); | 1447 wallpaper_path = wallpaper_dir.Append(file_name); |
| 1439 if (current_wallpaper_path_ == wallpaper_path) | 1448 if (current_wallpaper_path_ == wallpaper_path) |
| 1440 return; | 1449 return; |
| 1441 | 1450 |
| 1442 if (update_wallpaper) | 1451 if (update_wallpaper) |
| 1443 current_wallpaper_path_ = wallpaper_path; | 1452 current_wallpaper_path_ = wallpaper_path; |
| 1444 | 1453 |
| 1445 loaded_wallpapers_++; | 1454 loaded_wallpapers_++; |
| 1446 StartLoad( | 1455 StartLoad( |
| 1447 user_id, info, update_wallpaper, wallpaper_path, on_finish.Pass()); | 1456 user_id, info, update_wallpaper, wallpaper_path, on_finish.Pass()); |
| 1448 } else if (info.type == User::DEFAULT) { | 1457 } else if (info.type == user_manager::User::DEFAULT) { |
| 1449 // Default wallpapers are migrated from M21 user profiles. A code refactor | 1458 // Default wallpapers are migrated from M21 user profiles. A code refactor |
| 1450 // overlooked that case and caused these wallpapers not being loaded at all. | 1459 // overlooked that case and caused these wallpapers not being loaded at all. |
| 1451 // On some slow devices, it caused login webui not visible after upgrade to | 1460 // On some slow devices, it caused login webui not visible after upgrade to |
| 1452 // M26 from M21. See crosbug.com/38429 for details. | 1461 // M26 from M21. See crosbug.com/38429 for details. |
| 1453 base::FilePath user_data_dir; | 1462 base::FilePath user_data_dir; |
| 1454 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); | 1463 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir); |
| 1455 wallpaper_path = user_data_dir.Append(info.file); | 1464 wallpaper_path = user_data_dir.Append(info.file); |
| 1456 StartLoad( | 1465 StartLoad( |
| 1457 user_id, info, update_wallpaper, wallpaper_path, on_finish.Pass()); | 1466 user_id, info, update_wallpaper, wallpaper_path, on_finish.Pass()); |
| 1458 } else { | 1467 } else { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 return false; | 1504 return false; |
| 1496 std::string date_string; | 1505 std::string date_string; |
| 1497 if (!info_dict->GetString(kNewWallpaperDateNodeName, &date_string)) | 1506 if (!info_dict->GetString(kNewWallpaperDateNodeName, &date_string)) |
| 1498 return false; | 1507 return false; |
| 1499 int64 date_val; | 1508 int64 date_val; |
| 1500 if (!base::StringToInt64(date_string, &date_val)) | 1509 if (!base::StringToInt64(date_string, &date_val)) |
| 1501 return false; | 1510 return false; |
| 1502 | 1511 |
| 1503 info->file = file; | 1512 info->file = file; |
| 1504 info->layout = static_cast<ash::WallpaperLayout>(layout); | 1513 info->layout = static_cast<ash::WallpaperLayout>(layout); |
| 1505 info->type = static_cast<User::WallpaperType>(type); | 1514 info->type = static_cast<user_manager::User::WallpaperType>(type); |
| 1506 info->date = base::Time::FromInternalValue(date_val); | 1515 info->date = base::Time::FromInternalValue(date_val); |
| 1507 return true; | 1516 return true; |
| 1508 } | 1517 } |
| 1509 | 1518 |
| 1510 void WallpaperManager::MoveCustomWallpapersSuccess( | 1519 void WallpaperManager::MoveCustomWallpapersSuccess( |
| 1511 const std::string& user_id, | 1520 const std::string& user_id, |
| 1512 const std::string& user_id_hash) { | 1521 const std::string& user_id_hash) { |
| 1513 WallpaperInfo info; | 1522 WallpaperInfo info; |
| 1514 GetUserWallpaperInfo(user_id, &info); | 1523 GetUserWallpaperInfo(user_id, &info); |
| 1515 if (info.type == User::CUSTOMIZED) { | 1524 if (info.type == user_manager::User::CUSTOMIZED) { |
| 1516 // New file field should include user id hash in addition to file name. | 1525 // New file field should include user id hash in addition to file name. |
| 1517 // This is needed because at login screen, user id hash is not available. | 1526 // This is needed because at login screen, user id hash is not available. |
| 1518 std::string relative_path = | 1527 std::string relative_path = |
| 1519 base::FilePath(user_id_hash).Append(info.file).value(); | 1528 base::FilePath(user_id_hash).Append(info.file).value(); |
| 1520 info.file = relative_path; | 1529 info.file = relative_path; |
| 1521 bool is_persistent = | 1530 bool is_persistent = |
| 1522 !UserManager::Get()->IsUserNonCryptohomeDataEphemeral(user_id); | 1531 !UserManager::Get()->IsUserNonCryptohomeDataEphemeral(user_id); |
| 1523 SetUserWallpaperInfo(user_id, info, is_persistent); | 1532 SetUserWallpaperInfo(user_id, info, is_persistent); |
| 1524 } | 1533 } |
| 1525 } | 1534 } |
| 1526 | 1535 |
| 1527 void WallpaperManager::MoveLoggedInUserCustomWallpaper() { | 1536 void WallpaperManager::MoveLoggedInUserCustomWallpaper() { |
| 1528 const User* logged_in_user = UserManager::Get()->GetLoggedInUser(); | 1537 const user_manager::User* logged_in_user = |
| 1538 UserManager::Get()->GetLoggedInUser(); |
| 1529 task_runner_->PostTask( | 1539 task_runner_->PostTask( |
| 1530 FROM_HERE, | 1540 FROM_HERE, |
| 1531 base::Bind(&WallpaperManager::MoveCustomWallpapersOnWorker, | 1541 base::Bind(&WallpaperManager::MoveCustomWallpapersOnWorker, |
| 1532 logged_in_user->email(), | 1542 logged_in_user->email(), |
| 1533 logged_in_user->username_hash(), | 1543 logged_in_user->username_hash(), |
| 1534 weak_factory_.GetWeakPtr())); | 1544 weak_factory_.GetWeakPtr())); |
| 1535 } | 1545 } |
| 1536 | 1546 |
| 1537 void WallpaperManager::OnWallpaperDecoded( | 1547 void WallpaperManager::OnWallpaperDecoded( |
| 1538 const std::string& user_id, | 1548 const std::string& user_id, |
| 1539 ash::WallpaperLayout layout, | 1549 ash::WallpaperLayout layout, |
| 1540 bool update_wallpaper, | 1550 bool update_wallpaper, |
| 1541 MovableOnDestroyCallbackHolder on_finish, | 1551 MovableOnDestroyCallbackHolder on_finish, |
| 1542 const user_manager::UserImage& user_image) { | 1552 const user_manager::UserImage& user_image) { |
| 1543 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1553 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1544 TRACE_EVENT_ASYNC_END0("ui", "LoadAndDecodeWallpaper", this); | 1554 TRACE_EVENT_ASYNC_END0("ui", "LoadAndDecodeWallpaper", this); |
| 1545 | 1555 |
| 1546 // If decoded wallpaper is empty, we have probably failed to decode the file. | 1556 // If decoded wallpaper is empty, we have probably failed to decode the file. |
| 1547 // Use default wallpaper in this case. | 1557 // Use default wallpaper in this case. |
| 1548 if (user_image.image().isNull()) { | 1558 if (user_image.image().isNull()) { |
| 1549 // Updates user pref to default wallpaper. | 1559 // Updates user pref to default wallpaper. |
| 1550 WallpaperInfo info = { | 1560 WallpaperInfo info = {"", ash::WALLPAPER_LAYOUT_CENTER_CROPPED, |
| 1551 "", | 1561 user_manager::User::DEFAULT, |
| 1552 ash::WALLPAPER_LAYOUT_CENTER_CROPPED, | 1562 base::Time::Now().LocalMidnight()}; |
| 1553 User::DEFAULT, | |
| 1554 base::Time::Now().LocalMidnight() | |
| 1555 }; | |
| 1556 SetUserWallpaperInfo(user_id, info, true); | 1563 SetUserWallpaperInfo(user_id, info, true); |
| 1557 | 1564 |
| 1558 if (update_wallpaper) | 1565 if (update_wallpaper) |
| 1559 DoSetDefaultWallpaper(user_id, on_finish.Pass()); | 1566 DoSetDefaultWallpaper(user_id, on_finish.Pass()); |
| 1560 return; | 1567 return; |
| 1561 } | 1568 } |
| 1562 | 1569 |
| 1563 wallpaper_cache_[user_id] = user_image.image(); | 1570 wallpaper_cache_[user_id] = user_image.image(); |
| 1564 | 1571 |
| 1565 if (update_wallpaper) { | 1572 if (update_wallpaper) { |
| (...skipping 340 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1906 void WallpaperManager::CreateSolidDefaultWallpaper() { | 1913 void WallpaperManager::CreateSolidDefaultWallpaper() { |
| 1907 loaded_wallpapers_++; | 1914 loaded_wallpapers_++; |
| 1908 SkBitmap bitmap; | 1915 SkBitmap bitmap; |
| 1909 bitmap.allocN32Pixels(1, 1); | 1916 bitmap.allocN32Pixels(1, 1); |
| 1910 bitmap.eraseColor(kDefaultWallpaperColor); | 1917 bitmap.eraseColor(kDefaultWallpaperColor); |
| 1911 const gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); | 1918 const gfx::ImageSkia image = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); |
| 1912 default_wallpaper_image_.reset(new user_manager::UserImage(image)); | 1919 default_wallpaper_image_.reset(new user_manager::UserImage(image)); |
| 1913 } | 1920 } |
| 1914 | 1921 |
| 1915 } // namespace chromeos | 1922 } // namespace chromeos |
| OLD | NEW |