Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(120)

Unified Diff: ios/chrome/browser/web/mailto_url_rewriter.mm

Issue 2852003002: Adds mailto: URL support to app launching. (Closed)
Patch Set: separate migration from auto-default even more Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/web/mailto_url_rewriter.mm
diff --git a/ios/chrome/browser/web/mailto_url_rewriter.mm b/ios/chrome/browser/web/mailto_url_rewriter.mm
new file mode 100644
index 0000000000000000000000000000000000000000..f6c00c5cff1bcac1421298cf6d8a5f574e003e73
--- /dev/null
+++ b/ios/chrome/browser/web/mailto_url_rewriter.mm
@@ -0,0 +1,206 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/web/mailto_url_rewriter.h"
+
+#import "base/logging.h"
+#import "ios/chrome/browser/web/mailto_handler.h"
+#import "ios/chrome/browser/web/mailto_handler_gmail.h"
+#import "ios/chrome/browser/web/mailto_handler_system_mail.h"
+
+#import <UIKit/UIKit.h>
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace {
+// The key for NSUserDefaults to store the Mail client selected to handle
+// mailto: URL scheme. If this key is not set, user has not made an explicit
+// choice for default mailto: handler and system-provided Mail client app will
+// be used.
+NSString* const kMailtoDefaultHandlerKey = @"MailtoHandlerDefault";
+} // namespace
+
+@interface MailtoURLRewriter ()
+
+// Dictionary keyed by the App Store ID of the Mail client and the value is
+// the MailtoHandler object that can rewrite a mailto: URL.
+@property(nonatomic, strong)
+ NSMutableDictionary<NSString*, MailtoHandler*>* handlers;
+
+// Private method for testing to clear the default state.
++ (void)resetDefaultHandlerIDForTesting;
+
+// Private method to add one or more |handlerApp| objects to the list of known
+// Mail client apps.
+- (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps;
+
+// Custom logic to handle the migration from Google Native App Launcher options
+// to this simplified mailto: URL only system. This must be called after
+// -addMailtoApp: has been called to add all the known Mail client apps.
+// TODO(crbug.com/718601): At some point in the future when almost all users
+// have upgraded, this method can be removed.
+- (void)migrateLegacyOptions;
+
+// For users who have not made an explicit choice (kMailtoDefaultHandlerKey
+// not set), if Gmail is detected, make an explicit choice for the user to
+// use Gmail app as the default mailto: handler.
+- (void)autoDefaultToGmailIfInstalled;
+
+@end
+
+@implementation MailtoURLRewriter
+@synthesize handlers = _handlers;
+
++ (NSString*)systemMailApp {
+ // This is the App Store ID for Apple Mail app.
+ // See https://itunes.apple.com/us/app/mail/id1108187098?mt=8
+ return @"1108187098";
+}
+
+- (instancetype)init {
+ self = [super init];
+ if (self) {
+ _handlers = [NSMutableDictionary dictionary];
+ }
+ return self;
+}
+
+- (instancetype)initWithStandardHandlers {
+ self = [self init];
+ if (self) {
+ [self addMailtoApps:@[
+ [[MailtoHandlerSystemMail alloc] init], [[MailtoHandlerGmail alloc] init]
+ ]];
+ }
+ return self;
+}
+
+- (NSArray<MailtoHandler*>*)defaultHandlers {
+ return [_handlers allValues];
+}
+
+- (NSString*)defaultHandlerID {
+ NSString* value = [[NSUserDefaults standardUserDefaults]
+ stringForKey:kMailtoDefaultHandlerKey];
+ return value ? value : [[self class] systemMailApp];
+}
+
+- (void)setDefaultHandlerID:(NSString*)appStoreID {
+ DCHECK([appStoreID length]);
+ [[NSUserDefaults standardUserDefaults] setObject:appStoreID
+ forKey:kMailtoDefaultHandlerKey];
+}
+
+- (NSString*)rewriteMailtoURL:(const GURL&)gURL {
+ NSString* value = [self defaultHandlerID];
+ if ([value length]) {
+ MailtoHandler* handler = _handlers[value];
+ if (handler) {
+ return [handler rewriteMailtoURL:gURL];
+ }
+ }
+ return nil;
+}
+
+#pragma mark - Private
+
++ (void)resetDefaultHandlerIDForTesting {
+ [[NSUserDefaults standardUserDefaults]
+ removeObjectForKey:kMailtoDefaultHandlerKey];
+}
+
+- (void)addMailtoApps:(NSArray<MailtoHandler*>*)handlerApps {
+ for (MailtoHandler* app in handlerApps) {
+ if ([app isAvailable])
+ [_handlers setObject:app forKey:[app appStoreID]];
+ }
+ [self migrateLegacyOptions];
+ [self autoDefaultToGmailIfInstalled];
+}
+
+//
+// Implements the migration logic for users of previous versions of Google
+// Chrome which supports Google Native App Launcher. The goal is to preserve
+// the previous behavior and support user choice of non-system provided Mail
+// client apps. System-provided Mail client app will be referred to as
+// "System Mail". The migration goals are:
+// - If a user has not made a choice for preferred mailto: handler in the past,
+// the behavior after upgrading to this version should not change.
+// - If a user had disabled Gmail app as the preferred mailto: handler in the
+// past, System Mail should be selected as the default mailto: handler.
+// - If a user installs Gmail app after the installation of Chrome, Gmail app
+// will be chosen as the default mailto: handler, preserving the previous
+// behavior.
+// - If a user installs another 3rd party mail client app, assuming that the
+// 3rd party mail client app is explicitly supported in Chrome, the new 3rd
+// party mail client app can be set as the default mailto: handler through
+// Tools > Settings > Content Settings.
+//
+// Two NSUserDefaults keys are interpreted with the following meanings:
+// - kLegacyShouldAutoOpenKey: The existence of this key implies that the user
+// has used Chrome in the past and had Gmail app installed. Gmail app may or
+// may not be installed currently.
+// - kMailtoDefaultHandlerKey: If this key is not set, System Mail app is used
+// to handle mailto: URLs. If this key is set, the value is a string that is
+// the key to |_handlers| which maps to a MailtoHandler object.
+//
+- (void)migrateLegacyOptions {
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+
+ // User previously had a selection made for opening mailto: links with Gmail,
+ // upgrade will set Gmail app to be the default mailto: handler. If user had
+ // opted out to using Gmail app (even when it was installed), migrate user
+ // to use system-provided Mail client.
+ // The key used in NSUserDefaults is from legacy code when Native App
+ // Launcher was still in use. The general format is a string prefix,
+ // underscore, then followed by the App Store ID of the application.
+ NSString* const kGmailAppStoreID = @"422689480";
+ NSString* const kLegacyShouldAutoOpenKey =
+ [NSString stringWithFormat:@"ShouldAutoOpenLinks_%@", kGmailAppStoreID];
+ NSNumber* legacyValue = [defaults objectForKey:kLegacyShouldAutoOpenKey];
+ if (legacyValue) {
+ switch ([legacyValue intValue]) {
+ case 0:
+ case 2: {
+ // If legacy user was using default (kAutoOpenLinksNotSet) or had
+ // explicitly chosen to use Gmail (kAutoOpenLinksYes), migrate to use
+ // Gmail app.
+ MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID];
+ if ([gmailHandler isAvailable])
+ [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey];
+ else
+ [defaults removeObjectForKey:kMailtoDefaultHandlerKey];
+ break;
+ }
+ case 1:
+ // If legacy user was not using Gmail to handle mailto: links
+ // (kAutoOpenLinksNo), consider this an explicit user choice and
+ // migrate to use system-provided Mail app.
+ [defaults setObject:[[self class] systemMailApp]
+ forKey:kMailtoDefaultHandlerKey];
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+ [defaults removeObjectForKey:kLegacyShouldAutoOpenKey];
+ }
+}
+
+- (void)autoDefaultToGmailIfInstalled {
+ NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+ // If a default handler for mailto: has already been set, user had made an
+ // explicit choice and no further changes should be done.
+ if ([defaults objectForKey:kMailtoDefaultHandlerKey])
+ return;
+
+ NSString* const kGmailAppStoreID = @"422689480";
+ MailtoHandler* gmailHandler = _handlers[kGmailAppStoreID];
+ if ([gmailHandler isAvailable])
+ [defaults setObject:kGmailAppStoreID forKey:kMailtoDefaultHandlerKey];
+}
+
+@end
« no previous file with comments | « ios/chrome/browser/web/mailto_url_rewriter.h ('k') | ios/chrome/browser/web/mailto_url_rewriter_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698