| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "components/crash/app/breakpad_mac.h" | 5 #import "components/crash/app/breakpad_mac.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
| 8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
| 9 | 9 |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| 11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
| 12 #import "base/basictypes.h" | 12 #import "base/basictypes.h" |
| 13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
| 14 #include "base/debug/crash_logging.h" | 14 #include "base/debug/crash_logging.h" |
| 15 #include "base/debug/dump_without_crashing.h" | 15 #include "base/debug/dump_without_crashing.h" |
| 16 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
| 17 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 18 #import "base/logging.h" | 18 #import "base/logging.h" |
| 19 #include "base/mac/bundle_locations.h" | 19 #include "base/mac/bundle_locations.h" |
| 20 #include "base/mac/mac_util.h" | 20 #include "base/mac/mac_util.h" |
| 21 #include "base/mac/scoped_cftyperef.h" | 21 #include "base/mac/scoped_cftyperef.h" |
| 22 #import "base/mac/scoped_nsautorelease_pool.h" | 22 #import "base/mac/scoped_nsautorelease_pool.h" |
| 23 #include "base/strings/sys_string_conversions.h" | 23 #include "base/strings/sys_string_conversions.h" |
| 24 #include "base/threading/platform_thread.h" | 24 #include "base/threading/platform_thread.h" |
| 25 #include "base/threading/thread_restrictions.h" | 25 #include "base/threading/thread_restrictions.h" |
| 26 #import "breakpad/src/client/mac/Framework/Breakpad.h" | 26 #import "breakpad/src/client/mac/Framework/Breakpad.h" |
| 27 #include "components/crash/app/breakpad_client.h" | 27 #include "components/crash/app/crash_reporter_client.h" |
| 28 |
| 29 using crash_reporter::GetCrashReporterClient; |
| 28 | 30 |
| 29 namespace breakpad { | 31 namespace breakpad { |
| 30 | 32 |
| 31 namespace { | 33 namespace { |
| 32 | 34 |
| 33 BreakpadRef gBreakpadRef = NULL; | 35 BreakpadRef gBreakpadRef = NULL; |
| 34 | 36 |
| 35 void SetCrashKeyValue(NSString* key, NSString* value) { | 37 void SetCrashKeyValue(NSString* key, NSString* value) { |
| 36 // Comment repeated from header to prevent confusion: | 38 // Comment repeated from header to prevent confusion: |
| 37 // IMPORTANT: On OS X, the key/value pairs are sent to the crash server | 39 // IMPORTANT: On OS X, the key/value pairs are sent to the crash server |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 // the browser process, so the browser passes the decision to them on the | 161 // the browser process, so the browser passes the decision to them on the |
| 160 // command line. | 162 // command line. |
| 161 NSBundle* main_bundle = base::mac::FrameworkBundle(); | 163 NSBundle* main_bundle = base::mac::FrameworkBundle(); |
| 162 bool is_browser = !base::mac::IsBackgroundOnlyProcess(); | 164 bool is_browser = !base::mac::IsBackgroundOnlyProcess(); |
| 163 bool enable_breakpad = false; | 165 bool enable_breakpad = false; |
| 164 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 166 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
| 165 | 167 |
| 166 if (is_browser) { | 168 if (is_browser) { |
| 167 // Since the configuration management infrastructure is possibly not | 169 // Since the configuration management infrastructure is possibly not |
| 168 // initialized when this code runs, read the policy preference directly. | 170 // initialized when this code runs, read the policy preference directly. |
| 169 if (!GetBreakpadClient()->ReportingIsEnforcedByPolicy(&enable_breakpad)) { | 171 if (!GetCrashReporterClient()->ReportingIsEnforcedByPolicy( |
| 172 &enable_breakpad)) { |
| 170 // Controlled by the user. The crash reporter may be enabled by | 173 // Controlled by the user. The crash reporter may be enabled by |
| 171 // preference or through an environment variable, but the kDisableBreakpad | 174 // preference or through an environment variable, but the kDisableBreakpad |
| 172 // switch overrides both. | 175 // switch overrides both. |
| 173 enable_breakpad = GetBreakpadClient()->GetCollectStatsConsent() || | 176 enable_breakpad = GetCrashReporterClient()->GetCollectStatsConsent() || |
| 174 GetBreakpadClient()->IsRunningUnattended(); | 177 GetCrashReporterClient()->IsRunningUnattended(); |
| 175 enable_breakpad &= !command_line->HasSwitch(switches::kDisableBreakpad); | 178 enable_breakpad &= !command_line->HasSwitch(switches::kDisableBreakpad); |
| 176 } | 179 } |
| 177 } else { | 180 } else { |
| 178 // This is a helper process, check the command line switch. | 181 // This is a helper process, check the command line switch. |
| 179 enable_breakpad = command_line->HasSwitch(switches::kEnableCrashReporter); | 182 enable_breakpad = command_line->HasSwitch(switches::kEnableCrashReporter); |
| 180 } | 183 } |
| 181 | 184 |
| 182 if (!enable_breakpad) { | 185 if (!enable_breakpad) { |
| 183 VLOG_IF(1, is_browser) << "Breakpad disabled"; | 186 VLOG_IF(1, is_browser) << "Breakpad disabled"; |
| 184 return; | 187 return; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 207 forKey:@BREAKPAD_REPORTER_EXE_LOCATION]; | 210 forKey:@BREAKPAD_REPORTER_EXE_LOCATION]; |
| 208 | 211 |
| 209 // In the main application (the browser process), crashes can be passed to | 212 // In the main application (the browser process), crashes can be passed to |
| 210 // the system's Crash Reporter. This allows the system to notify the user | 213 // the system's Crash Reporter. This allows the system to notify the user |
| 211 // when the application crashes, and provide the user with the option to | 214 // when the application crashes, and provide the user with the option to |
| 212 // restart it. | 215 // restart it. |
| 213 if (is_browser) | 216 if (is_browser) |
| 214 [breakpad_config setObject:@"NO" forKey:@BREAKPAD_SEND_AND_EXIT]; | 217 [breakpad_config setObject:@"NO" forKey:@BREAKPAD_SEND_AND_EXIT]; |
| 215 | 218 |
| 216 base::FilePath dir_crash_dumps; | 219 base::FilePath dir_crash_dumps; |
| 217 GetBreakpadClient()->GetCrashDumpLocation(&dir_crash_dumps); | 220 GetCrashReporterClient()->GetCrashDumpLocation(&dir_crash_dumps); |
| 218 [breakpad_config setObject:base::SysUTF8ToNSString(dir_crash_dumps.value()) | 221 [breakpad_config setObject:base::SysUTF8ToNSString(dir_crash_dumps.value()) |
| 219 forKey:@BREAKPAD_DUMP_DIRECTORY]; | 222 forKey:@BREAKPAD_DUMP_DIRECTORY]; |
| 220 | 223 |
| 221 // Temporarily run Breakpad in-process on 10.10 and later because APIs that | 224 // Temporarily run Breakpad in-process on 10.10 and later because APIs that |
| 222 // it depends on got broken (http://crbug.com/386208). | 225 // it depends on got broken (http://crbug.com/386208). |
| 223 // This can catch crashes in the browser process only. | 226 // This can catch crashes in the browser process only. |
| 224 if (is_browser && base::mac::IsOSYosemiteOrLater()) { | 227 if (is_browser && base::mac::IsOSYosemiteOrLater()) { |
| 225 [breakpad_config setObject:[NSNumber numberWithBool:YES] | 228 [breakpad_config setObject:[NSNumber numberWithBool:YES] |
| 226 forKey:@BREAKPAD_IN_PROCESS]; | 229 forKey:@BREAKPAD_IN_PROCESS]; |
| 227 } | 230 } |
| 228 | 231 |
| 229 // Initialize Breakpad. | 232 // Initialize Breakpad. |
| 230 gBreakpadRef = BreakpadCreate(breakpad_config); | 233 gBreakpadRef = BreakpadCreate(breakpad_config); |
| 231 if (!gBreakpadRef) { | 234 if (!gBreakpadRef) { |
| 232 LOG_IF(ERROR, base::mac::AmIBundled()) << "Breakpad initializaiton failed"; | 235 LOG_IF(ERROR, base::mac::AmIBundled()) << "Breakpad initializaiton failed"; |
| 233 return; | 236 return; |
| 234 } | 237 } |
| 235 | 238 |
| 236 // Initialize the scoped crash key system. | 239 // Initialize the scoped crash key system. |
| 237 base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValueImpl, | 240 base::debug::SetCrashKeyReportingFunctions(&SetCrashKeyValueImpl, |
| 238 &ClearCrashKeyValueImpl); | 241 &ClearCrashKeyValueImpl); |
| 239 GetBreakpadClient()->RegisterCrashKeys(); | 242 GetCrashReporterClient()->RegisterCrashKeys(); |
| 240 | 243 |
| 241 // Set Breakpad metadata values. These values are added to Info.plist during | 244 // Set Breakpad metadata values. These values are added to Info.plist during |
| 242 // the branded Google Chrome.app build. | 245 // the branded Google Chrome.app build. |
| 243 SetCrashKeyValue(@"ver", [info_dictionary objectForKey:@BREAKPAD_VERSION]); | 246 SetCrashKeyValue(@"ver", [info_dictionary objectForKey:@BREAKPAD_VERSION]); |
| 244 SetCrashKeyValue(@"prod", [info_dictionary objectForKey:@BREAKPAD_PRODUCT]); | 247 SetCrashKeyValue(@"prod", [info_dictionary objectForKey:@BREAKPAD_PRODUCT]); |
| 245 SetCrashKeyValue(@"plat", @"OS X"); | 248 SetCrashKeyValue(@"plat", @"OS X"); |
| 246 | 249 |
| 247 if (!is_browser) { | 250 if (!is_browser) { |
| 248 // Get the guid from the command line switch. | 251 // Get the guid from the command line switch. |
| 249 std::string client_guid = | 252 std::string client_guid = |
| 250 command_line->GetSwitchValueASCII(switches::kEnableCrashReporter); | 253 command_line->GetSwitchValueASCII(switches::kEnableCrashReporter); |
| 251 GetBreakpadClient()->SetBreakpadClientIdFromGUID(client_guid); | 254 GetCrashReporterClient()->SetCrashReporterClientIdFromGUID(client_guid); |
| 252 } | 255 } |
| 253 | 256 |
| 254 logging::SetLogMessageHandler(&FatalMessageHandler); | 257 logging::SetLogMessageHandler(&FatalMessageHandler); |
| 255 base::debug::SetDumpWithoutCrashingFunction(&DumpHelper::DumpWithoutCrashing); | 258 base::debug::SetDumpWithoutCrashingFunction(&DumpHelper::DumpWithoutCrashing); |
| 256 | 259 |
| 257 // abort() sends SIGABRT, which breakpad does not intercept. | 260 // abort() sends SIGABRT, which breakpad does not intercept. |
| 258 // Register a signal handler to crash in a way breakpad will | 261 // Register a signal handler to crash in a way breakpad will |
| 259 // intercept. | 262 // intercept. |
| 260 struct sigaction sigact; | 263 struct sigaction sigact; |
| 261 memset(&sigact, 0, sizeof(sigact)); | 264 memset(&sigact, 0, sizeof(sigact)); |
| 262 sigact.sa_handler = SIGABRTHandler; | 265 sigact.sa_handler = SIGABRTHandler; |
| 263 CHECK(0 == sigaction(SIGABRT, &sigact, NULL)); | 266 CHECK(0 == sigaction(SIGABRT, &sigact, NULL)); |
| 264 } | 267 } |
| 265 | 268 |
| 266 void InitCrashProcessInfo(const std::string& process_type_switch) { | 269 void InitCrashProcessInfo(const std::string& process_type_switch) { |
| 267 if (gBreakpadRef == NULL) { | 270 if (gBreakpadRef == NULL) { |
| 268 return; | 271 return; |
| 269 } | 272 } |
| 270 | 273 |
| 271 // Determine the process type. | 274 // Determine the process type. |
| 272 NSString* process_type = @"browser"; | 275 NSString* process_type = @"browser"; |
| 273 if (!process_type_switch.empty()) { | 276 if (!process_type_switch.empty()) { |
| 274 process_type = base::SysUTF8ToNSString(process_type_switch); | 277 process_type = base::SysUTF8ToNSString(process_type_switch); |
| 275 } | 278 } |
| 276 | 279 |
| 277 GetBreakpadClient()->InstallAdditionalFilters(gBreakpadRef); | 280 GetCrashReporterClient()->InstallAdditionalFilters(gBreakpadRef); |
| 278 | 281 |
| 279 // Store process type in crash dump. | 282 // Store process type in crash dump. |
| 280 SetCrashKeyValue(@"ptype", process_type); | 283 SetCrashKeyValue(@"ptype", process_type); |
| 281 | 284 |
| 282 NSString* pid_value = | 285 NSString* pid_value = |
| 283 [NSString stringWithFormat:@"%d", static_cast<unsigned int>(getpid())]; | 286 [NSString stringWithFormat:@"%d", static_cast<unsigned int>(getpid())]; |
| 284 SetCrashKeyValue(@"pid", pid_value); | 287 SetCrashKeyValue(@"pid", pid_value); |
| 285 } | 288 } |
| 286 | 289 |
| 287 } // namespace breakpad | 290 } // namespace breakpad |
| OLD | NEW |