OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 #import "ios/chrome/browser/web/mailto_url_rewriter.h" | |
6 | |
7 #import "base/logging.h" | |
8 #import "ios/chrome/browser/web/mailto_handler.h" | |
9 #import "ios/chrome/browser/web/mailto_handler_gmail.h" | |
10 #import "ios/chrome/browser/web/mailto_handler_system_mail.h" | |
11 | |
12 #import <UIKit/UIKit.h> | |
13 | |
14 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
15 #error "This file requires ARC support." | |
16 #endif | |
17 | |
18 namespace { | |
19 // The key for NSUserDefaults to store the Mail client selected to handle | |
20 // mailto: URL scheme. If this key is not set, user has not made an explicit | |
21 // choice for default mailto: handler and system-provided Mail client app will | |
22 // be used. | |
23 NSString* const kMailtoDefaultHandlerKey = @"MailtoHandlerDefault"; | |
24 } // namespace | |
25 | |
26 @interface MailtoURLRewriter () | |
27 | |
28 // Dictionary keyed by the App Store ID of the Mail client and the value is | |
29 // the MailtoHandler object that can rewrite a mailto: URL. | |
30 @property(nonatomic, strong) | |
31 NSMutableDictionary<NSString*, MailtoHandler*>* handlers; | |
32 | |
33 // Private method for testing to clear the default state. | |
34 + (void)resetDefaultHandlerID; | |
35 | |
36 // Private method to add one or more |handlerApp| objects to the list of known | |
37 // Mail client apps. | |
38 - (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps; | |
39 | |
40 // Custom logic to handle the migration from Google Native App Launcher options | |
41 // to this simplified mailto: URL only system. This must be called after | |
42 // -addMailtoApp: has been called to add all the known Mail client apps. | |
43 // TODO(crbug.com/718601): At some point in the future when almost all users | |
44 // have upgraded, this method can be removed. | |
45 - (void)migrateLegacyOptions; | |
46 | |
47 @end | |
48 | |
49 @implementation MailtoURLRewriter | |
50 @synthesize handlers = _handlers; | |
51 | |
52 + (NSString*)systemMailApp { | |
53 // This is the App Store ID for Apple Mail app. | |
54 // See https://itunes.apple.com/us/app/mail/id1108187098?mt=8 | |
55 return @"1108187098"; | |
56 } | |
57 | |
58 - (instancetype)init { | |
59 self = [super init]; | |
60 if (self) { | |
61 _handlers = [NSMutableDictionary dictionary]; | |
62 } | |
63 return self; | |
64 } | |
65 | |
66 - (instancetype)initWithStandardHandlers { | |
67 self = [self init]; | |
68 if (self) { | |
69 [self addMailtoApps:@[ | |
70 [[MailtoHandlerSystemMail alloc] init], [[MailtoHandlerGmail alloc] init] | |
71 ]]; | |
72 } | |
73 return self; | |
74 } | |
75 | |
76 - (NSArray<MailtoHandler*>*)defaultHandlers { | |
77 return [_handlers allValues]; | |
78 } | |
79 | |
80 - (NSString*)defaultHandlerID { | |
81 NSString* value = [[NSUserDefaults standardUserDefaults] | |
82 stringForKey:kMailtoDefaultHandlerKey]; | |
83 return value ? value : [[self class] systemMailApp]; | |
84 } | |
85 | |
86 - (void)setDefaultHandlerID:(NSString*)appStoreID { | |
87 DCHECK([appStoreID length]); | |
88 [[NSUserDefaults standardUserDefaults] setObject:appStoreID | |
89 forKey:kMailtoDefaultHandlerKey]; | |
90 } | |
91 | |
92 - (NSString*)rewriteMailtoURL:(const GURL&)gURL { | |
93 NSString* value = [self defaultHandlerID]; | |
94 if ([value length]) { | |
95 MailtoHandler* handler = _handlers[value]; | |
96 if (handler) { | |
97 return [handler rewriteMailtoURL:gURL]; | |
98 } | |
99 } | |
100 return nil; | |
101 } | |
102 | |
103 #pragma mark - Private | |
104 | |
105 + (void)resetDefaultHandlerID { | |
rohitrao (ping after 24h)
2017/05/10 00:09:18
What code will call this function and reset the ha
pkl (ping after 24h if needed)
2017/05/10 01:04:14
No. This is only used by unit tests. I renamed it
| |
106 [[NSUserDefaults standardUserDefaults] | |
107 removeObjectForKey:kMailtoDefaultHandlerKey]; | |
108 } | |
109 | |
110 - (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps { | |
111 for (MailtoHandler* app in handlerApps) { | |
112 if ([app isAvailable]) | |
113 [_handlers setObject:app forKey:[app appStoreID]]; | |
114 } | |
115 [self migrateLegacyOptions]; | |
116 } | |
117 | |
118 // | |
119 // Implements the migration logic for users of previous versions of Google | |
120 // Chrome which supports Google Native App Launcher. The goal is to preserve | |
121 // the previous behavior and support user choice of non-system provided Mail | |
122 // client apps. System-provided Mail client app will be referred to as | |
123 // "System Mail". The migration goals are: | |
124 // - If a user has not made a choice for preferred mailto: handler in the past, | |
125 // the behavior after upgrading to this version should not change. | |
126 // - If a user had disabled Gmail app as the preferred mailto: handler in the | |
127 // past, System Mail should be selected as the default mailto: handler. | |
128 // - If a user installs Gmail app after the installation of Chrome, Gmail app | |
129 // will be chosen as the default mailto: handler, preserving the previous | |
130 // behavior. | |
131 // - If a user installs another 3rd party mail client app, assuming that the | |
132 // 3rd party mail client app is explicitly supported in Chrome, the new 3rd | |
133 // party mail client app can be set as the default mailto: handler through | |
134 // Tools > Settings > Content Settings. | |
135 // | |
136 // Two NSUserDefaults keys are interpreted with the following meanings: | |
137 // - kLegacyShouldAutoOpenKey: The existence of this key implies that the user | |
138 // has used Chrome in the past and had Gmail app installed. Gmail app may or | |
139 // may not be installed currently. | |
140 // - kMailtoDefaultHandlerKey: If this key is not set, System Mail app is used | |
141 // to handle mailto: URLs. If this key is set, the value is a string that is | |
142 // the key to |_handlers| which maps to a MailtoHandler object. | |
143 // | |
144 - (void)migrateLegacyOptions { | |
145 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; | |
146 | |
147 // User previously had a selection made for opening mailto: links with Gmail, | |
148 // upgrade will set Gmail app to be the default mailto: handler. If user had | |
149 // opted out to using Gmail app (even when it was installed), migrate user | |
150 // to use system-provided Mail client. | |
151 // The key used in NSUserDefaults is from legacy code when Native App | |
152 // Launcher was still in use. The general format is a string prefix, | |
153 // underscore, then followed by the App Store ID of the application. | |
154 NSString* const kGmailAppStoreID = @"422689480"; | |
155 NSString* const kLegacyShouldAutoOpenKey = | |
156 [NSString stringWithFormat:@"ShouldAutoOpenLinks_%@", kGmailAppStoreID]; | |
157 NSNumber* legacyValue = [defaults objectForKey:kLegacyShouldAutoOpenKey]; | |
158 if (legacyValue) { | |
159 switch ([legacyValue intValue]) { | |
160 case 0: | |
161 case 2: { | |
162 // If legacy user was using default (kAutoOpenLinksNotSet) or had | |
163 // explicitly chosen to use Gmail (kAutoOpenLinksYes), migrate to use | |
164 // Gmail app. | |
165 MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID]; | |
166 if ([gmailHandler isAvailable]) | |
167 [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey]; | |
168 else | |
169 [defaults removeObjectForKey:kMailtoDefaultHandlerKey]; | |
170 break; | |
171 } | |
172 case 1: | |
173 // If legacy user was not using Gmail to handle mailto: links | |
174 // (kAutoOpenLinksNo), migrate to use system-provided Mail app. | |
175 [defaults removeObjectForKey:kMailtoDefaultHandlerKey]; | |
176 break; | |
177 default: | |
178 NOTREACHED(); | |
179 break; | |
180 } | |
181 [defaults removeObjectForKey:kLegacyShouldAutoOpenKey]; | |
182 return; | |
183 } | |
184 | |
185 // If a default handler for mailto: has already been registered, this means | |
rohitrao (ping after 24h)
2017/05/10 00:09:18
The rest of this function after this line isn't re
pkl (ping after 24h if needed)
2017/05/10 01:04:14
Done.
| |
186 // that user had made a choice and no further migration should be done. | |
187 if ([defaults objectForKey:kMailtoDefaultHandlerKey]) | |
188 return; | |
189 | |
190 // For users who have not made an explict choice (kMailtoDefaultHandlerKey | |
rohitrao (ping after 24h)
2017/05/09 23:52:20
Typo: explicit.
rohitrao (ping after 24h)
2017/05/09 23:52:21
The absence of kMailtoDefaultHandlerKey could happ
pkl (ping after 24h if needed)
2017/05/10 00:02:19
From Settings UI, user can set Mail app as the han
pkl (ping after 24h if needed)
2017/05/10 00:02:19
Yes, will fix that.
| |
191 // not set), if Gmail is detected, make an explicit choice for the user to | |
rohitrao (ping after 24h)
2017/05/09 23:52:20
If I choose to use system mail, then later install
pkl (ping after 24h if needed)
2017/05/10 00:02:19
If user has made a choice, this migration code wil
| |
192 // use Gmail app as the default mailto: handler. | |
193 MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID]; | |
194 if ([gmailHandler isAvailable]) | |
195 [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey]; | |
196 } | |
197 | |
198 @end | |
OLD | NEW |