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 3 // found in the LICENSE file. 4 5 #include "chrome/browser/profiles/profile_loader.h" 6 7 #include <map> 8 9 #include "base/bind.h" 10 #include "base/files/file_path.h" 11 #include "base/memory/weak_ptr.h" 12 #include "chrome/browser/lifetime/application_lifetime.h" 13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile_loader.h" 15 #include "chrome/test/base/testing_profile.h" 16 #include "testing/gmock/include/gmock/gmock.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace { 20 21 using ::testing::_; 22 using ::testing::Invoke; 23 using ::testing::Return; 24 using ::testing::StrictMock; 25 using ::testing::WithArgs; 26 27 class TestProfileLoader : public ProfileLoader { 28 public: 29 TestProfileLoader() : ProfileLoader(NULL) {} 30 virtual ~TestProfileLoader() {} 31 32 MOCK_METHOD1(GetProfileByPath, Profile*(const base::FilePath&)); 33 MOCK_METHOD5(CreateProfileAsync, void(const base::FilePath&, 34 const ProfileManager::CreateCallback&, 35 const string16&, 36 const string16&, 37 const std::string&)); 38 39 void SetCreateCallback(const base::FilePath& path, 40 const ProfileManager::CreateCallback& callback) { 41 callbacks_[path] = callback; 42 } 43 44 void RunCreateCallback(const base::FilePath& path, 45 Profile* profile, 46 Profile::CreateStatus status) { 47 callbacks_[path].Run(profile, status); 48 } 49 50 private: 51 std::map<base::FilePath, ProfileManager::CreateCallback> callbacks_; 52 53 DISALLOW_COPY_AND_ASSIGN(TestProfileLoader); 54 }; 55 56 class MockCallback : public base::RefCountedThreadSafe<MockCallback> { 57 public: 58 MockCallback(); 59 MOCK_METHOD1(Run, void(Profile*)); 60 61 protected: 62 friend class base::RefCountedThreadSafe<MockCallback>; 63 virtual ~MockCallback(); 64 65 private: 66 DISALLOW_COPY_AND_ASSIGN(MockCallback); 67 }; 68 69 MockCallback::MockCallback() {} 70 MockCallback::~MockCallback() {} 71 72 TEST(ProfileLoaderTest, LoadProfileInvalidatingOtherLoads) { 73 TestingProfile profile; 74 base::FilePath fake_profile_path_1 = 75 base::FilePath::FromUTF8Unsafe("fake/profile 1"); 76 base::FilePath fake_profile_path_2 = 77 base::FilePath::FromUTF8Unsafe("fake/profile 2"); 78 79 TestProfileLoader loader; 80 EXPECT_FALSE(loader.IsAnyProfileLoading()); 81 82 // path_1 never loads. 83 EXPECT_CALL(loader, GetProfileByPath(fake_profile_path_1)) 84 .WillRepeatedly(Return(static_cast<Profile*>(NULL))); 85 EXPECT_CALL(loader, 86 CreateProfileAsync(fake_profile_path_1, _, _, _, std::string())) 87 .WillRepeatedly(WithArgs<0, 1>( 88 Invoke(&loader, &TestProfileLoader::SetCreateCallback))); 89 90 // path_2 loads after the first request. 91 EXPECT_CALL(loader, GetProfileByPath(fake_profile_path_2)) 92 .WillOnce(Return(static_cast<Profile*>(NULL))) 93 .WillRepeatedly(Return(&profile)); 94 EXPECT_CALL(loader, 95 CreateProfileAsync(fake_profile_path_2, _, _, _, std::string())) 96 .WillRepeatedly(WithArgs<0, 1>( 97 Invoke(&loader, &TestProfileLoader::SetCreateCallback))); 98 99 // Try to load both paths twice. 100 // path_1_load is never called because it is first invalidated by the load 101 // request for (path_2), and then invalidated manually. 102 // path_2_load is called both times. 103 StrictMock<MockCallback>* path_1_load = new StrictMock<MockCallback>(); 104 StrictMock<MockCallback>* path_2_load = new StrictMock<MockCallback>(); 105 EXPECT_CALL(*path_2_load, Run(&profile)) 106 .Times(2); 107 108 // Try to load path_1. 109 loader.LoadProfileInvalidatingOtherLoads( 110 fake_profile_path_1, base::Bind(&MockCallback::Run, path_1_load)); 111 EXPECT_TRUE(loader.IsAnyProfileLoading()); 112 113 // Try to load path_2, this invalidates the previous request. 114 loader.LoadProfileInvalidatingOtherLoads( 115 fake_profile_path_2, base::Bind(&MockCallback::Run, path_2_load)); 116 117 // Finish the load request for path_1, then for path_2. 118 loader.RunCreateCallback(fake_profile_path_1, &profile, 119 Profile::CREATE_STATUS_INITIALIZED); 120 loader.RunCreateCallback(fake_profile_path_2, &profile, 121 Profile::CREATE_STATUS_INITIALIZED); 122 EXPECT_FALSE(loader.IsAnyProfileLoading()); 123 124 // The second request for path_2 should return immediately. 125 loader.LoadProfileInvalidatingOtherLoads( 126 fake_profile_path_2, base::Bind(&MockCallback::Run, path_2_load)); 127 128 // Make a second request for path_1, and invalidate it. 129 loader.LoadProfileInvalidatingOtherLoads( 130 fake_profile_path_1, base::Bind(&MockCallback::Run, path_1_load)); 131 loader.InvalidatePendingProfileLoads(); 132 } 133 134 } // namespace 135