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

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: 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
68 - (void)performSaveToDirectoryInBackground:(NSString*)directory; 103 - (void)performSaveToDirectoryInBackground:(NSString*)directory;
kkhorimoto 2017/03/07 05:13:53 Since we're cleaning up this class, can you add a
sdefresne 2017/03/07 17:58:17 Done.
69 - (void)performSaveWindow:(SessionWindowIOS*)window
70 toDirectory:(NSString*)directory;
71 @end 104 @end
72 105
73 @implementation SessionServiceIOS 106 @implementation SessionServiceIOS
74 107
75 + (SessionServiceIOS*)sharedService { 108 + (SessionServiceIOS*)sharedService {
76 static SessionServiceIOS* singleton = nil; 109 static SessionServiceIOS* singleton = nil;
77 if (!singleton) { 110 if (!singleton) {
78 singleton = [[[self class] alloc] init]; 111 singleton = [[[self class] alloc] init];
79 } 112 }
80 return singleton; 113 return singleton;
81 } 114 }
82 115
83 - (id)init { 116 - (instancetype)init {
84 self = [super init]; 117 self = [super init];
85 if (self) { 118 if (self) {
86 pendingWindows_.reset([[NSMutableDictionary alloc] init]); 119 _pendingWindows.reset([[NSMutableDictionary alloc] init]);
87 auto* pool = web::WebThread::GetBlockingPool(); 120 auto* pool = web::WebThread::GetBlockingPool();
88 taskRunner_ = pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 121 _taskRunner = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
89 } 122 }
90 return self; 123 return self;
91 } 124 }
92 125
93 // Returns the path of the session file. 126 // Returns the path of the session file.
94 - (NSString*)sessionFilePathForDirectory:(NSString*)directory { 127 - (NSString*)sessionFilePathForDirectory:(NSString*)directory {
95 return [directory stringByAppendingPathComponent:@"session.plist"]; 128 return [directory stringByAppendingPathComponent:@"session.plist"];
96 } 129 }
97 130
98 // Do the work of saving on a background thread. Assumes |window| is threadsafe. 131 // Do the work of saving on a background thread. Assumes |window| is threadsafe.
99 - (void)performSaveToDirectoryInBackground:(NSString*)directory { 132 - (void)performSaveToDirectoryInBackground:(NSString*)directory {
100 DCHECK(directory); 133 DCHECK(directory);
101 DCHECK([pendingWindows_ objectForKey:directory] != nil); 134 DCHECK([_pendingWindows objectForKey:directory] != nil);
102 UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication] 135 UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication]
103 beginBackgroundTaskWithExpirationHandler:^{ 136 beginBackgroundTaskWithExpirationHandler:^{
104 }]; 137 }];
105 DCHECK(identifier != UIBackgroundTaskInvalid); 138 DCHECK(identifier != UIBackgroundTaskInvalid);
106 139
107 // Put the window into a local var so it can be retained for the block, yet 140 // 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. 141 // we can remove it from the dictionary to allow queuing another save.
109 SessionWindowIOS* localWindow = 142 SessionWindowIOS* localWindow =
110 [[pendingWindows_ objectForKey:directory] retain]; 143 [[_pendingWindows objectForKey:directory] retain];
111 [pendingWindows_ removeObjectForKey:directory]; 144 [_pendingWindows removeObjectForKey:directory];
112 145
113 taskRunner_->PostTask( 146 _taskRunner->PostTask(
114 FROM_HERE, base::BindBlock(^{ 147 FROM_HERE, base::BindBlock(^{
115 @try { 148 @try {
116 [self performSaveWindow:localWindow toDirectory:directory]; 149 [self performSaveWindow:localWindow toDirectory:directory];
117 } @catch (NSException* e) { 150 } @catch (NSException* e) {
118 // Do nothing. 151 // Do nothing.
119 } 152 }
120 [localWindow release]; 153 [localWindow release];
121 [[UIApplication sharedApplication] endBackgroundTask:identifier]; 154 [[UIApplication sharedApplication] endBackgroundTask:identifier];
122 })); 155 }));
123 } 156 }
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 } 205 }
173 206
174 - (void)saveWindow:(SessionWindowIOS*)window 207 - (void)saveWindow:(SessionWindowIOS*)window
175 forBrowserState:(ios::ChromeBrowserState*)browserState 208 forBrowserState:(ios::ChromeBrowserState*)browserState
176 immediately:(BOOL)immediately { 209 immediately:(BOOL)immediately {
177 NSString* stashPath = 210 NSString* stashPath =
178 base::SysUTF8ToNSString(browserState->GetStatePath().value()); 211 base::SysUTF8ToNSString(browserState->GetStatePath().value());
179 // If there's an existing session window for |stashPath|, clear it before it's 212 // If there's an existing session window for |stashPath|, clear it before it's
180 // replaced. 213 // replaced.
181 SessionWindowIOS* pendingSession = base::mac::ObjCCast<SessionWindowIOS>( 214 SessionWindowIOS* pendingSession = base::mac::ObjCCast<SessionWindowIOS>(
182 [pendingWindows_ objectForKey:stashPath]); 215 [_pendingWindows objectForKey:stashPath]);
183 [pendingSession clearSessions]; 216 [pendingSession clearSessions];
184 // Set |window| as the pending save for |stashPath|. 217 // Set |window| as the pending save for |stashPath|.
185 [pendingWindows_ setObject:window forKey:stashPath]; 218 [_pendingWindows setObject:window forKey:stashPath];
186 if (immediately) { 219 if (immediately) {
187 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 220 [NSObject cancelPreviousPerformRequestsWithTarget:self];
188 [self performSaveToDirectoryInBackground:stashPath]; 221 [self performSaveToDirectoryInBackground:stashPath];
189 } else if (!pendingSession) { 222 } else if (!pendingSession) {
190 // If there wasn't previously a delayed save pending for |stashPath|, 223 // If there wasn't previously a delayed save pending for |stashPath|,
191 // enqueue one now. 224 // enqueue one now.
192 [self performSelector:@selector(performSaveToDirectoryInBackground:) 225 [self performSelector:@selector(performSaveToDirectoryInBackground:)
193 withObject:stashPath 226 withObject:stashPath
194 afterDelay:kSaveDelay]; 227 afterDelay:kSaveDelay];
195 } 228 }
196 } 229 }
197 230
198 - (SessionWindowIOS*)loadWindowForBrowserState: 231 - (SessionWindowIOS*)loadWindowForBrowserState:
199 (ios::ChromeBrowserState*)browserState { 232 (ios::ChromeBrowserState*)browserState {
200 NSString* stashPath = 233 NSString* stashPath =
201 base::SysUTF8ToNSString(browserState->GetStatePath().value()); 234 base::SysUTF8ToNSString(browserState->GetStatePath().value());
202 SessionWindowIOS* window = 235 SessionWindowIOS* window =
203 [self loadWindowFromPath:[self sessionFilePathForDirectory:stashPath] 236 [self loadWindowFromPath:[self sessionFilePathForDirectory:stashPath]
204 forBrowserState:browserState]; 237 forBrowserState:browserState];
205 return window; 238 return window;
206 } 239 }
207 240
208 - (SessionWindowIOS*)loadWindowFromPath:(NSString*)path 241 - (SessionWindowIOS*)loadWindowFromPath:(NSString*)path
209 forBrowserState:(ios::ChromeBrowserState*)browserState { 242 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; 243 SessionWindowIOS* window = nil;
228 @try { 244 @try {
229 NSData* data = [NSData dataWithContentsOfFile:path]; 245 NSData* data = [NSData dataWithContentsOfFile:path];
230 if (data) { 246 if (data) {
231 base::scoped_nsobject<SessionWindowUnarchiver> unarchiver([ 247 base::scoped_nsobject<SessionWindowUnarchiver> unarchiver([
232 [SessionWindowUnarchiver alloc] initForReadingWithData:data 248 [SessionWindowUnarchiver alloc] initForReadingWithData:data
233 browserState:browserState]); 249 browserState:browserState]);
234 window = [[[unarchiver decodeObjectForKey:@"root"] retain] autorelease]; 250 window = [[[unarchiver decodeObjectForKey:@"root"] retain] autorelease];
235 } 251 }
236 } @catch (NSException* exception) { 252 } @catch (NSException* exception) {
237 DLOG(ERROR) << "Error loading session.plist"; 253 DLOG(ERROR) << "Error loading session file.";
238 } 254 }
239 return window; 255 return window;
240 } 256 }
241 257
242 // Deletes the file containing the commands for the last session in the given 258 // Deletes the file containing the commands for the last session in the given
243 // browserState directory. 259 // browserState directory.
244 - (void)deleteLastSession:(NSString*)directory { 260 - (void)deleteLastSession:(NSString*)directory {
245 NSString* sessionFile = [self sessionFilePathForDirectory:directory]; 261 NSString* sessionFile = [self sessionFilePathForDirectory:directory];
246 taskRunner_->PostTask( 262 _taskRunner->PostTask(
247 FROM_HERE, base::BindBlock(^{ 263 FROM_HERE, base::BindBlock(^{
248 base::ThreadRestrictions::AssertIOAllowed(); 264 base::ThreadRestrictions::AssertIOAllowed();
249 NSFileManager* fileManager = [NSFileManager defaultManager]; 265 NSFileManager* fileManager = [NSFileManager defaultManager];
250 if (![fileManager fileExistsAtPath:sessionFile]) 266 if (![fileManager fileExistsAtPath:sessionFile])
251 return; 267 return;
252 if (![fileManager removeItemAtPath:sessionFile error:nil]) 268 if (![fileManager removeItemAtPath:sessionFile error:nil])
253 CHECK(false) << "Unable to delete session file."; 269 CHECK(false) << "Unable to delete session file.";
254 })); 270 }));
255 } 271 }
256 272
257 @end 273 @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