OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/shell_integration.h" | |
6 | |
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" | |
12 | |
13 ShellIntegration::DefaultWebClientSetPermission | |
14 ShellIntegration::CanSetAsDefaultBrowser() { | |
15 if (chrome::VersionInfo::GetChannel() != | |
16 chrome::VersionInfo::CHANNEL_CANARY) { | |
17 return SET_DEFAULT_UNATTENDED; | |
18 } | |
19 | |
20 return SET_DEFAULT_NOT_ALLOWED; | |
21 } | |
22 | |
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) | |
28 return false; | |
29 | |
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]; | |
33 if (!identifier) | |
34 return false; | |
35 | |
36 [[NSWorkspace sharedWorkspace] setDefaultBrowserWithIdentifier:identifier]; | |
37 return true; | |
38 } | |
39 | |
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) { | |
44 if (protocol.empty()) | |
45 return false; | |
46 | |
47 if (CanSetAsDefaultProtocolClient() != SET_DEFAULT_UNATTENDED) | |
48 return false; | |
49 | |
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]; | |
53 if (!identifier) | |
54 return false; | |
55 | |
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; | |
61 } | |
62 | |
63 namespace { | |
64 | |
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]; | |
69 if (!default_browser) | |
70 return false; | |
71 | |
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; | |
77 } | |
78 | |
79 // Returns true if |identifier| is the bundle id of the default client | |
80 // application for the given protocol. | |
81 bool IsIdentifierDefaultProtocolClient(NSString* identifier, | |
82 NSString* protocol) { | |
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)); | |
87 if (!default_client) | |
88 return false; | |
89 | |
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; | |
95 } | |
96 | |
97 } // namespace | |
98 | |
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]; | |
107 if (!my_identifier) | |
108 return UNKNOWN_DEFAULT; | |
109 | |
110 return IsIdentifierDefaultBrowser(my_identifier) ? IS_DEFAULT : NOT_DEFAULT; | |
111 } | |
112 | |
113 // Returns true if Firefox is the default browser for the current user. | |
114 bool ShellIntegration::IsFirefoxDefaultBrowser() { | |
115 return IsIdentifierDefaultBrowser(@"org.mozilla.firefox"); | |
116 } | |
117 | |
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; | |
124 | |
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]; | |
128 if (!my_identifier) | |
129 return UNKNOWN_DEFAULT; | |
130 | |
131 NSString* protocol_ns = [NSString stringWithUTF8String:protocol.c_str()]; | |
132 return IsIdentifierDefaultProtocolClient(my_identifier, protocol_ns) ? | |
133 IS_DEFAULT : NOT_DEFAULT; | |
134 } | |
OLD | NEW |