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 |