blob: 288453b69676f75551afac1fed63daa5413c21da [file] [log] [blame]
// Copyright 2017 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 "components/crash/core/common/crash_key.h"
#include <dispatch/dispatch.h>
#include "base/strings/sys_string_conversions.h"
#include "components/crash/core/common/crash_key_base_support.h"
#import "third_party/breakpad/breakpad/src/client/ios/Breakpad.h"
#import "third_party/breakpad/breakpad/src/client/ios/BreakpadController.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// The iOS Breakpad implementation internally uses a LongStringDictionary,
// which performs the same chunking done by crash_key_breakpad.cc. This class
// implementation therefore just wraps the iOS Breakpad interface.
namespace crash_reporter {
namespace internal {
namespace {
// Accessing the BreakpadRef is done on an async queue, so serialize the
// access to the current thread, as the CrashKeyString API is sync. This
// matches //ios/chrome/browser/crash_report/breakpad_helper.mm.
void WithBreakpadRefSync(void (^block)(BreakpadRef ref)) {
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
[[BreakpadController sharedInstance] withBreakpadRef:^(BreakpadRef ref) {
block(ref);
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
} // namespace
void CrashKeyStringImpl::Set(base::StringPiece value) {
NSString* key = base::SysUTF8ToNSString(name_);
NSString* value_ns = base::SysUTF8ToNSString(value.as_string());
WithBreakpadRefSync(^(BreakpadRef ref) {
BreakpadAddUploadParameter(ref, key, value_ns);
});
}
void CrashKeyStringImpl::Clear() {
NSString* key = base::SysUTF8ToNSString(name_);
WithBreakpadRefSync(^(BreakpadRef ref) {
BreakpadRemoveUploadParameter(ref, key);
});
}
bool CrashKeyStringImpl::is_set() const {
__block bool is_set = false;
NSString* key = base::SysUTF8ToNSString(
std::string(BREAKPAD_SERVER_PARAMETER_PREFIX) + name_);
WithBreakpadRefSync(^(BreakpadRef ref) {
is_set = BreakpadKeyValue(ref, key) != nil;
});
return is_set;
}
} // namespace internal
void InitializeCrashKeys() {
InitializeCrashKeyBaseSupport();
}
std::string GetCrashKeyValue(const std::string& key_name) {
__block NSString* value;
NSString* key = base::SysUTF8ToNSString(
std::string(BREAKPAD_SERVER_PARAMETER_PREFIX) + key_name);
internal::WithBreakpadRefSync(^(BreakpadRef ref) {
value = BreakpadKeyValue(ref, key);
});
return base::SysNSStringToUTF8(value);
}
void ResetCrashKeysForTesting() {
// There's no way to do this on iOS without tearing down the
// BreakpadController.
}
} // namespace crash_reporter