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

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

Issue 2811593004: [ios] Allow having multiple session windows in a session. (Closed)
Patch Set: Address comments. Created 3 years, 8 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_ios.h" 5 #import "ios/chrome/browser/sessions/session_service_ios.h"
6 6
7 #import <UIKit/UIKit.h> 7 #import <UIKit/UIKit.h>
8 8
9 #include "base/critical_closure.h" 9 #include "base/critical_closure.h"
10 #include "base/files/file_path.h" 10 #include "base/files/file_path.h"
11 #include "base/format_macros.h"
11 #include "base/location.h" 12 #include "base/location.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #import "base/mac/bind_objc_block.h" 14 #import "base/mac/bind_objc_block.h"
15 #import "base/mac/foundation_util.h"
14 #include "base/memory/ref_counted.h" 16 #include "base/memory/ref_counted.h"
15 #include "base/sequenced_task_runner.h" 17 #include "base/sequenced_task_runner.h"
16 #include "base/strings/sys_string_conversions.h" 18 #include "base/strings/sys_string_conversions.h"
17 #include "base/threading/sequenced_worker_pool.h" 19 #include "base/threading/sequenced_worker_pool.h"
18 #include "base/threading/thread_restrictions.h" 20 #include "base/threading/thread_restrictions.h"
21 #import "ios/chrome/browser/sessions/session_ios.h"
19 #import "ios/chrome/browser/sessions/session_window_ios.h" 22 #import "ios/chrome/browser/sessions/session_window_ios.h"
20 #import "ios/web/public/crw_navigation_item_storage.h" 23 #import "ios/web/public/crw_navigation_item_storage.h"
21 #import "ios/web/public/crw_session_certificate_policy_cache_storage.h" 24 #import "ios/web/public/crw_session_certificate_policy_cache_storage.h"
22 #import "ios/web/public/crw_session_storage.h" 25 #import "ios/web/public/crw_session_storage.h"
23 #include "ios/web/public/web_thread.h" 26 #include "ios/web/public/web_thread.h"
24 27
25 #if !defined(__has_feature) || !__has_feature(objc_arc) 28 #if !defined(__has_feature) || !__has_feature(objc_arc)
26 #error "This file requires ARC support." 29 #error "This file requires ARC support."
27 #endif 30 #endif
28 31
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 [self setClass:[CRWSessionCertificatePolicyCacheStorage class] 68 [self setClass:[CRWSessionCertificatePolicyCacheStorage class]
66 forClassName:@"CRWSessionCertificatePolicyManager"]; 69 forClassName:@"CRWSessionCertificatePolicyManager"];
67 } 70 }
68 71
69 @end 72 @end
70 73
71 @implementation SessionServiceIOS { 74 @implementation SessionServiceIOS {
72 // The SequencedTaskRunner on which File IO operations are performed. 75 // The SequencedTaskRunner on which File IO operations are performed.
73 scoped_refptr<base::SequencedTaskRunner> _taskRunner; 76 scoped_refptr<base::SequencedTaskRunner> _taskRunner;
74 77
75 // Maps session path to the pending session window for the delayed save 78 // Maps session path to the pending session for the delayed save behaviour.
76 // behaviour. 79 NSMutableDictionary<NSString*, SessionIOS*>* _pendingSessions;
77 NSMutableDictionary<NSString*, SessionWindowIOS*>* _pendingSessionWindows;
78 } 80 }
79 81
80 #pragma mark - NSObject overrides 82 #pragma mark - NSObject overrides
81 83
82 - (instancetype)init { 84 - (instancetype)init {
83 base::SequencedWorkerPool* pool = web::WebThread::GetBlockingPool(); 85 base::SequencedWorkerPool* pool = web::WebThread::GetBlockingPool();
84 scoped_refptr<base::SequencedTaskRunner> taskRunner = 86 scoped_refptr<base::SequencedTaskRunner> taskRunner =
85 pool->GetSequencedTaskRunner(pool->GetSequenceToken()); 87 pool->GetSequencedTaskRunner(pool->GetSequenceToken());
86 return [self initWithTaskRunner:taskRunner]; 88 return [self initWithTaskRunner:taskRunner];
87 } 89 }
88 90
89 #pragma mark - Public interface 91 #pragma mark - Public interface
90 92
91 + (SessionServiceIOS*)sharedService { 93 + (SessionServiceIOS*)sharedService {
92 static SessionServiceIOS* singleton = nil; 94 static SessionServiceIOS* singleton = nil;
93 if (!singleton) { 95 if (!singleton) {
94 singleton = [[[self class] alloc] init]; 96 singleton = [[[self class] alloc] init];
95 } 97 }
96 return singleton; 98 return singleton;
97 } 99 }
98 100
99 - (instancetype)initWithTaskRunner: 101 - (instancetype)initWithTaskRunner:
100 (const scoped_refptr<base::SequencedTaskRunner>&)taskRunner { 102 (const scoped_refptr<base::SequencedTaskRunner>&)taskRunner {
101 DCHECK(taskRunner); 103 DCHECK(taskRunner);
102 self = [super init]; 104 self = [super init];
103 if (self) { 105 if (self) {
104 _pendingSessionWindows = [NSMutableDictionary dictionary]; 106 _pendingSessions = [NSMutableDictionary dictionary];
105 _taskRunner = taskRunner; 107 _taskRunner = taskRunner;
106 } 108 }
107 return self; 109 return self;
108 } 110 }
109 111
110 - (void)saveSessionWindow:(SessionWindowIOS*)sessionWindow 112 - (void)saveSession:(SessionIOS*)session
111 directory:(NSString*)directory 113 directory:(NSString*)directory
112 immediately:(BOOL)immediately { 114 immediately:(BOOL)immediately {
113 NSString* sessionPath = [[self class] sessionPathForDirectory:directory]; 115 NSString* sessionPath = [[self class] sessionPathForDirectory:directory];
114 BOOL hadPendingSession = 116 BOOL hadPendingSession = [_pendingSessions objectForKey:sessionPath] != nil;
115 [_pendingSessionWindows objectForKey:sessionPath] != nil; 117 [_pendingSessions setObject:session forKey:sessionPath];
116 [_pendingSessionWindows setObject:sessionWindow forKey:sessionPath];
117 if (immediately) { 118 if (immediately) {
118 [NSObject cancelPreviousPerformRequestsWithTarget:self]; 119 [NSObject cancelPreviousPerformRequestsWithTarget:self];
119 [self performSaveToPathInBackground:sessionPath]; 120 [self performSaveToPathInBackground:sessionPath];
120 } else if (!hadPendingSession) { 121 } else if (!hadPendingSession) {
121 // If there wasn't previously a delayed save pending for |sessionPath|, 122 // If there wasn't previously a delayed save pending for |sessionPath|,
122 // enqueue one now. 123 // enqueue one now.
123 [self performSelector:@selector(performSaveToPathInBackground:) 124 [self performSelector:@selector(performSaveToPathInBackground:)
124 withObject:sessionPath 125 withObject:sessionPath
125 afterDelay:kSaveDelay]; 126 afterDelay:kSaveDelay];
126 } 127 }
127 } 128 }
128 129
129 - (SessionWindowIOS*)loadSessionWindowFromDirectory:(NSString*)directory { 130 - (SessionIOS*)loadSessionFromDirectory:(NSString*)directory {
130 NSString* sessionPath = [[self class] sessionPathForDirectory:directory]; 131 NSString* sessionPath = [[self class] sessionPathForDirectory:directory];
131 return [self loadSessionWindowFromPath:sessionPath]; 132 return [self loadSessionFromPath:sessionPath];
132 } 133 }
133 134
134 - (SessionWindowIOS*)loadSessionWindowFromPath:(NSString*)sessionPath { 135 - (SessionIOS*)loadSessionFromPath:(NSString*)sessionPath {
136 NSObject<NSCoding>* rootObject = nil;
135 @try { 137 @try {
136 NSData* data = [NSData dataWithContentsOfFile:sessionPath]; 138 NSData* data = [NSData dataWithContentsOfFile:sessionPath];
137 if (!data) 139 if (!data)
138 return nil; 140 return nil;
139 141
140 NSKeyedUnarchiver* unarchiver = 142 NSKeyedUnarchiver* unarchiver =
141 [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; 143 [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
142 144
143 // Register compatibility aliases to support legacy saved sessions. 145 // Register compatibility aliases to support legacy saved sessions.
144 [unarchiver cr_registerCompatibilityAliases]; 146 [unarchiver cr_registerCompatibilityAliases];
145 return [unarchiver decodeObjectForKey:kRootObjectKey]; 147 rootObject = [unarchiver decodeObjectForKey:kRootObjectKey];
146 } @catch (NSException* exception) { 148 } @catch (NSException* exception) {
147 NOTREACHED() << "Error loading session file: " 149 NOTREACHED() << "Error loading session file: "
148 << base::SysNSStringToUTF8(sessionPath) << ": " 150 << base::SysNSStringToUTF8(sessionPath) << ": "
149 << base::SysNSStringToUTF8([exception reason]); 151 << base::SysNSStringToUTF8([exception reason]);
152 }
153
154 if (!rootObject)
150 return nil; 155 return nil;
156
157 // Support for legacy saved session that contained a single SessionWindowIOS
158 // object as the root object (pre-M-59).
159 if ([rootObject isKindOfClass:[SessionWindowIOS class]]) {
160 return [[SessionIOS alloc] initWithWindows:@[
161 base::mac::ObjCCastStrict<SessionWindowIOS>(rootObject)
162 ]];
151 } 163 }
164
165 return base::mac::ObjCCastStrict<SessionIOS>(rootObject);
152 } 166 }
153 167
154 - (void)deleteLastSessionFileInDirectory:(NSString*)directory { 168 - (void)deleteLastSessionFileInDirectory:(NSString*)directory {
155 NSString* sessionPath = [[self class] sessionPathForDirectory:directory]; 169 NSString* sessionPath = [[self class] sessionPathForDirectory:directory];
156 _taskRunner->PostTask( 170 _taskRunner->PostTask(
157 FROM_HERE, base::BindBlockArc(^{ 171 FROM_HERE, base::BindBlockArc(^{
158 base::ThreadRestrictions::AssertIOAllowed(); 172 base::ThreadRestrictions::AssertIOAllowed();
159 NSFileManager* fileManager = [NSFileManager defaultManager]; 173 NSFileManager* fileManager = [NSFileManager defaultManager];
160 if (![fileManager fileExistsAtPath:sessionPath]) 174 if (![fileManager fileExistsAtPath:sessionPath])
161 return; 175 return;
162 176
163 NSError* error = nil; 177 NSError* error = nil;
164 if (![fileManager removeItemAtPath:sessionPath error:nil]) 178 if (![fileManager removeItemAtPath:sessionPath error:nil])
165 CHECK(false) << "Unable to delete session file: " 179 CHECK(false) << "Unable to delete session file: "
166 << base::SysNSStringToUTF8(sessionPath) << ": " 180 << base::SysNSStringToUTF8(sessionPath) << ": "
167 << base::SysNSStringToUTF8([error description]); 181 << base::SysNSStringToUTF8([error description]);
168 })); 182 }));
169 } 183 }
170 184
171 + (NSString*)sessionPathForDirectory:(NSString*)directory { 185 + (NSString*)sessionPathForDirectory:(NSString*)directory {
172 return [directory stringByAppendingPathComponent:@"session.plist"]; 186 return [directory stringByAppendingPathComponent:@"session.plist"];
173 } 187 }
174 188
175 #pragma mark - Private methods 189 #pragma mark - Private methods
176 190
177 // Do the work of saving on a background thread. 191 // Do the work of saving on a background thread.
178 - (void)performSaveToPathInBackground:(NSString*)sessionPath { 192 - (void)performSaveToPathInBackground:(NSString*)sessionPath {
179 DCHECK(sessionPath); 193 DCHECK(sessionPath);
180 DCHECK([_pendingSessionWindows objectForKey:sessionPath] != nil); 194 DCHECK([_pendingSessions objectForKey:sessionPath] != nil);
181 195
182 // Serialize to NSData on the main thread to avoid accessing potentially 196 // Serialize to NSData on the main thread to avoid accessing potentially
183 // non-threadsafe objects on a background thread. 197 // non-threadsafe objects on a background thread.
184 SessionWindowIOS* sessionWindow = 198 SessionIOS* session = [_pendingSessions objectForKey:sessionPath];
185 [_pendingSessionWindows objectForKey:sessionPath]; 199 [_pendingSessions removeObjectForKey:sessionPath];
186 [_pendingSessionWindows removeObjectForKey:sessionPath];
187 200
188 @try { 201 @try {
189 NSData* sessionData = 202 NSData* sessionData = [NSKeyedArchiver archivedDataWithRootObject:session];
190 [NSKeyedArchiver archivedDataWithRootObject:sessionWindow];
191 _taskRunner->PostTask( 203 _taskRunner->PostTask(
192 FROM_HERE, base::MakeCriticalClosure(base::BindBlockArc(^{ 204 FROM_HERE, base::MakeCriticalClosure(base::BindBlockArc(^{
193 [self performSaveSessionData:sessionData sessionPath:sessionPath]; 205 [self performSaveSessionData:sessionData sessionPath:sessionPath];
194 }))); 206 })));
195 } @catch (NSException* exception) { 207 } @catch (NSException* exception) {
196 NOTREACHED() << "Error serializing session for path: " 208 NOTREACHED() << "Error serializing session for path: "
197 << base::SysNSStringToUTF8(sessionPath) << ": " 209 << base::SysNSStringToUTF8(sessionPath) << ": "
198 << base::SysNSStringToUTF8([exception description]); 210 << base::SysNSStringToUTF8([exception description]);
199 return; 211 return;
200 } 212 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 250
239 if (![sessionData writeToFile:sessionPath options:options error:&error]) { 251 if (![sessionData writeToFile:sessionPath options:options error:&error]) {
240 NOTREACHED() << "Error writing session file: " 252 NOTREACHED() << "Error writing session file: "
241 << base::SysNSStringToUTF8(sessionPath) << ": " 253 << base::SysNSStringToUTF8(sessionPath) << ": "
242 << base::SysNSStringToUTF8([error description]); 254 << base::SysNSStringToUTF8([error description]);
243 return; 255 return;
244 } 256 }
245 } 257 }
246 258
247 @end 259 @end
OLDNEW
« no previous file with comments | « ios/chrome/browser/sessions/session_service_ios.h ('k') | ios/chrome/browser/sessions/session_service_ios_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698