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)resetDefaultHandlerIDForTesting; |
| 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 // For users who have not made an explicit choice (kMailtoDefaultHandlerKey |
| 48 // not set), if Gmail is detected, make an explicit choice for the user to |
| 49 // use Gmail app as the default mailto: handler. |
| 50 - (void)autoDefaultToGmailIfInstalled; |
| 51 |
| 52 @end |
| 53 |
| 54 @implementation MailtoURLRewriter |
| 55 @synthesize handlers = _handlers; |
| 56 |
| 57 + (NSString*)systemMailApp { |
| 58 // This is the App Store ID for Apple Mail app. |
| 59 // See https://itunes.apple.com/us/app/mail/id1108187098?mt=8 |
| 60 return @"1108187098"; |
| 61 } |
| 62 |
| 63 - (instancetype)init { |
| 64 self = [super init]; |
| 65 if (self) { |
| 66 _handlers = [NSMutableDictionary dictionary]; |
| 67 } |
| 68 return self; |
| 69 } |
| 70 |
| 71 - (instancetype)initWithStandardHandlers { |
| 72 self = [self init]; |
| 73 if (self) { |
| 74 [self addMailtoApps:@[ |
| 75 [[MailtoHandlerSystemMail alloc] init], [[MailtoHandlerGmail alloc] init] |
| 76 ]]; |
| 77 } |
| 78 return self; |
| 79 } |
| 80 |
| 81 - (NSArray<MailtoHandler*>*)defaultHandlers { |
| 82 return [_handlers allValues]; |
| 83 } |
| 84 |
| 85 - (NSString*)defaultHandlerID { |
| 86 NSString* value = [[NSUserDefaults standardUserDefaults] |
| 87 stringForKey:kMailtoDefaultHandlerKey]; |
| 88 return value ? value : [[self class] systemMailApp]; |
| 89 } |
| 90 |
| 91 - (void)setDefaultHandlerID:(NSString*)appStoreID { |
| 92 DCHECK([appStoreID length]); |
| 93 [[NSUserDefaults standardUserDefaults] setObject:appStoreID |
| 94 forKey:kMailtoDefaultHandlerKey]; |
| 95 } |
| 96 |
| 97 - (NSString*)rewriteMailtoURL:(const GURL&)gURL { |
| 98 NSString* value = [self defaultHandlerID]; |
| 99 if ([value length]) { |
| 100 MailtoHandler* handler = _handlers[value]; |
| 101 if (handler) { |
| 102 return [handler rewriteMailtoURL:gURL]; |
| 103 } |
| 104 } |
| 105 return nil; |
| 106 } |
| 107 |
| 108 #pragma mark - Private |
| 109 |
| 110 + (void)resetDefaultHandlerIDForTesting { |
| 111 [[NSUserDefaults standardUserDefaults] |
| 112 removeObjectForKey:kMailtoDefaultHandlerKey]; |
| 113 } |
| 114 |
| 115 - (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps { |
| 116 for (MailtoHandler* app in handlerApps) { |
| 117 if ([app isAvailable]) |
| 118 [_handlers setObject:app forKey:[app appStoreID]]; |
| 119 } |
| 120 [self migrateLegacyOptions]; |
| 121 [self autoDefaultToGmailIfInstalled]; |
| 122 } |
| 123 |
| 124 // |
| 125 // Implements the migration logic for users of previous versions of Google |
| 126 // Chrome which supports Google Native App Launcher. The goal is to preserve |
| 127 // the previous behavior and support user choice of non-system provided Mail |
| 128 // client apps. System-provided Mail client app will be referred to as |
| 129 // "System Mail". The migration goals are: |
| 130 // - If a user has not made a choice for preferred mailto: handler in the past, |
| 131 // the behavior after upgrading to this version should not change. |
| 132 // - If a user had disabled Gmail app as the preferred mailto: handler in the |
| 133 // past, System Mail should be selected as the default mailto: handler. |
| 134 // - If a user installs Gmail app after the installation of Chrome, Gmail app |
| 135 // will be chosen as the default mailto: handler, preserving the previous |
| 136 // behavior. |
| 137 // - If a user installs another 3rd party mail client app, assuming that the |
| 138 // 3rd party mail client app is explicitly supported in Chrome, the new 3rd |
| 139 // party mail client app can be set as the default mailto: handler through |
| 140 // Tools > Settings > Content Settings. |
| 141 // |
| 142 // Two NSUserDefaults keys are interpreted with the following meanings: |
| 143 // - kLegacyShouldAutoOpenKey: The existence of this key implies that the user |
| 144 // has used Chrome in the past and had Gmail app installed. Gmail app may or |
| 145 // may not be installed currently. |
| 146 // - kMailtoDefaultHandlerKey: If this key is not set, System Mail app is used |
| 147 // to handle mailto: URLs. If this key is set, the value is a string that is |
| 148 // the key to |_handlers| which maps to a MailtoHandler object. |
| 149 // |
| 150 - (void)migrateLegacyOptions { |
| 151 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| 152 |
| 153 // User previously had a selection made for opening mailto: links with Gmail, |
| 154 // upgrade will set Gmail app to be the default mailto: handler. If user had |
| 155 // opted out to using Gmail app (even when it was installed), migrate user |
| 156 // to use system-provided Mail client. |
| 157 // The key used in NSUserDefaults is from legacy code when Native App |
| 158 // Launcher was still in use. The general format is a string prefix, |
| 159 // underscore, then followed by the App Store ID of the application. |
| 160 NSString* const kGmailAppStoreID = @"422689480"; |
| 161 NSString* const kLegacyShouldAutoOpenKey = |
| 162 [NSString stringWithFormat:@"ShouldAutoOpenLinks_%@", kGmailAppStoreID]; |
| 163 NSNumber* legacyValue = [defaults objectForKey:kLegacyShouldAutoOpenKey]; |
| 164 if (legacyValue) { |
| 165 switch ([legacyValue intValue]) { |
| 166 case 0: |
| 167 case 2: { |
| 168 // If legacy user was using default (kAutoOpenLinksNotSet) or had |
| 169 // explicitly chosen to use Gmail (kAutoOpenLinksYes), migrate to use |
| 170 // Gmail app. |
| 171 MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID]; |
| 172 if ([gmailHandler isAvailable]) |
| 173 [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey]; |
| 174 else |
| 175 [defaults removeObjectForKey:kMailtoDefaultHandlerKey]; |
| 176 break; |
| 177 } |
| 178 case 1: |
| 179 // If legacy user was not using Gmail to handle mailto: links |
| 180 // (kAutoOpenLinksNo), consider this an explicit user choice and |
| 181 // migrate to use system-provided Mail app. |
| 182 [defaults setObject:[[self class] systemMailApp] |
| 183 forKey:kMailtoDefaultHandlerKey]; |
| 184 break; |
| 185 default: |
| 186 NOTREACHED(); |
| 187 break; |
| 188 } |
| 189 [defaults removeObjectForKey:kLegacyShouldAutoOpenKey]; |
| 190 } |
| 191 } |
| 192 |
| 193 - (void)autoDefaultToGmailIfInstalled { |
| 194 NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; |
| 195 // If a default handler for mailto: has already been set, user had made an |
| 196 // explicit choice and no further changes should be done. |
| 197 if ([defaults objectForKey:kMailtoDefaultHandlerKey]) |
| 198 return; |
| 199 |
| 200 NSString* const kGmailAppStoreID = @"422689480"; |
| 201 MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID]; |
| 202 if ([gmailHandler isAvailable]) |
| 203 [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey]; |
| 204 } |
| 205 |
| 206 @end |
OLD | NEW |