Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |