1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/shell_integration.h"
7 #include "base/mac/bundle_locations.h"
8 #include "base/mac/mac_util.h"
9 #include "base/mac/foundation_util.h"
10 #include "chrome/common/chrome_version_info.h"
11 #import "third_party/mozilla/NSWorkspace+Utils.h"
13 ShellIntegration::DefaultWebClientSetPermission
14 ShellIntegration::CanSetAsDefaultBrowser() {
15 if (chrome::VersionInfo::GetChannel() !=
16 chrome::VersionInfo::CHANNEL_CANARY) {
17 return SET_DEFAULT_UNATTENDED;
20 return SET_DEFAULT_NOT_ALLOWED;
23 // Sets Chromium as default browser to be used by the operating system. This
24 // applies only for the current user. Returns false if this cannot be done, or
25 // if the operation fails.
26 bool ShellIntegration::SetAsDefaultBrowser() {
27 if (CanSetAsDefaultBrowser() != SET_DEFAULT_UNATTENDED)
30 // We really do want the outer bundle here, not the main bundle since setting
31 // a shortcut to Chrome as the default browser doesn't make sense.
32 NSString* identifier = [base::mac::OuterBundle() bundleIdentifier];
36 [[NSWorkspace sharedWorkspace] setDefaultBrowserWithIdentifier:identifier];
40 // Sets Chromium as the default application to be used by the operating system
41 // for the given protocol. This applies only for the current user. Returns false
42 // if this cannot be done, or if the operation fails.
43 bool ShellIntegration::SetAsDefaultProtocolClient(const std::string& protocol) {
47 if (CanSetAsDefaultProtocolClient() != SET_DEFAULT_UNATTENDED)
50 // We really do want the main bundle here since it makes sense to set an
51 // app shortcut as a default protocol handler.
52 NSString* identifier = [base::mac::MainBundle() bundleIdentifier];
56 NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()];
57 OSStatus return_code =
58 LSSetDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol_ns),
59 base::mac::NSToCFCast(identifier));
60 return return_code == noErr;
65 // Returns true if |identifier| is the bundle id of the default browser.
66 bool IsIdentifierDefaultBrowser(NSString* identifier) {
67 NSString* default_browser =
68 [[NSWorkspace sharedWorkspace] defaultBrowserIdentifier];
72 // We need to ensure we do the comparison case-insensitive as LS doesn't
73 // persist the case of our bundle id.
74 NSComparisonResult result =
75 [default_browser caseInsensitiveCompare:identifier];
76 return result == NSOrderedSame;
79 // Returns true if |identifier| is the bundle id of the default client
80 // application for the given protocol.
81 bool IsIdentifierDefaultProtocolClient(NSString* identifier,
83 CFStringRef default_client_cf =
84 LSCopyDefaultHandlerForURLScheme(base::mac::NSToCFCast(protocol));
85 NSString* default_client = static_cast<NSString*>(
86 base::mac::CFTypeRefToNSObjectAutorelease(default_client_cf));
90 // We need to ensure we do the comparison case-insensitive as LS doesn't
91 // persist the case of our bundle id.
92 NSComparisonResult result =
93 [default_client caseInsensitiveCompare:identifier];
94 return result == NSOrderedSame;
99 // Attempt to determine if this instance of Chrome is the default browser and
100 // return the appropriate state. (Defined as being the handler for HTTP/HTTPS
101 // protocols; we don't want to report "no" here if the user has simply chosen
102 // to open HTML files in a text editor and FTP links with an FTP client.)
103 ShellIntegration::DefaultWebClientState ShellIntegration::GetDefaultBrowser() {
104 // We really do want the outer bundle here, since this we want to know the
105 // status of the main Chrome bundle and not a shortcut.
106 NSString* my_identifier = [base::mac::OuterBundle() bundleIdentifier];
108 return UNKNOWN_DEFAULT;
110 return IsIdentifierDefaultBrowser(my_identifier) ? IS_DEFAULT : NOT_DEFAULT;
113 // Returns true if Firefox is the default browser for the current user.
114 bool ShellIntegration::IsFirefoxDefaultBrowser() {
115 return IsIdentifierDefaultBrowser(@"org.mozilla.firefox");
118 // Attempt to determine if this instance of Chrome is the default client
119 // application for the given protocol and return the appropriate state.
120 ShellIntegration::DefaultWebClientState
121 ShellIntegration::IsDefaultProtocolClient(const std::string& protocol) {
122 if (protocol.empty())
123 return UNKNOWN_DEFAULT;
125 // We really do want the main bundle here since it makes sense to set an
126 // app shortcut as a default protocol handler.
127 NSString* my_identifier = [base::mac::MainBundle() bundleIdentifier];
129 return UNKNOWN_DEFAULT;
131 NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()];
132 return IsIdentifierDefaultProtocolClient(my_identifier, protocol_ns) ?
133 IS_DEFAULT : NOT_DEFAULT;