| 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/widget_extension/widget_view_controller.h" | |
| 6 | |
| 7 #import <NotificationCenter/NotificationCenter.h> | |
| 8 | |
| 9 #include "base/ios/ios_util.h" | |
| 10 #include "base/mac/foundation_util.h" | |
| 11 #include "base/strings/sys_string_conversions.h" | |
| 12 #include "components/open_from_clipboard/clipboard_recent_content_impl_ios.h" | |
| 13 #include "ios/chrome/common/app_group/app_group_constants.h" | |
| 14 #import "ios/chrome/widget_extension/widget_view.h" | |
| 15 | |
| 16 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 17 #error "This file requires ARC support." | |
| 18 #endif | |
| 19 | |
| 20 namespace { | |
| 21 // Using GURL in the extension is not wanted as it includes ICU which makes the | |
| 22 // extension binary much larger; therefore, ios/chrome/common/x_callback_url.h | |
| 23 // cannot be used. This class makes a very basic use of x-callback-url, so no | |
| 24 // full implementation is required. | |
| 25 NSString* const kXCallbackURLHost = @"x-callback-url"; | |
| 26 } // namespace | |
| 27 | |
| 28 @interface WidgetViewController ()<WidgetViewActionTarget> | |
| 29 @property(nonatomic, weak) WidgetView* widgetView; | |
| 30 @property(nonatomic, strong) NSURL* copiedURL; | |
| 31 @property(nonatomic, strong) | |
| 32 ClipboardRecentContentImplIOS* clipboardRecentContent; | |
| 33 | |
| 34 // Updates the widget with latest data from the clipboard. Returns whether any | |
| 35 // visual updates occured. | |
| 36 - (BOOL)updateWidget; | |
| 37 // Opens the main application with the given |command|. | |
| 38 - (void)openAppWithCommand:(NSString*)command; | |
| 39 // Opens the main application with the given |command| and |parameter|. | |
| 40 - (void)openAppWithCommand:(NSString*)command parameter:(NSString*)parameter; | |
| 41 // Returns the dictionary of commands to pass via user defaults to open the main | |
| 42 // application for a given |command| and |parameter|. | |
| 43 + (NSDictionary*)dictForCommand:(NSString*)command | |
| 44 parameter:(NSString*)parameter; | |
| 45 | |
| 46 @end | |
| 47 | |
| 48 @implementation WidgetViewController | |
| 49 | |
| 50 @synthesize widgetView = _widgetView; | |
| 51 @synthesize copiedURL = _copiedURL; | |
| 52 @synthesize clipboardRecentContent = _clipboardRecentContent; | |
| 53 | |
| 54 - (instancetype)init { | |
| 55 self = [super init]; | |
| 56 if (self) { | |
| 57 _clipboardRecentContent = [[ClipboardRecentContentImplIOS alloc] | |
| 58 initWithAuthorizedSchemes:[NSSet setWithObjects:@"http", @"https", nil] | |
| 59 userDefaults:app_group::GetGroupUserDefaults() | |
| 60 delegate:nil]; | |
| 61 } | |
| 62 return self; | |
| 63 } | |
| 64 | |
| 65 #pragma mark - UIViewController | |
| 66 | |
| 67 - (void)viewDidLoad { | |
| 68 [super viewDidLoad]; | |
| 69 | |
| 70 // A local variable is necessary here as the property is declared weak and the | |
| 71 // object would be deallocated before being retained by the addSubview call. | |
| 72 WidgetView* widgetView = [[WidgetView alloc] initWithActionTarget:self]; | |
| 73 self.widgetView = widgetView; | |
| 74 [self.view addSubview:self.widgetView]; | |
| 75 [self updateWidget]; | |
| 76 | |
| 77 if (base::ios::IsRunningOnIOS10OrLater()) { | |
| 78 self.extensionContext.widgetLargestAvailableDisplayMode = | |
| 79 NCWidgetDisplayModeExpanded; | |
| 80 } | |
| 81 | |
| 82 self.widgetView.translatesAutoresizingMaskIntoConstraints = NO; | |
| 83 | |
| 84 NSLayoutConstraint* heightAnchor = [self.widgetView.heightAnchor | |
| 85 constraintEqualToAnchor:self.view.heightAnchor]; | |
| 86 heightAnchor.priority = 900; | |
| 87 | |
| 88 [NSLayoutConstraint activateConstraints:@[ | |
| 89 [self.widgetView.leadingAnchor | |
| 90 constraintEqualToAnchor:self.view.leadingAnchor], | |
| 91 [self.widgetView.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], | |
| 92 [self.widgetView.trailingAnchor | |
| 93 constraintEqualToAnchor:self.view.trailingAnchor], | |
| 94 heightAnchor, | |
| 95 [self.widgetView.topAnchor constraintEqualToAnchor:self.view.topAnchor], | |
| 96 ]]; | |
| 97 } | |
| 98 | |
| 99 - (void)viewWillAppear:(BOOL)animated { | |
| 100 [super viewWillAppear:animated]; | |
| 101 [self updateWidget]; | |
| 102 } | |
| 103 | |
| 104 - (void)widgetPerformUpdateWithCompletionHandler: | |
| 105 (void (^)(NCUpdateResult))completionHandler { | |
| 106 completionHandler([self updateWidget] ? NCUpdateResultNewData | |
| 107 : NCUpdateResultNoData); | |
| 108 } | |
| 109 | |
| 110 - (BOOL)updateWidget { | |
| 111 NSURL* url = [_clipboardRecentContent recentURLFromClipboard]; | |
| 112 | |
| 113 if (![url isEqual:self.copiedURL]) { | |
| 114 self.copiedURL = url; | |
| 115 [self.widgetView updateCopiedURL:self.copiedURL.absoluteString]; | |
| 116 return YES; | |
| 117 } | |
| 118 return NO; | |
| 119 } | |
| 120 | |
| 121 #pragma mark - NCWidgetProviding | |
| 122 | |
| 123 - (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode | |
| 124 withMaximumSize:(CGSize)maxSize { | |
| 125 CGSize fittingSize = [self.widgetView | |
| 126 systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; | |
| 127 if (fittingSize.height > maxSize.height) { | |
| 128 self.preferredContentSize = maxSize; | |
| 129 } else { | |
| 130 self.preferredContentSize = fittingSize; | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 #pragma mark - WidgetViewActionTarget | |
| 135 | |
| 136 - (void)openSearch:(id)sender { | |
| 137 [self openAppWithCommand:base::SysUTF8ToNSString( | |
| 138 app_group::kChromeAppGroupFocusOmniboxCommand)]; | |
| 139 } | |
| 140 | |
| 141 - (void)openIncognito:(id)sender { | |
| 142 [self | |
| 143 openAppWithCommand:base::SysUTF8ToNSString( | |
| 144 app_group::kChromeAppGroupIncognitoSearchCommand)]; | |
| 145 } | |
| 146 | |
| 147 - (void)openVoice:(id)sender { | |
| 148 [self openAppWithCommand:base::SysUTF8ToNSString( | |
| 149 app_group::kChromeAppGroupVoiceSearchCommand)]; | |
| 150 } | |
| 151 | |
| 152 - (void)openQRCode:(id)sender { | |
| 153 [self openAppWithCommand:base::SysUTF8ToNSString( | |
| 154 app_group::kChromeAppGroupQRScannerCommand)]; | |
| 155 } | |
| 156 | |
| 157 - (void)openCopiedURL:(id)sender { | |
| 158 DCHECK(self.copiedURL); | |
| 159 [self openAppWithCommand:base::SysUTF8ToNSString( | |
| 160 app_group::kChromeAppGroupOpenURLCommand) | |
| 161 parameter:self.copiedURL.absoluteString]; | |
| 162 } | |
| 163 | |
| 164 #pragma mark - internal | |
| 165 | |
| 166 - (void)openAppWithCommand:(NSString*)command { | |
| 167 return [self openAppWithCommand:command parameter:nil]; | |
| 168 } | |
| 169 | |
| 170 - (void)openAppWithCommand:(NSString*)command parameter:(NSString*)parameter { | |
| 171 NSUserDefaults* sharedDefaults = | |
| 172 [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]; | |
| 173 NSString* defaultsKey = | |
| 174 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandPreference); | |
| 175 [sharedDefaults setObject:[WidgetViewController dictForCommand:command | |
| 176 parameter:parameter] | |
| 177 forKey:defaultsKey]; | |
| 178 [sharedDefaults synchronize]; | |
| 179 | |
| 180 NSString* scheme = base::mac::ObjCCast<NSString>([[NSBundle mainBundle] | |
| 181 objectForInfoDictionaryKey:@"KSChannelChromeScheme"]); | |
| 182 if (!scheme) | |
| 183 return; | |
| 184 | |
| 185 NSURLComponents* urlComponents = [NSURLComponents new]; | |
| 186 urlComponents.scheme = scheme; | |
| 187 urlComponents.host = kXCallbackURLHost; | |
| 188 urlComponents.path = [NSString | |
| 189 stringWithFormat:@"/%@", base::SysUTF8ToNSString( | |
| 190 app_group::kChromeAppGroupXCallbackCommand)]; | |
| 191 | |
| 192 NSURL* openURL = [urlComponents URL]; | |
| 193 [self.extensionContext openURL:openURL completionHandler:nil]; | |
| 194 } | |
| 195 | |
| 196 + (NSDictionary*)dictForCommand:(NSString*)command | |
| 197 parameter:(NSString*)parameter { | |
| 198 NSString* timePrefKey = | |
| 199 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandTimePreference); | |
| 200 NSString* appPrefKey = | |
| 201 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandAppPreference); | |
| 202 NSString* commandPrefKey = base::SysUTF8ToNSString( | |
| 203 app_group::kChromeAppGroupCommandCommandPreference); | |
| 204 | |
| 205 if (parameter) { | |
| 206 NSString* paramPrefKey = base::SysUTF8ToNSString( | |
| 207 app_group::kChromeAppGroupCommandParameterPreference); | |
| 208 return @{ | |
| 209 timePrefKey : [NSDate date], | |
| 210 appPrefKey : @"TodayExtension", | |
| 211 commandPrefKey : command, | |
| 212 paramPrefKey : parameter, | |
| 213 }; | |
| 214 } | |
| 215 return @{ | |
| 216 timePrefKey : [NSDate date], | |
| 217 appPrefKey : @"TodayExtension", | |
| 218 commandPrefKey : command, | |
| 219 }; | |
| 220 } | |
| 221 | |
| 222 @end | |
| OLD | NEW |