| Index: ios/chrome/browser/sessions/session_service.mm
|
| diff --git a/ios/chrome/browser/sessions/session_service.mm b/ios/chrome/browser/sessions/session_service.mm
|
| deleted file mode 100644
|
| index b1254ffd046ada214e9f28026db231616b46f1ff..0000000000000000000000000000000000000000
|
| --- a/ios/chrome/browser/sessions/session_service.mm
|
| +++ /dev/null
|
| @@ -1,279 +0,0 @@
|
| -// Copyright 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#import "ios/chrome/browser/sessions/session_service.h"
|
| -
|
| -#import <UIKit/UIKit.h>
|
| -
|
| -#include "base/files/file_path.h"
|
| -#include "base/location.h"
|
| -#include "base/logging.h"
|
| -#include "base/mac/bind_objc_block.h"
|
| -#include "base/mac/foundation_util.h"
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/sequenced_task_runner.h"
|
| -#include "base/strings/sys_string_conversions.h"
|
| -#include "base/synchronization/lock.h"
|
| -#include "base/threading/sequenced_worker_pool.h"
|
| -#include "base/threading/thread_restrictions.h"
|
| -#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
|
| -#import "ios/chrome/browser/sessions/session_window_ios.h"
|
| -#import "ios/web/public/crw_navigation_item_storage.h"
|
| -#import "ios/web/public/crw_session_certificate_policy_cache_storage.h"
|
| -#import "ios/web/public/crw_session_storage.h"
|
| -#include "ios/web/public/web_thread.h"
|
| -
|
| -// When C++ exceptions are disabled, the C++ library defines |try| and
|
| -// |catch| so as to allow exception-expecting C++ code to build properly when
|
| -// language support for exceptions is not present. These macros interfere
|
| -// with the use of |@try| and |@catch| in Objective-C files such as this one.
|
| -// Undefine these macros here, after everything has been #included, since
|
| -// there will be no C++ uses and only Objective-C uses from this point on.
|
| -#undef try
|
| -#undef catch
|
| -
|
| -const NSTimeInterval kSaveDelay = 2.5; // Value taken from Desktop Chrome.
|
| -
|
| -@interface SessionWindowUnarchiver ()
|
| -
|
| -// Register compatibility aliases to support loading serialised sessions
|
| -// informations when the serialised classes are renamed.
|
| -+ (void)registerCompatibilityAliases;
|
| -
|
| -@end
|
| -
|
| -@implementation SessionWindowUnarchiver
|
| -
|
| -@synthesize browserState = _browserState;
|
| -
|
| -- (instancetype)initForReadingWithData:(NSData*)data
|
| - browserState:(ios::ChromeBrowserState*)browserState {
|
| - if (self = [super initForReadingWithData:data]) {
|
| - _browserState = browserState;
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (instancetype)initForReadingWithData:(NSData*)data {
|
| - return [self initForReadingWithData:data browserState:nullptr];
|
| -}
|
| -
|
| -+ (void)initialize {
|
| - [super initialize];
|
| - [self registerCompatibilityAliases];
|
| -}
|
| -
|
| -// When adding a new compatibility alias here, create a new crbug to track its
|
| -// removal and mark it with a release at least one year after the introduction
|
| -// of the alias.
|
| -+ (void)registerCompatibilityAliases {
|
| - // TODO(crbug.com/661633): those aliases where introduced between M57 and
|
| - // M58, so remove them after M67 has shipped to stable.
|
| - [SessionWindowUnarchiver
|
| - setClass:[CRWSessionCertificatePolicyCacheStorage class]
|
| - forClassName:@"SessionCertificatePolicyManager"];
|
| - [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
|
| - forClassName:@"SessionController"];
|
| - [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
|
| - forClassName:@"CRWSessionController"];
|
| - [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
|
| - forClassName:@"SessionEntry"];
|
| - [SessionWindowUnarchiver setClass:[CRWNavigationItemStorage class]
|
| - forClassName:@"CRWSessionEntry"];
|
| - [SessionWindowUnarchiver setClass:[SessionWindowIOS class]
|
| - forClassName:@"SessionWindow"];
|
| -
|
| - // TODO(crbug.com/661633): this alias was introduced between M58 and M59, so
|
| - // remove it after M68 has shipped to stable.
|
| - [SessionWindowUnarchiver setClass:[CRWSessionStorage class]
|
| - forClassName:@"CRWNavigationManagerStorage"];
|
| - [SessionWindowUnarchiver
|
| - setClass:[CRWSessionCertificatePolicyCacheStorage class]
|
| - forClassName:@"CRWSessionCertificatePolicyManager"];
|
| -}
|
| -
|
| -@end
|
| -
|
| -@interface SessionServiceIOS () {
|
| - // The SequencedTaskRunner on which File IO operations are performed.
|
| - scoped_refptr<base::SequencedTaskRunner> _taskRunner;
|
| -
|
| - // Maps save directories to the pending SessionWindow for the delayed
|
| - // save behavior.
|
| - base::scoped_nsobject<NSMutableDictionary> _pendingWindows;
|
| -}
|
| -
|
| -// Saves the session corresponding to |directory| on the background
|
| -// task runner |_taskRunner|.
|
| -- (void)performSaveToDirectoryInBackground:(NSString*)directory;
|
| -@end
|
| -
|
| -@implementation SessionServiceIOS
|
| -
|
| -+ (SessionServiceIOS*)sharedService {
|
| - static SessionServiceIOS* singleton = nil;
|
| - if (!singleton) {
|
| - singleton = [[[self class] alloc] init];
|
| - }
|
| - return singleton;
|
| -}
|
| -
|
| -- (instancetype)init {
|
| - self = [super init];
|
| - if (self) {
|
| - _pendingWindows.reset([[NSMutableDictionary alloc] init]);
|
| - auto* pool = web::WebThread::GetBlockingPool();
|
| - _taskRunner = pool->GetSequencedTaskRunner(pool->GetSequenceToken());
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -// Returns the path of the session file.
|
| -- (NSString*)sessionFilePathForDirectory:(NSString*)directory {
|
| - return [directory stringByAppendingPathComponent:@"session.plist"];
|
| -}
|
| -
|
| -// Do the work of saving on a background thread. Assumes |window| is threadsafe.
|
| -- (void)performSaveToDirectoryInBackground:(NSString*)directory {
|
| - DCHECK(directory);
|
| - DCHECK([_pendingWindows objectForKey:directory] != nil);
|
| - UIBackgroundTaskIdentifier identifier = [[UIApplication sharedApplication]
|
| - beginBackgroundTaskWithExpirationHandler:^{
|
| - }];
|
| - DCHECK(identifier != UIBackgroundTaskInvalid);
|
| -
|
| - // Put the window into a local var so it can be retained for the block, yet
|
| - // we can remove it from the dictionary to allow queuing another save.
|
| - SessionWindowIOS* localWindow =
|
| - [[_pendingWindows objectForKey:directory] retain];
|
| - [_pendingWindows removeObjectForKey:directory];
|
| -
|
| - _taskRunner->PostTask(
|
| - FROM_HERE, base::BindBlock(^{
|
| - @try {
|
| - [self performSaveWindow:localWindow toDirectory:directory];
|
| - } @catch (NSException* e) {
|
| - // Do nothing.
|
| - }
|
| - [localWindow release];
|
| - [[UIApplication sharedApplication] endBackgroundTask:identifier];
|
| - }));
|
| -}
|
| -
|
| -// Saves a SessionWindowIOS in a given directory. In case the directory doesn't
|
| -// exists it will be automatically created.
|
| -- (void)performSaveWindow:(SessionWindowIOS*)window
|
| - toDirectory:(NSString*)directory {
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| - NSFileManager* fileManager = [NSFileManager defaultManager];
|
| - BOOL isDir;
|
| - if (![fileManager fileExistsAtPath:directory isDirectory:&isDir]) {
|
| - NSError* error = nil;
|
| - BOOL result = [fileManager createDirectoryAtPath:directory
|
| - withIntermediateDirectories:YES
|
| - attributes:nil
|
| - error:&error];
|
| - DCHECK(result);
|
| - if (!result) {
|
| - DLOG(ERROR) << "Error creating destination dir: "
|
| - << base::SysNSStringToUTF8([error description]);
|
| - return;
|
| - }
|
| - } else {
|
| - DCHECK(isDir);
|
| - if (!isDir) {
|
| - DLOG(ERROR) << "Destination Directory already exists and is a file";
|
| - return;
|
| - }
|
| - }
|
| -
|
| - NSString* filename = [self sessionFilePathForDirectory:directory];
|
| - if (filename) {
|
| - BOOL result = [NSKeyedArchiver archiveRootObject:window toFile:filename];
|
| - DCHECK(result);
|
| - if (!result)
|
| - DLOG(ERROR) << "Error writing session file to " << filename;
|
| - // Encrypt the session file (mostly for Incognito, but can't hurt to
|
| - // always do it).
|
| - NSDictionary* attributeDict =
|
| - [NSDictionary dictionaryWithObject:NSFileProtectionComplete
|
| - forKey:NSFileProtectionKey];
|
| - NSError* error = nil;
|
| - BOOL success = [[NSFileManager defaultManager] setAttributes:attributeDict
|
| - ofItemAtPath:filename
|
| - error:&error];
|
| - if (!success) {
|
| - DLOG(ERROR) << "Error encrypting session file"
|
| - << base::SysNSStringToUTF8([error description]);
|
| - }
|
| - }
|
| -}
|
| -
|
| -- (void)saveWindow:(SessionWindowIOS*)window
|
| - forBrowserState:(ios::ChromeBrowserState*)browserState
|
| - immediately:(BOOL)immediately {
|
| - NSString* stashPath =
|
| - base::SysUTF8ToNSString(browserState->GetStatePath().value());
|
| - // If there's an existing session window for |stashPath|, clear it before it's
|
| - // replaced.
|
| - SessionWindowIOS* pendingSession = base::mac::ObjCCast<SessionWindowIOS>(
|
| - [_pendingWindows objectForKey:stashPath]);
|
| - [pendingSession clearSessions];
|
| - // Set |window| as the pending save for |stashPath|.
|
| - [_pendingWindows setObject:window forKey:stashPath];
|
| - if (immediately) {
|
| - [NSObject cancelPreviousPerformRequestsWithTarget:self];
|
| - [self performSaveToDirectoryInBackground:stashPath];
|
| - } else if (!pendingSession) {
|
| - // If there wasn't previously a delayed save pending for |stashPath|,
|
| - // enqueue one now.
|
| - [self performSelector:@selector(performSaveToDirectoryInBackground:)
|
| - withObject:stashPath
|
| - afterDelay:kSaveDelay];
|
| - }
|
| -}
|
| -
|
| -- (SessionWindowIOS*)loadWindowForBrowserState:
|
| - (ios::ChromeBrowserState*)browserState {
|
| - NSString* stashPath =
|
| - base::SysUTF8ToNSString(browserState->GetStatePath().value());
|
| - SessionWindowIOS* window =
|
| - [self loadWindowFromPath:[self sessionFilePathForDirectory:stashPath]
|
| - forBrowserState:browserState];
|
| - return window;
|
| -}
|
| -
|
| -- (SessionWindowIOS*)loadWindowFromPath:(NSString*)path
|
| - forBrowserState:(ios::ChromeBrowserState*)browserState {
|
| - SessionWindowIOS* window = nil;
|
| - @try {
|
| - NSData* data = [NSData dataWithContentsOfFile:path];
|
| - if (data) {
|
| - base::scoped_nsobject<SessionWindowUnarchiver> unarchiver([
|
| - [SessionWindowUnarchiver alloc] initForReadingWithData:data
|
| - browserState:browserState]);
|
| - window = [[[unarchiver decodeObjectForKey:@"root"] retain] autorelease];
|
| - }
|
| - } @catch (NSException* exception) {
|
| - DLOG(ERROR) << "Error loading session file.";
|
| - }
|
| - return window;
|
| -}
|
| -
|
| -// Deletes the file containing the commands for the last session in the given
|
| -// browserState directory.
|
| -- (void)deleteLastSession:(NSString*)directory {
|
| - NSString* sessionFile = [self sessionFilePathForDirectory:directory];
|
| - _taskRunner->PostTask(
|
| - FROM_HERE, base::BindBlock(^{
|
| - base::ThreadRestrictions::AssertIOAllowed();
|
| - NSFileManager* fileManager = [NSFileManager defaultManager];
|
| - if (![fileManager fileExistsAtPath:sessionFile])
|
| - return;
|
| - if (![fileManager removeItemAtPath:sessionFile error:nil])
|
| - CHECK(false) << "Unable to delete session file.";
|
| - }));
|
| -}
|
| -
|
| -@end
|
|
|