OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "ios/chrome/widget_extension/widget_view_controller.h" | 5 #import "ios/chrome/widget_extension/widget_view_controller.h" |
6 | 6 |
7 #import <NotificationCenter/NotificationCenter.h> | 7 #import <NotificationCenter/NotificationCenter.h> |
8 | 8 |
9 #include "base/ios/ios_util.h" | |
9 #include "base/mac/foundation_util.h" | 10 #include "base/mac/foundation_util.h" |
10 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
12 #include "components/open_from_clipboard/clipboard_recent_content_impl_ios.h" | |
11 #include "ios/chrome/common/app_group/app_group_constants.h" | 13 #include "ios/chrome/common/app_group/app_group_constants.h" |
12 #include "ios/chrome/common/x_callback_url.h" | |
13 #import "ios/chrome/widget_extension/widget_view.h" | 14 #import "ios/chrome/widget_extension/widget_view.h" |
14 #import "net/base/mac/url_conversions.h" | |
15 #include "url/gurl.h" | |
16 | 15 |
17 #if !defined(__has_feature) || !__has_feature(objc_arc) | 16 #if !defined(__has_feature) || !__has_feature(objc_arc) |
18 #error "This file requires ARC support." | 17 #error "This file requires ARC support." |
19 #endif | 18 #endif |
20 | 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. As this class makes a very basic use of xcallback no full | |
lpromero
2017/04/11 13:24:04
s/xcallback/x-callback-url, and add a comma.
lody
2017/04/11 14:38:19
Done.
| |
24 // implementation in is required. | |
lpromero
2017/04/11 13:24:03
Should you remove "in"?
lody
2017/04/11 14:38:18
Done.
| |
25 NSString* const kXCallbackURLHost = @"x-callback-url"; | |
26 } // namespace | |
27 | |
21 @interface WidgetViewController ()<WidgetViewActionTarget> | 28 @interface WidgetViewController ()<WidgetViewActionTarget> |
22 @property(nonatomic, weak) WidgetView* widgetView; | 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; | |
lpromero
2017/04/11 13:24:03
s/Parameter/parameter
lody
2017/04/11 14:38:18
Done.
| |
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*)commandDict:(NSString*)command Parameter:(NSString*)parameter; | |
lpromero
2017/04/11 13:24:03
Rename commandDictForCommand:parameter:, or dictFo
lody
2017/04/11 14:38:18
Done.
| |
44 | |
23 @end | 45 @end |
24 | 46 |
25 @implementation WidgetViewController | 47 @implementation WidgetViewController |
26 | 48 |
27 @synthesize widgetView = _widgetView; | 49 @synthesize widgetView = _widgetView; |
50 @synthesize copiedURL = _copiedURL; | |
51 @synthesize clipboardRecentContent = _clipboardRecentContent; | |
52 | |
53 - (instancetype)init { | |
54 self = [super init]; | |
55 if (self) { | |
56 _clipboardRecentContent = [[ClipboardRecentContentImplIOS alloc] | |
57 initWithAuthorizedSchemes:[NSSet setWithObjects:@"http", @"https", nil] | |
58 userDefaults:app_group::GetGroupUserDefaults() | |
59 delegate:nil]; | |
60 } | |
61 return self; | |
62 } | |
28 | 63 |
29 #pragma mark - UIViewController | 64 #pragma mark - UIViewController |
30 | 65 |
31 - (void)viewDidLoad { | 66 - (void)viewDidLoad { |
32 [super viewDidLoad]; | 67 [super viewDidLoad]; |
33 | 68 |
34 // A local variable is necessary here as the property is declared weak and the | 69 // A local variable is necessary here as the property is declared weak and the |
35 // object would be deallocated before being retained by the addSubview call. | 70 // object would be deallocated before being retained by the addSubview call. |
36 WidgetView* widgetView = [[WidgetView alloc] initWithActionTarget:self]; | 71 WidgetView* widgetView = [[WidgetView alloc] initWithActionTarget:self]; |
37 self.widgetView = widgetView; | 72 self.widgetView = widgetView; |
38 [self.view addSubview:self.widgetView]; | 73 [self.view addSubview:self.widgetView]; |
74 [self updateWidget]; | |
39 | 75 |
40 [self.widgetView setTranslatesAutoresizingMaskIntoConstraints:NO]; | 76 if (base::ios::IsRunningOnIOS10OrLater()) { |
77 self.extensionContext.widgetLargestAvailableDisplayMode = | |
78 NCWidgetDisplayModeExpanded; | |
79 } | |
80 | |
81 self.widgetView.translatesAutoresizingMaskIntoConstraints = NO; | |
82 | |
83 NSLayoutConstraint* heightAnchor = [self.widgetView.heightAnchor | |
84 constraintEqualToAnchor:self.view.heightAnchor]; | |
85 heightAnchor.priority = 900; | |
86 | |
41 [NSLayoutConstraint activateConstraints:@[ | 87 [NSLayoutConstraint activateConstraints:@[ |
42 [self.widgetView.leadingAnchor | 88 [self.widgetView.leadingAnchor |
43 constraintEqualToAnchor:[self.view leadingAnchor]], | 89 constraintEqualToAnchor:self.view.leadingAnchor], |
90 [self.widgetView.widthAnchor constraintEqualToAnchor:self.view.widthAnchor], | |
44 [self.widgetView.trailingAnchor | 91 [self.widgetView.trailingAnchor |
45 constraintEqualToAnchor:[self.view trailingAnchor]], | 92 constraintEqualToAnchor:self.view.trailingAnchor], |
46 [self.widgetView.heightAnchor | 93 heightAnchor, |
47 constraintEqualToAnchor:[self.view heightAnchor]], | 94 [self.widgetView.topAnchor constraintEqualToAnchor:self.view.topAnchor], |
48 [self.widgetView.widthAnchor | |
49 constraintEqualToAnchor:[self.view widthAnchor]] | |
50 ]]; | 95 ]]; |
51 } | 96 } |
52 | 97 |
53 - (void)openApp:(id)sender { | 98 - (void)viewDidAppear:(BOOL)animated { |
lpromero
2017/04/11 13:24:03
You should call [super viewDidAppear:animated]. I
lpromero
2017/04/11 13:24:03
Why in viewDidLoad and viewDidAppear and not just
lody
2017/04/11 14:38:18
Done.
lody
2017/04/11 14:38:18
ViewDidLoad is not called as often as viewWillAppe
| |
99 [self updateWidget]; | |
100 } | |
101 | |
102 - (void)widgetPerformUpdateWithCompletionHandler: | |
103 (void (^)(NCUpdateResult))completionHandler { | |
104 completionHandler([self updateWidget] ? NCUpdateResultNewData | |
105 : NCUpdateResultNoData); | |
106 } | |
107 | |
108 - (BOOL)updateWidget { | |
109 NSURL* url = [_clipboardRecentContent recentURLFromClipboard]; | |
110 | |
111 if (![url isEqual:self.copiedURL]) { | |
112 self.copiedURL = url; | |
113 [self.widgetView | |
114 updateCopiedURL:self.copiedURL ? self.copiedURL.absoluteString : nil]; | |
lpromero
2017/04/11 13:24:03
You can simplify in [self.widgetView updateCopiedU
lody
2017/04/11 14:38:18
Done.
| |
115 | |
116 return YES; | |
117 } | |
118 return NO; | |
119 } | |
120 | |
121 #pragma mark NCWidgetProviding | |
lpromero
2017/04/11 13:24:03
Nit: #pragma mark - NCWidgetProviding
lody
2017/04/11 14:38:18
Done.
| |
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 | |
lpromero
2017/04/11 13:24:03
Ditto
lody
2017/04/11 14:38:19
Done.
| |
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)openCopiedLink:(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 | |
lpromero
2017/04/11 13:24:04
Ditto
lody
2017/04/11 14:38:19
Done.
| |
165 | |
166 - (void)openAppWithCommand:(NSString*)command { | |
167 return [self openAppWithCommand:command Parameter:nil]; | |
168 } | |
169 | |
170 - (void)openAppWithCommand:(NSString*)command Parameter:(NSString*)parameter { | |
54 NSUserDefaults* sharedDefaults = | 171 NSUserDefaults* sharedDefaults = |
55 [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]; | 172 [[NSUserDefaults alloc] initWithSuiteName:app_group::ApplicationGroup()]; |
56 NSString* defaultsKey = | 173 NSString* defaultsKey = |
57 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandPreference); | 174 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandPreference); |
58 [sharedDefaults setObject:[WidgetViewController commandDict] | 175 [sharedDefaults |
59 forKey:defaultsKey]; | 176 setObject:[WidgetViewController commandDict:command Parameter:parameter] |
177 forKey:defaultsKey]; | |
60 [sharedDefaults synchronize]; | 178 [sharedDefaults synchronize]; |
61 | 179 |
62 NSString* scheme = base::mac::ObjCCast<NSString>([[NSBundle mainBundle] | 180 NSString* scheme = base::mac::ObjCCast<NSString>([[NSBundle mainBundle] |
63 objectForInfoDictionaryKey:@"KSChannelChromeScheme"]); | 181 objectForInfoDictionaryKey:@"KSChannelChromeScheme"]); |
64 if (!scheme) | 182 if (!scheme) |
65 return; | 183 return; |
66 const GURL openURL = | 184 |
67 CreateXCallbackURL(base::SysNSStringToUTF8(scheme), | 185 NSURLComponents* urlComponents = [NSURLComponents new]; |
68 app_group::kChromeAppGroupXCallbackCommand); | 186 urlComponents.scheme = scheme; |
69 [self.extensionContext openURL:net::NSURLWithGURL(openURL) | 187 urlComponents.host = kXCallbackURLHost; |
70 completionHandler:nil]; | 188 urlComponents.path = [NSString |
189 stringWithFormat:@"/%@", base::SysUTF8ToNSString( | |
lpromero
2017/04/11 13:24:03
Do you really need the "/" given that you are sett
lody
2017/04/11 14:38:18
unfortunately, nope (unless I missed an option)
| |
190 app_group::kChromeAppGroupXCallbackCommand)]; | |
191 | |
192 NSURL* openURL = [urlComponents URL]; | |
193 [self.extensionContext openURL:openURL completionHandler:nil]; | |
71 } | 194 } |
72 | 195 |
73 + (NSDictionary*)commandDict { | 196 + (NSDictionary*)commandDict:(NSString*)command Parameter:(NSString*)parameter { |
lpromero
2017/04/11 13:24:04
s/Parameter/parameter
lody
2017/04/11 14:38:18
Done.
| |
74 NSString* command = | |
75 base::SysUTF8ToNSString(app_group::kChromeAppGroupFocusOmniboxCommand); | |
76 NSString* timePrefKey = | 197 NSString* timePrefKey = |
77 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandTimePreference); | 198 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandTimePreference); |
78 NSString* appPrefKey = | 199 NSString* appPrefKey = |
79 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandAppPreference); | 200 base::SysUTF8ToNSString(app_group::kChromeAppGroupCommandAppPreference); |
80 NSString* commandPrefKey = base::SysUTF8ToNSString( | 201 NSString* commandPrefKey = base::SysUTF8ToNSString( |
81 app_group::kChromeAppGroupCommandCommandPreference); | 202 app_group::kChromeAppGroupCommandCommandPreference); |
203 | |
204 if (parameter) { | |
205 NSString* paramPrefKey = base::SysUTF8ToNSString( | |
206 app_group::kChromeAppGroupCommandParameterPreference); | |
207 return @{ | |
208 timePrefKey : [NSDate date], | |
209 appPrefKey : @"TodayExtension", | |
210 commandPrefKey : command, | |
211 paramPrefKey : parameter, | |
212 }; | |
213 } | |
82 return @{ | 214 return @{ |
83 timePrefKey : [NSDate date], | 215 timePrefKey : [NSDate date], |
84 appPrefKey : @"TodayExtension", | 216 appPrefKey : @"TodayExtension", |
85 commandPrefKey : command, | 217 commandPrefKey : command, |
86 }; | 218 }; |
87 } | 219 } |
88 | 220 |
89 @end | 221 @end |
OLD | NEW |