From c8ff24d91332764f5f6deb66f428f18cdfd32fd3 Mon Sep 17 00:00:00 2001 From: sdefresne Date: Thu, 23 Apr 2015 09:35:13 -0700 Subject: [PATCH] [iOS] Upstream safe mode utils SafeMode is a feature of Chrome on iOS that attempts to recover from crash loop on startup and provide additional information in crash reports. BUG=429756 Review URL: https://codereview.chromium.org/1098273003 Cr-Commit-Position: refs/heads/master@{#326539} --- ios/chrome/app/DEPS | 3 ++ ios/chrome/app/safe_mode_crashing_modules_config.h | 25 ++++++++++++ .../app/safe_mode_crashing_modules_config.mm | 42 ++++++++++++++++++++ ios/chrome/app/safe_mode_util.cc | 23 +++++++++++ ios/chrome/app/safe_mode_util.h | 21 ++++++++++ ios/chrome/app/safe_mode_util_unittest.cc | 46 ++++++++++++++++++++++ ios/chrome/ios_chrome.gyp | 21 ++++++++++ ios/chrome/ios_chrome_tests.gyp | 2 + 8 files changed, 183 insertions(+) create mode 100644 ios/chrome/app/DEPS create mode 100644 ios/chrome/app/safe_mode_crashing_modules_config.h create mode 100644 ios/chrome/app/safe_mode_crashing_modules_config.mm create mode 100644 ios/chrome/app/safe_mode_util.cc create mode 100644 ios/chrome/app/safe_mode_util.h create mode 100644 ios/chrome/app/safe_mode_util_unittest.cc diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS new file mode 100644 index 000000000000..9074a78c1d67 --- /dev/null +++ b/ios/chrome/app/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+ios/chrome/browser", +] diff --git a/ios/chrome/app/safe_mode_crashing_modules_config.h b/ios/chrome/app/safe_mode_crashing_modules_config.h new file mode 100644 index 000000000000..d918edcc213d --- /dev/null +++ b/ios/chrome/app/safe_mode_crashing_modules_config.h @@ -0,0 +1,25 @@ +// Copyright 2013 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. + +#ifndef IOS_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_ +#define IOS_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_ + +#import + +#import "ios/chrome/browser/updatable_config/updatable_dictionary.h" + +// Class for updatable configuration file singleton. This singleton object +// is created when +sharedInstance is called for the first time and the default +// configuration is loaded from a plist bundled into the application. +@interface SafeModeCrashingModulesConfig : UpdatableDictionary + +// Returns singleton object for this class. ++ (SafeModeCrashingModulesConfig*)sharedInstance; + +// Return friendly name of module if module is a known crasher. +- (NSString*)startupCrashModuleFriendlyName:(NSString*)modulePath; + +@end + +#endif // IOS_CHROME_APP_SAFE_MODE_CRASHING_MODULES_CONFIG_H_ diff --git a/ios/chrome/app/safe_mode_crashing_modules_config.mm b/ios/chrome/app/safe_mode_crashing_modules_config.mm new file mode 100644 index 000000000000..7dd5e90f67d8 --- /dev/null +++ b/ios/chrome/app/safe_mode_crashing_modules_config.mm @@ -0,0 +1,42 @@ +// Copyright 2013 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/app/safe_mode_crashing_modules_config.h" + +#include "base/logging.h" + +namespace { + +NSString* const kStartupCrashModulesKey = @"StartupCrashModules"; +NSString* const kModuleFriendlyNameKey = @"ModuleFriendlyName"; + +} // namespace + +@implementation SafeModeCrashingModulesConfig + ++ (SafeModeCrashingModulesConfig*)sharedInstance { + static SafeModeCrashingModulesConfig* instance = + [[SafeModeCrashingModulesConfig alloc] init]; + return instance; +} + +- (instancetype)init { + return [super initWithAppId:nil version:nil plist:@"CrashingModules.plist"]; +} + +- (NSString*)startupCrashModuleFriendlyName:(NSString*)modulePath { + NSDictionary* configData = [self dictionaryFromConfig]; + NSDictionary* modules = [configData objectForKey:kStartupCrashModulesKey]; + if (modules) { + DCHECK([modules isKindOfClass:[NSDictionary class]]); + NSDictionary* module = modules[modulePath]; + if (module) { + DCHECK([module isKindOfClass:[NSDictionary class]]); + return module[kModuleFriendlyNameKey]; + } + } + return nil; +} + +@end diff --git a/ios/chrome/app/safe_mode_util.cc b/ios/chrome/app/safe_mode_util.cc new file mode 100644 index 000000000000..be448a450fae --- /dev/null +++ b/ios/chrome/app/safe_mode_util.cc @@ -0,0 +1,23 @@ +// Copyright 2013 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. + +#include "ios/chrome/app/safe_mode_util.h" + +#include + +namespace safe_mode_util { + +std::vector GetLoadedImages(const char* path_filter) { + std::vector images; + uint32_t image_count = _dyld_image_count(); + for (uint32_t i = 0; i < image_count; ++i) { + const char* path = _dyld_get_image_name(i); + if (path_filter && strncmp(path, path_filter, strlen(path_filter)) != 0) + continue; + images.push_back(path); + } + return images; +} + +} // namespace safe_mode_util diff --git a/ios/chrome/app/safe_mode_util.h b/ios/chrome/app/safe_mode_util.h new file mode 100644 index 000000000000..d4e25fd52ac7 --- /dev/null +++ b/ios/chrome/app/safe_mode_util.h @@ -0,0 +1,21 @@ +// Copyright 2013 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. + +#ifndef IOS_CHROME_APP_SAFE_MODE_UTIL_H_ +#define IOS_CHROME_APP_SAFE_MODE_UTIL_H_ + +#include +#include + +namespace safe_mode_util { + +// Returns a list of the paths of all images (e.g., dynamic libraries) +// currently loaded. +// If |path_filter| is non-NULL, only paths starting with |path_filter| will be +// returned. +std::vector GetLoadedImages(const char* path_filter); + +} // namespace safe_mode_util + +#endif // IOS_CHROME_APP_SAFE_MODE_UTIL_H_ diff --git a/ios/chrome/app/safe_mode_util_unittest.cc b/ios/chrome/app/safe_mode_util_unittest.cc new file mode 100644 index 000000000000..3164d59fc7e1 --- /dev/null +++ b/ios/chrome/app/safe_mode_util_unittest.cc @@ -0,0 +1,46 @@ +// Copyright 2013 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. + +#include + +#include "base/files/file_path.h" +#include "base/strings/string_util.h" +#include "ios/chrome/app/safe_mode_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +using std::string; +using std::vector; + +namespace { + +typedef PlatformTest SafeModeUtilTest; + +TEST_F(SafeModeUtilTest, GetAllImages) { + vector images = safe_mode_util::GetLoadedImages(nullptr); + // There should be loaded images. + EXPECT_GT(images.size(), 0U); + + // The libSystem dylib should always be present. + bool found_lib_system = false; + string lib_system_prefix("libSystem"); + for (size_t i = 0; i < images.size(); ++i) { + string base_name = base::FilePath(images[i]).BaseName().value(); + if (StartsWithASCII(base_name, lib_system_prefix, true)) { + found_lib_system = true; + break; + } + } + EXPECT_TRUE(found_lib_system); +} + +TEST_F(SafeModeUtilTest, GetSomeImages) { + vector all_images = safe_mode_util::GetLoadedImages(nullptr); + vector usr_lib_images = safe_mode_util::GetLoadedImages("/usr/lib/"); + // There should be images under /usr/lib/, but not all of them are. + EXPECT_GT(usr_lib_images.size(), 0U); + EXPECT_LT(usr_lib_images.size(), all_images.size()); +} + +} // namespace diff --git a/ios/chrome/ios_chrome.gyp b/ios/chrome/ios_chrome.gyp index dbd68e1ed495..2176a2d8b86c 100644 --- a/ios/chrome/ios_chrome.gyp +++ b/ios/chrome/ios_chrome.gyp @@ -8,6 +8,27 @@ }, 'targets': [ { + 'target_name': 'ios_chrome_app', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'dependencies': [ + 'ios_chrome_browser', + ], + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/Foundation.framework', + ], + }, + 'sources': [ + 'app/safe_mode_crashing_modules_config.h', + 'app/safe_mode_crashing_modules_config.mm', + 'app/safe_mode_util.h', + 'app/safe_mode_util.cc', + ], + }, + { 'target_name': 'ios_chrome_browser', 'type': 'static_library', 'include_dirs': [ diff --git a/ios/chrome/ios_chrome_tests.gyp b/ios/chrome/ios_chrome_tests.gyp index 3af8d8f77961..d1b7aee9b6e7 100644 --- a/ios/chrome/ios_chrome_tests.gyp +++ b/ios/chrome/ios_chrome_tests.gyp @@ -19,11 +19,13 @@ '../ios_tests.gyp:test_support_ios', '../web/ios_web.gyp:ios_web', '../web/ios_web.gyp:test_support_ios_web', + 'ios_chrome.gyp:ios_chrome_app', 'ios_chrome.gyp:ios_chrome_browser', 'ios_chrome.gyp:ios_chrome_common', 'ios_chrome_test_support', ], 'sources': [ + 'app/safe_mode_util_unittest.cc', 'browser/net/image_fetcher_unittest.mm', 'browser/net/metrics_network_client_unittest.mm', 'browser/net/retryable_url_fetcher_unittest.mm', -- 2.11.4.GIT