// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/app/startup/sandbox_dump.h"
#import <Foundation/Foundation.h>
#import "base/apple/bundle_locations.h"
#import "base/functional/bind.h"
#import "base/strings/sys_string_conversions.h"
#import "ios/chrome/app/startup/ios_enable_sandbox_dump_buildflags.h"
#import "ios/chrome/common/app_group/app_group_constants.h"
#import "third_party/zlib/google/zip.h"
#if !BUILDFLAG(IOS_ENABLE_SANDBOX_DUMP)
#error "This file should only be compiled with IOS_ENABLE_SANDBOX_DUMP flag."
#endif // BUILDFLAG(IOS_ENABLE_SANDBOX_DUMP)
void DumpSandboxIfRequested() {
if (![[NSUserDefaults standardUserDefaults]
boolForKey:@"EnableDumpSandboxes"]) {
return;
}
[[NSUserDefaults standardUserDefaults] setBool:NO
forKey:@"EnableDumpSandboxes"];
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* document_directory = [paths objectAtIndex:0];
NSString* appdata_directory =
[document_directory stringByDeletingLastPathComponent];
NSString* dump_directory =
[document_directory stringByAppendingPathComponent:@"sandboxdump"];
NSError* error;
[[NSFileManager defaultManager] removeItemAtPath:dump_directory error:&error];
[[NSFileManager defaultManager] createDirectoryAtPath:dump_directory
withIntermediateDirectories:NO
attributes:nil
error:&error];
NSString* application_zip = [dump_directory
stringByAppendingPathComponent:
[NSString stringWithFormat:@"%@.zip", [base::apple::FrameworkBundle()
bundleIdentifier]]];
zip::FilterCallback callback =
base::BindRepeating(^(const base::FilePath& path) {
NSString* nspath = base::SysUTF8ToNSString(path.value());
if ([nspath hasPrefix:document_directory]) {
return false;
}
if (![[NSFileManager defaultManager] isReadableFileAtPath:nspath]) {
return false;
}
return true;
});
base::FilePath source_dir(base::SysNSStringToUTF8(appdata_directory));
base::FilePath zip_path(base::SysNSStringToUTF8(application_zip));
zip::ZipWithFilterCallback(source_dir, zip_path, callback);
NSString* common_group = app_group::CommonApplicationGroup();
if ([common_group length]) {
NSURL* common_group_url = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:common_group];
NSString* common_group_zip = [dump_directory
stringByAppendingPathComponent:[NSString
stringWithFormat:@"%@.zip",
common_group]];
base::FilePath common_group_path(
base::SysNSStringToUTF8([common_group_url path]));
base::FilePath common_group_zip_path(
base::SysNSStringToUTF8(common_group_zip));
zip::ZipWithFilterCallback(common_group_path, common_group_zip_path,
callback);
}
NSString* app_group = app_group::ApplicationGroup();
if ([app_group length]) {
NSURL* app_group_url = [[NSFileManager defaultManager]
containerURLForSecurityApplicationGroupIdentifier:app_group];
NSString* app_group_zip = [dump_directory
stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.zip",
app_group]];
base::FilePath app_group_path(
base::SysNSStringToUTF8([app_group_url path]));
base::FilePath app_group_zip_path(base::SysNSStringToUTF8(app_group_zip));
zip::ZipWithFilterCallback(app_group_path, app_group_zip_path, callback);
}
}