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

Side by Side Diff: ios/chrome/browser/native_app_launcher/native_app_navigation_controller.mm

Issue 2650563002: Pass WebState to NativeAppNavigationController (Closed)
Patch Set: Add chrome_web_test support Created 3 years, 11 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 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/browser/native_app_launcher/native_app_navigation_controller .h" 5 #import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller .h"
6 6
7 #import <StoreKit/StoreKit.h> 7 #import <StoreKit/StoreKit.h>
8 8
9 #include "base/metrics/user_metrics.h" 9 #include "base/metrics/user_metrics.h"
10 #include "base/metrics/user_metrics_action.h" 10 #include "base/metrics/user_metrics_action.h"
11 #include "components/infobars/core/infobar_manager.h" 11 #include "components/infobars/core/infobar_manager.h"
12 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
12 #import "ios/chrome/browser/installation_notifier.h" 13 #import "ios/chrome/browser/installation_notifier.h"
13 #include "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h" 14 #include "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
14 #import "ios/chrome/browser/open_url_util.h" 15 #import "ios/chrome/browser/open_url_util.h"
15 #import "ios/chrome/browser/tabs/tab.h" 16 #import "ios/chrome/browser/tabs/tab.h"
16 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" 17 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
17 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_metad ata.h" 18 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_metad ata.h"
18 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types .h" 19 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types .h"
19 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_white list_manager.h" 20 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_white list_manager.h"
20 #import "ios/web/navigation/navigation_manager_impl.h" 21 #import "ios/web/navigation/navigation_manager_impl.h"
21 #include "ios/web/public/navigation_item.h" 22 #include "ios/web/public/navigation_item.h"
23 #include "ios/web/public/web_state/web_state.h"
Eugene But (OOO till 7-30) 2017/01/21 02:30:08 s/include/import
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Since web_state.h is pure C++ class WebState, shou
22 #import "net/base/mac/url_conversions.h" 24 #import "net/base/mac/url_conversions.h"
23 #include "net/url_request/url_request_context_getter.h" 25 #include "net/url_request/url_request_context_getter.h"
24 26
25 using base::UserMetricsAction; 27 using base::UserMetricsAction;
26 28
27 @interface NativeAppNavigationController () 29 @interface NativeAppNavigationController ()
28 // Shows a native app infobar by looking at the page's URL and by checking 30 // Shows a native app infobar by looking at the page's URL and by checking
29 // wheter that infobar should be bypassed or not. 31 // wheter that infobar should be bypassed or not.
30 - (void)showInfoBarIfNecessary; 32 - (void)showInfoBarIfNecessary;
31 33
32 // Returns a pointer to the NSMutableSet of |_appsPossiblyBeingInstalled| 34 // Returns a pointer to the NSMutableSet of |_appsPossiblyBeingInstalled|
33 - (NSMutableSet*)appsPossiblyBeingInstalled; 35 - (NSMutableSet*)appsPossiblyBeingInstalled;
34 36
35 // Records what type of infobar was opened. 37 // Records what type of infobar was opened.
36 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type 38 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
37 onLinkNavigation:(BOOL)isLinkNavigation; 39 onLinkNavigation:(BOOL)isLinkNavigation;
38 40
39 // Returns whether the current state is Link Navigation in the sense of Native 41 // Returns whether the current state is Link Navigation in the sense of Native
40 // App Launcher, i.e. a navigation caused by an explicit user action in the 42 // App Launcher, i.e. a navigation caused by an explicit user action in the
41 // rectangle of the web content area. 43 // rectangle of the web content area.
42 - (BOOL)isLinkNavigation; 44 - (BOOL)isLinkNavigation;
43 45
44 @end 46 @end
45 47
46 @implementation NativeAppNavigationController { 48 @implementation NativeAppNavigationController {
49 // WebState provides access to the *TabHelper objects. This will eventually
50 // replace the need to have |_tab| in this object.
51 web::WebState* _webState;
47 // A reference to the URLRequestContextGetter needed to fetch icons. 52 // A reference to the URLRequestContextGetter needed to fetch icons.
48 scoped_refptr<net::URLRequestContextGetter> _requestContextGetter; 53 scoped_refptr<net::URLRequestContextGetter> _requestContextGetter;
49 // Tab hosting the infobar. 54 // DEPRECATED: Tab hosting the infobar and is also used for accessing Tab
55 // states such as navigation manager and whether it is a pre-rendered tab.
56 // Use |webState| whenever possible.
50 __unsafe_unretained Tab* _tab; // weak 57 __unsafe_unretained Tab* _tab; // weak
51 base::scoped_nsprotocol<id<NativeAppMetadata>> _metadata; 58 base::scoped_nsprotocol<id<NativeAppMetadata>> _metadata;
52 // A set of appIds encoded as NSStrings. 59 // A set of appIds encoded as NSStrings.
53 base::scoped_nsobject<NSMutableSet> _appsPossiblyBeingInstalled; 60 base::scoped_nsobject<NSMutableSet> _appsPossiblyBeingInstalled;
54 } 61 }
55 62
56 // This prevents incorrect initialization of this object.
57 - (id)init {
58 NOTREACHED();
59 return nil;
60 }
61
62 // Designated initializer. Use this instead of -init. 63 // Designated initializer. Use this instead of -init.
63 - (id)initWithRequestContextGetter:(net::URLRequestContextGetter*)context 64 - (instancetype)initWithWebState:(web::WebState*)webState
rohitrao (ping after 24h) 2017/01/24 14:24:56 I can't decide whether we should pass both WebStat
pkl (ping after 24h if needed) 2017/01/26 00:30:17 My intent is that we can stop passing in |tab| eve
64 tab:(Tab*)tab { 65 requestContextGetter:(net::URLRequestContextGetter*)context
66 tab:(Tab*)tab {
65 self = [super init]; 67 self = [super init];
66 if (self) { 68 if (self) {
67 DCHECK(context); 69 DCHECK(context);
68 _requestContextGetter = context; 70 _requestContextGetter = context;
71 _webState = webState;
69 // Allows |tab| to be nil for unit testing. 72 // Allows |tab| to be nil for unit testing.
70 _tab = tab; 73 _tab = tab;
71 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] init]); 74 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] init]);
72 } 75 }
73 return self; 76 return self;
74 } 77 }
75 78
76 - (void)copyStateFrom:(NativeAppNavigationController*)controller { 79 - (void)copyStateFrom:(NativeAppNavigationController*)controller {
77 DCHECK(controller); 80 DCHECK(controller);
78 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] 81 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc]
(...skipping 15 matching lines...) Expand all
94 [[InstallationNotifier sharedInstance] unregisterForNotifications:self]; 97 [[InstallationNotifier sharedInstance] unregisterForNotifications:self];
95 [super dealloc]; 98 [super dealloc];
96 } 99 }
97 100
98 - (NSMutableSet*)appsPossiblyBeingInstalled { 101 - (NSMutableSet*)appsPossiblyBeingInstalled {
99 return _appsPossiblyBeingInstalled; 102 return _appsPossiblyBeingInstalled;
100 } 103 }
101 104
102 - (void)showInfoBarIfNecessary { 105 - (void)showInfoBarIfNecessary {
103 // Find a potential matching native app. 106 // Find a potential matching native app.
104 GURL pageURL = _tab.webState->GetLastCommittedURL(); 107 GURL pageURL = _webState->GetLastCommittedURL();
105 _metadata.reset( 108 _metadata.reset(
106 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager() 109 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
107 newNativeAppForURL:pageURL]); 110 newNativeAppForURL:pageURL]);
108 if (!_metadata || [_metadata shouldBypassInfoBars]) 111 if (!_metadata || [_metadata shouldBypassInfoBars])
109 return; 112 return;
110 113
111 // Select the infobar type. 114 // Select the infobar type.
112 NativeAppControllerType type; 115 NativeAppControllerType type;
113 if ([_metadata canOpenURL:pageURL]) { // App is installed. 116 if ([_metadata canOpenURL:pageURL]) { // App is installed.
114 type = [self isLinkNavigation] && ![_metadata shouldAutoOpenLinks] 117 type = [self isLinkNavigation] && ![_metadata shouldAutoOpenLinks]
115 ? NATIVE_APP_OPEN_POLICY_CONTROLLER 118 ? NATIVE_APP_OPEN_POLICY_CONTROLLER
116 : NATIVE_APP_LAUNCHER_CONTROLLER; 119 : NATIVE_APP_LAUNCHER_CONTROLLER;
117 } else { // App is not installed. 120 } else { // App is not installed.
118 // Check if the user already opened the store for this app. 121 // Check if the user already opened the store for this app.
119 if ([_appsPossiblyBeingInstalled containsObject:[_metadata appId]]) 122 if ([_appsPossiblyBeingInstalled containsObject:[_metadata appId]])
120 return; 123 return;
121 type = NATIVE_APP_INSTALLER_CONTROLLER; 124 type = NATIVE_APP_INSTALLER_CONTROLLER;
122 } 125 }
123 // Inform the metadata that an infobar of |type| will be shown so that metrics 126 // Inform the metadata that an infobar of |type| will be shown so that metrics
124 // and ignored behavior can be handled. 127 // and ignored behavior can be handled.
125 [_metadata willBeShownInInfobarOfType:type]; 128 [_metadata willBeShownInInfobarOfType:type];
126 // Display the proper infobar. 129 // Display the proper infobar.
127 infobars::InfoBarManager* infoBarManager = [_tab infoBarManager]; 130 infobars::InfoBarManager* infoBarManager =
131 InfoBarManagerImpl::FromWebState(_webState);
128 NativeAppInfoBarDelegate::Create(infoBarManager, self, pageURL, type); 132 NativeAppInfoBarDelegate::Create(infoBarManager, self, pageURL, type);
129 [self recordInfobarDisplayedOfType:type 133 [self recordInfobarDisplayedOfType:type
130 onLinkNavigation:[self isLinkNavigation]]; 134 onLinkNavigation:[self isLinkNavigation]];
131 } 135 }
132 136
133 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type 137 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
134 onLinkNavigation:(BOOL)isLinkNavigation { 138 onLinkNavigation:(BOOL)isLinkNavigation {
135 switch (type) { 139 switch (type) {
136 case NATIVE_APP_INSTALLER_CONTROLLER: 140 case NATIVE_APP_INSTALLER_CONTROLLER:
137 base::RecordAction( 141 base::RecordAction(
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 registerForInstallationNotifications:self 177 registerForInstallationNotifications:self
174 withSelector:@selector(appDidInstall:) 178 withSelector:@selector(appDidInstall:)
175 forScheme:[_metadata anyScheme]]; 179 forScheme:[_metadata anyScheme]];
176 NSString* appIdString = [self appId]; 180 NSString* appIdString = [self appId];
177 // Defensively early return if native app metadata returns an nil string for 181 // Defensively early return if native app metadata returns an nil string for
178 // appId which can cause subsequent -addObject: to throw exceptions. 182 // appId which can cause subsequent -addObject: to throw exceptions.
179 if (![appIdString length]) 183 if (![appIdString length])
180 return; 184 return;
181 DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]); 185 DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]);
182 [_appsPossiblyBeingInstalled addObject:appIdString]; 186 [_appsPossiblyBeingInstalled addObject:appIdString];
187 // TODO(pkl): Preferred method is to add a helper object to WebState
Eugene But (OOO till 7-30) 2017/01/21 02:30:08 Please use |TODO(crbug.com/):| format
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Done.
188 // and use the helper object to launch Store Kit.
rohitrao (ping after 24h) 2017/01/24 14:24:56 The intent is to do this in a separate CL?
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Yes. I've updated the comment to include a crbug r
183 [_tab openAppStore:appIdString]; 189 [_tab openAppStore:appIdString];
184 } 190 }
185 191
186 - (void)launchApp:(const GURL&)URL { 192 - (void)launchApp:(const GURL&)URL {
187 // TODO(crbug.com/353957): Pass the ChromeIdentity to 193 // TODO(crbug.com/353957): Pass the ChromeIdentity to
188 // -launchURLWithURL:identity: 194 // -launchURLWithURL:identity:
189 GURL launchURL([_metadata launchURLWithURL:URL identity:nil]); 195 GURL launchURL([_metadata launchURLWithURL:URL identity:nil]);
190 if (launchURL.is_valid()) { 196 if (launchURL.is_valid()) {
191 OpenUrlWithCompletionHandler(net::NSURLWithGURL(launchURL), nil); 197 OpenUrlWithCompletionHandler(net::NSURLWithGURL(launchURL), nil);
192 } 198 }
193 } 199 }
194 200
195 - (void)updateMetadataWithUserAction:(NativeAppActionType)userAction { 201 - (void)updateMetadataWithUserAction:(NativeAppActionType)userAction {
196 [_metadata updateWithUserAction:userAction]; 202 [_metadata updateWithUserAction:userAction];
197 } 203 }
198 204
199 #pragma mark - 205 #pragma mark -
200 #pragma mark CRWWebControllerObserver methods 206 #pragma mark CRWWebControllerObserver methods
201 207
202 - (void)pageLoaded:(CRWWebController*)webController { 208 - (void)pageLoaded:(CRWWebController*)webController {
203 if (![_tab isPrerenderTab]) 209 if (![_tab isPrerenderTab])
204 [self showInfoBarIfNecessary]; 210 [self showInfoBarIfNecessary];
205 } 211 }
206 212
207 - (void)webControllerWillClose:(CRWWebController*)webController { 213 - (void)webControllerWillClose:(CRWWebController*)webController {
208 [webController removeObserver:self]; 214 [webController removeObserver:self];
209 } 215 }
210 216
211 - (BOOL)isLinkNavigation { 217 - (BOOL)isLinkNavigation {
212 if (![_tab navigationManager]) 218 web::NavigationManager* navigationManager = _webState->GetNavigationManager();
Eugene But (OOO till 7-30) 2017/01/21 02:30:08 Should we move this code to utility function, so i
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Done.
213 return NO; 219 if (navigationManager) {
Eugene But (OOO till 7-30) 2017/01/21 02:30:08 nit: do you want to keep original logic with early
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Reverted.
214 web::NavigationItem* userItem = [_tab navigationManager]->GetLastUserItem(); 220 NSInteger index = navigationManager->GetCurrentItemIndex();
Eugene But (OOO till 7-30) 2017/01/21 02:30:08 Maybe s/NSInteger/int ?
pkl (ping after 24h if needed) 2017/01/26 00:30:17 Done.
215 if (!userItem) 221 while (index >= 0) {
216 return NO; 222 web::NavigationItem* item = navigationManager->GetItemAtIndex(index);
217 ui::PageTransition currentTransition = userItem->GetTransitionType(); 223 DCHECK(item);
218 return PageTransitionCoreTypeIs(currentTransition, 224 ui::PageTransition currentTransition = item->GetTransitionType();
219 ui::PAGE_TRANSITION_LINK) || 225 // Checks all non-redirect entries for transitions that are either links
220 PageTransitionCoreTypeIs(currentTransition, 226 // or bookmarks.
221 ui::PAGE_TRANSITION_AUTO_BOOKMARK); 227 if ((currentTransition & ui::PAGE_TRANSITION_IS_REDIRECT_MASK) == 0) {
228 return PageTransitionCoreTypeIs(currentTransition,
229 ui::PAGE_TRANSITION_LINK) ||
230 PageTransitionCoreTypeIs(currentTransition,
231 ui::PAGE_TRANSITION_AUTO_BOOKMARK);
232 }
233 --index;
234 }
235 }
236 return NO;
222 } 237 }
223 238
224 - (void)appDidInstall:(NSNotification*)notification { 239 - (void)appDidInstall:(NSNotification*)notification {
225 [self removeAppFromNotification:notification]; 240 [self removeAppFromNotification:notification];
226 [self showInfoBarIfNecessary]; 241 [self showInfoBarIfNecessary];
227 } 242 }
228 243
229 - (void)removeAppFromNotification:(NSNotification*)notification { 244 - (void)removeAppFromNotification:(NSNotification*)notification {
230 DCHECK([[notification object] isKindOfClass:[InstallationNotifier class]]); 245 DCHECK([[notification object] isKindOfClass:[InstallationNotifier class]]);
231 NSString* schemeOfInstalledApp = [notification name]; 246 NSString* schemeOfInstalledApp = [notification name];
232 __block NSString* appIDToRemove = nil; 247 __block NSString* appIDToRemove = nil;
233 [_appsPossiblyBeingInstalled 248 [_appsPossiblyBeingInstalled
234 enumerateObjectsUsingBlock:^(id appID, BOOL* stop) { 249 enumerateObjectsUsingBlock:^(id appID, BOOL* stop) {
235 NSURL* appURL = 250 NSURL* appURL =
236 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager() 251 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
237 schemeForAppId:appID]; 252 schemeForAppId:appID];
238 if ([[appURL scheme] isEqualToString:schemeOfInstalledApp]) { 253 if ([[appURL scheme] isEqualToString:schemeOfInstalledApp]) {
239 appIDToRemove = appID; 254 appIDToRemove = appID;
240 *stop = YES; 255 *stop = YES;
241 } 256 }
242 }]; 257 }];
243 DCHECK(appIDToRemove); 258 DCHECK(appIDToRemove);
244 [_appsPossiblyBeingInstalled removeObject:appIDToRemove]; 259 [_appsPossiblyBeingInstalled removeObject:appIDToRemove];
245 } 260 }
246 261
247 @end 262 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698