Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: ios/chrome/browser/sessions/session_service.mm

Issue 2732063003: Add unittests checking that old saved session can be restored. (Closed)
Patch Set: Rebase and document -performSaveToDirectoryInBackground:. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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 #import "ios/chrome/browser/sessions/session_service.h" 5 #import "ios/chrome/browser/sessions/session_service.h"
6 6
7 #import <UIKit/UIKit.h> 7 #import <UIKit/UIKit.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 17 matching lines...) Expand all
28 // |catch| so as to allow exception-expecting C++ code to build properly when 28 // |catch| so as to allow exception-expecting C++ code to build properly when
29 // language support for exceptions is not present. These macros interfere 29 // language support for exceptions is not present. These macros interfere
30 // with the use of |@try| and |@catch| in Objective-C files such as this one. 30 // with the use of |@try| and |@catch| in Objective-C files such as this one.
31 // Undefine these macros here, after everything has been #included, since 31 // Undefine these macros here, after everything has been #included, since
32 // there will be no C++ uses and only Objective-C uses from this point on. 32 // there will be no C++ uses and only Objective-C uses from this point on.
33 #undef try 33 #undef try
34 #undef catch 34 #undef catch
35 35
36 const NSTimeInterval kSaveDelay = 2.5; // Value taken from Desktop Chrome. 36 const NSTimeInterval kSaveDelay = 2.5; // Value taken from Desktop Chrome.
37 37
38 @interface SessionWindowUnarchiver () { 38 @interface SessionWindowUnarchiver ()
39 ios::ChromeBrowserState* _browserState; 39
40 } 40 // Register compatibility aliases to support loading serialised sessions
41 // informations when the serialised classes are renamed.
42 + (void)registerCompatibilityAliases;
41 43
42 @end 44 @end
43 45
44 @implementation SessionWindowUnarchiver 46 @implementation SessionWindowUnarchiver
45 47
46 @synthesize browserState = _browserState; // weak 48 @synthesize browserState = _browserState;
47 49
48 - (id)initForReadingWithData:(NSData*)data 50 - (instancetype)initForReadingWithData:(NSData*)data
49 browserState:(ios::ChromeBrowserState*)browserState { 51 browserState:(ios::ChromeBrowserState*)browserState {
50 if (self = [super initForReadingWithData:data]) { 52 if (self = [super initForReadingWithData:data]) {
51 _browserState = browserState; 53 _browserState = browserState;
52 } 54 }
53 return self; 55 return self;
54 } 56 }
55 57
58 - (instancetype)initForReadingWithData:(NSData*)data {
59 return [self initForReadingWithData:data browserState:nullptr];
60 }
61
62 + (void)initialize {
63 [super initialize];
64 [self registerCompatibilityAliases];
65 }
66
67 // When adding a new compatibility alias here, create a new crbug to track its
68 // removal and mark it with a release at least one year after the introduction
69 // of the alias.
70 + (void)registerCompatibilityAliases {
71 // TODO(crbug.com/661633): those aliases where introduced between M57 and
72 // M58, so remove them after M67 has shipped to stable.
73 [SessionWindowUnarchiver setClass:[CRWSessionCertificatePolicyManager class]
74 forClassName:@"SessionCertificatePolicyManager"];
75 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
76 forClassName:@"SessionController"];
77 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
78 forClassName:@"CRWSessionController"];
79 [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
80 forClassName:@"SessionEntry"];
81 [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
82 forClassName:@"CRWSessionEntry"];
83 [SessionWindowUnarchiver setClass:[SessionWindowIOS class]
84 forClassName:@"SessionWindow"];
85
86 // TODO(crbug.com/661633): this alias was introduced between M58 and M59, so
87 // remove it after M68 has shipped to stable.
88 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
89 forClassName:@"CRWNavigationManagerStorage"];
90 }
91
56 @end 92 @end
57 93
58 @interface SessionServiceIOS () { 94 @interface SessionServiceIOS () {
59 @private
60 // The SequencedTaskRunner on which File IO operations are performed. 95 // The SequencedTaskRunner on which File IO operations are performed.
61 scoped_refptr<base::SequencedTaskRunner> taskRunner_; 96 scoped_refptr<base::SequencedTaskRunner> _taskRunner;
62 97
63 // Maps save directories to the pending SessionWindow for the delayed 98 // Maps save directories to the pending SessionWindow for the delayed
64 // save behavior. 99 // save behavior.
65 base::scoped_nsobject<NSMutableDictionary> pendingWindows_; 100 base::scoped_nsobject<NSMutableDictionary> _pendingWindows;
66 } 101 }
67 102
103 // Saves the session corresponding to |directory| on the background
104 // task runner |_taskRunner|.
68 - (void)performSaveToDirectoryInBackground:(NSString*)directory; 105 - (void)performSaveToDirectoryInBackground:(NSString*)directory;
69 - (void)performSaveWindow:(SessionWindowIOS*)window
70 toDirectory:(NSString*)directory;
71 @end 106 @end
72 107
73 @implementation SessionServiceIOS 108 @implementation SessionServiceIOS
74 109
75 + (SessionServiceIOS*)sharedService { 110 + (SessionServiceIOS*)sharedService {
76 static SessionServiceIOS* singleton = nil; 111 static SessionServiceIOS* singleton = nil;
77 if (!singleton) { 112 if (!singleton) {
78 singleton = [[[self class] alloc] init]; 113 singleton = [[[self class] alloc] init];
79 } 114 }
80 return singleton; 115 return singleton;
81 } 116 }
82 117
83 - (id)init { 118 - (instancetype)init {
84 self = [super init]; 119 self = [super init];
85 if (self) { 120 if (self) {
86 pendingWindows_.reset([[NSMutableDictionary alloc] init]); 121 _pendingWindows.reset([[NSMutableDictionary alloc] init]);
87 auto* pool = web::WebThread::GetBlockingPool(); 122 auto* pool = web::WebThread::GetBlockingPool();
88 taskRunner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 123 _taskRunner = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
89 } 124 }
90 return self; 125 return self;
91 } 126 }
92 127
93 // Returns the path of the session file. 128 // Returns the path of the session file.
94 - (NSString*)sessionFilePathForDirectory:(NSString*)directory { 129 - (NSString*)sessionFilePathForDirectory:(NSString*)directory {
95 return [directory stringByAppendingPathComponent:@"session.plist"]; 130 return [directory stringByAppendingPathComponent:@"session.plist"];
96 } 131 }
97 132
98 // Do the work of saving on a background thread. Assumes |window| is threadsafe. 133 // Do the work of saving on a background thread. Assumes |window| is threadsafe.
99 - (void)performSaveToDirectoryInBackground:(NSString*)directory { 134 - (void)performSaveToDirectoryInBackground:(NSString*)directory {
100 DCHECK(directory); 135 DCHECK(directory);
101 DCHECK([pendingWindows_ objectForKey:directory] != nil); 136 DCHECK([_pendingWindows objectForKey:directory] != nil);
102 UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] 137 UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication]
103 beginBackgroundTaskWithExpirationHandler:^{ 138 beginBackgroundTaskWithExpirationHandler:^{
104 }]; 139 }];
105 DCHECK(identifier != UIBackgroundTaskInvalid); 140 DCHECK(identifier != UIBackgroundTaskInvalid);
106 141
107 // Put the window into a local var so it can be retained for the block, yet 142 // Put the window into a local var so it can be retained for the block, yet
108 // we can remove it from the dictionary to allow queuing another save. 143 // we can remove it from the dictionary to allow queuing another save.
109 SessionWindowIOS* localWindow = 144 SessionWindowIOS* localWindow =
110 [[pendingWindows_ objectForKey:directory] retain]; 145 [[_pendingWindows objectForKey:directory] retain];
111 [pendingWindows_ removeObjectForKey:directory]; 146 [_pendingWindows removeObjectForKey:directory];
112 147
113 taskRunner_->PostTask( 148 _taskRunner->PostTask(
114 FROM_HERE, base::BindBlock(^{ 149 FROM_HERE, base::BindBlock(^{
115 @try { 150 @try {
116 [self performSaveWindow:localWindow toDirectory:directory]; 151 [self performSaveWindow:localWindow toDirectory:directory];
117 } @catch (NSException* e) { 152 } @catch (NSException* e) {
118 // Do nothing. 153 // Do nothing.
119 } 154 }
120 [localWindow release]; 155 [localWindow release];
121 [[UIApplication sharedApplication] endBackgroundTask:identifier]; 156 [[UIApplication sharedApplication] endBackgroundTask:identifier];
122 })); 157 }));
123 } 158 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 } 207 }
173 208
174 - (void)saveWindow:(SessionWindowIOS*)window 209 - (void)saveWindow:(SessionWindowIOS*)window
175 forBrowserState:(ios::ChromeBrowserState*)browserState 210 forBrowserState:(ios::ChromeBrowserState*)browserState
176 immediately:(BOOL)immediately { 211 immediately:(BOOL)immediately {
177 NSString* stashPath = 212 NSString* stashPath =
178 base::SysUTF8ToNSString(browserState->GetStatePath().value()); 213 base::SysUTF8ToNSString(browserState->GetStatePath().value());
179 // If there's an existing session window for |stashPath|, clear it before it's 214 // If there's an existing session window for |stashPath|, clear it before it's
180 // replaced. 215 // replaced.
181 SessionWindowIOS* pendingSession = base::mac::ObjCCast<SessionWindowIOS>( 216 SessionWindowIOS* pendingSession = base::mac::ObjCCast<SessionWindowIOS>(
182 [pendingWindows_ objectForKey:stashPath]); 217 [_pendingWindows objectForKey:stashPath]);
183 [pendingSession clearSessions]; 218 [pendingSession clearSessions];
184 // Set |window| as the pending save for |stashPath|. 219 // Set |window| as the pending save for |stashPath|.
185 [pendingWindows_ setObject:window forKey:stashPath]; 220 [_pendingWindows setObject:window forKey:stashPath];
186 if (immediately) { 221 if (immediately) {
187 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 222 [NSObject cancelPreviousPerformRequestsWithTarget:self];
188 [self performSaveToDirectoryInBackground:stashPath]; 223 [self performSaveToDirectoryInBackground:stashPath];
189 } else if (!pendingSession) { 224 } else if (!pendingSession) {
190 // If there wasn't previously a delayed save pending for |stashPath|, 225 // If there wasn't previously a delayed save pending for |stashPath|,
191 // enqueue one now. 226 // enqueue one now.
192 [self performSelector:@selector(performSaveToDirectoryInBackground:) 227 [self performSelector:@selector(performSaveToDirectoryInBackground:)
193 withObject:stashPath 228 withObject:stashPath
194 afterDelay:kSaveDelay]; 229 afterDelay:kSaveDelay];
195 } 230 }
196 } 231 }
197 232
198 - (SessionWindowIOS*)loadWindowForBrowserState: 233 - (SessionWindowIOS*)loadWindowForBrowserState:
199 (ios::ChromeBrowserState*)browserState { 234 (ios::ChromeBrowserState*)browserState {
200 NSString* stashPath = 235 NSString* stashPath =
201 base::SysUTF8ToNSString(browserState->GetStatePath().value()); 236 base::SysUTF8ToNSString(browserState->GetStatePath().value());
202 SessionWindowIOS* window = 237 SessionWindowIOS* window =
203 [self loadWindowFromPath:[self sessionFilePathForDirectory:stashPath] 238 [self loadWindowFromPath:[self sessionFilePathForDirectory:stashPath]
204 forBrowserState:browserState]; 239 forBrowserState:browserState];
205 return window; 240 return window;
206 } 241 }
207 242
208 - (SessionWindowIOS*)loadWindowFromPath:(NSString*)path 243 - (SessionWindowIOS*)loadWindowFromPath:(NSString*)path
209 forBrowserState:(ios::ChromeBrowserState*)browserState { 244 forBrowserState:(ios::ChromeBrowserState*)browserState {
210 // HACK: Handle the case where we had to change the class name of a persisted
211 // class on disk.
212 [SessionWindowUnarchiver setClass:[CRWSessionCertificatePolicyManager class]
213 forClassName:@"SessionCertificatePolicyManager"];
214 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
215 forClassName:@"SessionController"];
216 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
217 forClassName:@"CRWSessionController"];
218 [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
219 forClassName:@"CRWNavigationManagerStorage"];
220 [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
221 forClassName:@"SessionEntry"];
222 [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
223 forClassName:@"CRWSessionEntry"];
224 // TODO(crbug.com/661633): Remove this hack.
225 [SessionWindowUnarchiver setClass:[SessionWindowIOS class]
226 forClassName:@"SessionWindow"];
227 SessionWindowIOS* window = nil; 245 SessionWindowIOS* window = nil;
228 @try { 246 @try {
229 NSData* data = [NSData dataWithContentsOfFile:path]; 247 NSData* data = [NSData dataWithContentsOfFile:path];
230 if (data) { 248 if (data) {
231 base::scoped_nsobject<SessionWindowUnarchiver> unarchiver([ 249 base::scoped_nsobject<SessionWindowUnarchiver> unarchiver([
232 [SessionWindowUnarchiver alloc] initForReadingWithData:data 250 [SessionWindowUnarchiver alloc] initForReadingWithData:data
233 browserState:browserState]); 251 browserState:browserState]);
234 window = [[[unarchiver decodeObjectForKey:@"root"] retain] autorelease]; 252 window = [[[unarchiver decodeObjectForKey:@"root"] retain] autorelease];
235 } 253 }
236 } @catch (NSException* exception) { 254 } @catch (NSException* exception) {
237 DLOG(ERROR) << "Error loading session.plist"; 255 DLOG(ERROR) << "Error loading session file.";
238 } 256 }
239 return window; 257 return window;
240 } 258 }
241 259
242 // Deletes the file containing the commands for the last session in the given 260 // Deletes the file containing the commands for the last session in the given
243 // browserState directory. 261 // browserState directory.
244 - (void)deleteLastSession:(NSString*)directory { 262 - (void)deleteLastSession:(NSString*)directory {
245 NSString* sessionFile = [self sessionFilePathForDirectory:directory]; 263 NSString* sessionFile = [self sessionFilePathForDirectory:directory];
246 taskRunner_->PostTask( 264 _taskRunner->PostTask(
247 FROM_HERE, base::BindBlock(^{ 265 FROM_HERE, base::BindBlock(^{
248 base::ThreadRestrictions::AssertIOAllowed(); 266 base::ThreadRestrictions::AssertIOAllowed();
249 NSFileManager* fileManager = [NSFileManager defaultManager]; 267 NSFileManager* fileManager = [NSFileManager defaultManager];
250 if (![fileManager fileExistsAtPath:sessionFile]) 268 if (![fileManager fileExistsAtPath:sessionFile])
251 return; 269 return;
252 if (![fileManager removeItemAtPath:sessionFile error:nil]) 270 if (![fileManager removeItemAtPath:sessionFile error:nil])
253 CHECK(false) << "Unable to delete session file."; 271 CHECK(false) << "Unable to delete session file.";
254 })); 272 }));
255 } 273 }
256 274
257 @end 275 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/sessions/session_service.h ('k') | ios/chrome/browser/sessions/session_service_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698