blob: 5a49e40625fcc196f70ebb0df7ad2fec9cfc0290 [file] [log] [blame]
// Copyright 2016 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/startup/setup_debugging.h"
#include <objc/runtime.h>
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "components/crash/core/common/objc_zombie.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
#if !defined(NDEBUG)
// Swizzles [UIImage imageNamed:] to trigger a DCHECK if an invalid image is
// attempted to be loaded.
void swizzleUIImageImageNamed() {
// Retained by the swizzle block.
NSMutableSet* whiteList = [NSMutableSet set];
// TODO(crbug.com/720337): Add missing image.
[whiteList addObject:@"card_close_button_pressed_incognito"];
// TODO(crbug.com/720355): Add missing image.
[whiteList addObject:@"find_close_pressed_incognito"];
// TODO(crbug.com/720338): Add missing images.
[whiteList addObject:@"glif-mic-to-dots-small_37"];
[whiteList addObject:@"glif-mic-to-dots-large_37"];
[whiteList addObject:@"glif-google-to-dots_28"];
// TODO(crbug.com/721338): Add missing image.
[whiteList addObject:@"voice_icon_keyboard_accessory"];
[whiteList addObject:@"voice_icon"];
// TODO(crbug.com/754032): Add missing image.
[whiteList addObject:@"ios_default_avatar"];
// The original implementation of [UIImage imageNamed:].
// Called by the new implementation.
static IMP originalImp;
IMP* originalImpPtr = &originalImp;
id swizzleBlock = ^(id self, NSString* imageName) {
// Call the original [UIImage imageNamed:] method.
UIImage* (*imp)(id, SEL, id) = (UIImage*(*)(id,SEL,id))*originalImpPtr;
Class aClass = objc_getClass("UIImage");
UIImage* image = imp(aClass, @selector(imageNamed:), imageName);
if (![whiteList containsObject:imageName]) {
DCHECK(image) << "Missing image: " << base::SysNSStringToUTF8(imageName);
}
return image;
};
Method method = class_getClassMethod([UIImage class], @selector(imageNamed:));
DCHECK(method);
IMP blockImp = imp_implementationWithBlock(swizzleBlock);
originalImp = method_setImplementation(method, blockImp);
}
#endif // !defined(NDEBUG) && TARGET_IPHONE_SIMULATOR
} // namespace
@implementation SetupDebugging
+ (void)setUpDebuggingOptions {
// Enable the zombie treadmill on simulator builds.
// TODO(crbug.com/663390): Consider enabling this on device builds too.
#if TARGET_IPHONE_SIMULATOR
DCHECK(ObjcEvilDoers::ZombieEnable(true, 10000));
#endif
#if !defined(NDEBUG)
// Enable the detection of missing image assets.
swizzleUIImageImageNamed();
#endif
}
@end