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

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

Issue 2650563002: Pass WebState to NativeAppNavigationController (Closed)
Patch Set: fixed import vs. include Created 3 years, 10 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"
15 #include "ios/chrome/browser/native_app_launcher/native_app_navigation_util.h"
14 #import "ios/chrome/browser/open_url_util.h" 16 #import "ios/chrome/browser/open_url_util.h"
15 #import "ios/chrome/browser/tabs/tab.h" 17 #import "ios/chrome/browser/tabs/tab.h"
16 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h" 18 #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" 19 #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" 20 #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" 21 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_white list_manager.h"
20 #import "ios/web/navigation/navigation_manager_impl.h" 22 #include "ios/web/public/web_state/web_state.h"
21 #include "ios/web/public/navigation_item.h"
22 #import "net/base/mac/url_conversions.h" 23 #import "net/base/mac/url_conversions.h"
23 #include "net/url_request/url_request_context_getter.h" 24 #include "net/url_request/url_request_context_getter.h"
24 25
25 using base::UserMetricsAction; 26 using base::UserMetricsAction;
26 27
27 @interface NativeAppNavigationController () 28 @interface NativeAppNavigationController ()
28 // Shows a native app infobar by looking at the page's URL and by checking 29 // Shows a native app infobar by looking at the page's URL and by checking
29 // wheter that infobar should be bypassed or not. 30 // wheter that infobar should be bypassed or not.
30 - (void)showInfoBarIfNecessary; 31 - (void)showInfoBarIfNecessary;
31 32
32 // Returns a pointer to the NSMutableSet of |_appsPossiblyBeingInstalled| 33 // Returns a pointer to the NSMutableSet of |_appsPossiblyBeingInstalled|
33 - (NSMutableSet*)appsPossiblyBeingInstalled; 34 - (NSMutableSet*)appsPossiblyBeingInstalled;
34 35
35 // Records what type of infobar was opened. 36 // Records what type of infobar was opened.
36 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type 37 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
37 onLinkNavigation:(BOOL)isLinkNavigation; 38 onLinkNavigation:(BOOL)isLinkNavigation;
38 39
39 // 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
41 // rectangle of the web content area.
42 - (BOOL)isLinkNavigation;
43
44 @end 40 @end
45 41
46 @implementation NativeAppNavigationController { 42 @implementation NativeAppNavigationController {
43 // WebState provides access to the *TabHelper objects. This will eventually
44 // replace the need to have |_tab| in this object.
45 web::WebState* _webState;
47 // A reference to the URLRequestContextGetter needed to fetch icons. 46 // A reference to the URLRequestContextGetter needed to fetch icons.
48 scoped_refptr<net::URLRequestContextGetter> _requestContextGetter; 47 scoped_refptr<net::URLRequestContextGetter> _requestContextGetter;
49 // Tab hosting the infobar. 48 // DEPRECATED: Tab hosting the infobar and is also used for accessing Tab
49 // states such as navigation manager and whether it is a pre-rendered tab.
50 // Use |webState| whenever possible.
50 __unsafe_unretained Tab* _tab; // weak 51 __unsafe_unretained Tab* _tab; // weak
51 base::scoped_nsprotocol<id<NativeAppMetadata>> _metadata; 52 base::scoped_nsprotocol<id<NativeAppMetadata>> _metadata;
52 // A set of appIds encoded as NSStrings. 53 // A set of appIds encoded as NSStrings.
53 base::scoped_nsobject<NSMutableSet> _appsPossiblyBeingInstalled; 54 base::scoped_nsobject<NSMutableSet> _appsPossiblyBeingInstalled;
54 } 55 }
55 56
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. 57 // Designated initializer. Use this instead of -init.
63 - (id)initWithRequestContextGetter:(net::URLRequestContextGetter*)context 58 - (instancetype)initWithWebState:(web::WebState*)webState
64 tab:(Tab*)tab { 59 requestContextGetter:(net::URLRequestContextGetter*)context
60 tab:(Tab*)tab {
65 self = [super init]; 61 self = [super init];
66 if (self) { 62 if (self) {
67 DCHECK(context); 63 DCHECK(context);
68 _requestContextGetter = context; 64 _requestContextGetter = context;
69 // Allows |tab| to be nil for unit testing. 65 DCHECK(webState);
66 _webState = webState;
67 // Allows |tab| to be nil for unit testing. If not nil, it should have the
68 // same webState.
69 DCHECK(!tab || [tab webState] == webState);
70 _tab = tab; 70 _tab = tab;
71 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] init]); 71 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] init]);
72 } 72 }
73 return self; 73 return self;
74 } 74 }
75 75
76 - (void)copyStateFrom:(NativeAppNavigationController*)controller { 76 - (void)copyStateFrom:(NativeAppNavigationController*)controller {
77 DCHECK(controller); 77 DCHECK(controller);
78 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc] 78 _appsPossiblyBeingInstalled.reset([[NSMutableSet alloc]
79 initWithSet:[controller appsPossiblyBeingInstalled]]); 79 initWithSet:[controller appsPossiblyBeingInstalled]]);
(...skipping 14 matching lines...) Expand all
94 [[InstallationNotifier sharedInstance] unregisterForNotifications:self]; 94 [[InstallationNotifier sharedInstance] unregisterForNotifications:self];
95 [super dealloc]; 95 [super dealloc];
96 } 96 }
97 97
98 - (NSMutableSet*)appsPossiblyBeingInstalled { 98 - (NSMutableSet*)appsPossiblyBeingInstalled {
99 return _appsPossiblyBeingInstalled; 99 return _appsPossiblyBeingInstalled;
100 } 100 }
101 101
102 - (void)showInfoBarIfNecessary { 102 - (void)showInfoBarIfNecessary {
103 // Find a potential matching native app. 103 // Find a potential matching native app.
104 GURL pageURL = _tab.webState->GetLastCommittedURL(); 104 GURL pageURL = _webState->GetLastCommittedURL();
105 _metadata.reset( 105 _metadata.reset(
106 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager() 106 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
107 newNativeAppForURL:pageURL]); 107 newNativeAppForURL:pageURL]);
108 if (!_metadata || [_metadata shouldBypassInfoBars]) 108 if (!_metadata || [_metadata shouldBypassInfoBars])
109 return; 109 return;
110 110
111 // Select the infobar type. 111 // Select the infobar type.
112 NativeAppControllerType type; 112 NativeAppControllerType type;
113 bool isLinkNavigation = native_app_launcher::IsLinkNavigation(_webState);
113 if ([_metadata canOpenURL:pageURL]) { // App is installed. 114 if ([_metadata canOpenURL:pageURL]) { // App is installed.
114 type = [self isLinkNavigation] && ![_metadata shouldAutoOpenLinks] 115 type = isLinkNavigation && ![_metadata shouldAutoOpenLinks]
115 ? NATIVE_APP_OPEN_POLICY_CONTROLLER 116 ? NATIVE_APP_OPEN_POLICY_CONTROLLER
116 : NATIVE_APP_LAUNCHER_CONTROLLER; 117 : NATIVE_APP_LAUNCHER_CONTROLLER;
117 } else { // App is not installed. 118 } else { // App is not installed.
118 // Check if the user already opened the store for this app. 119 // Check if the user already opened the store for this app.
119 if ([_appsPossiblyBeingInstalled containsObject:[_metadata appId]]) 120 if ([_appsPossiblyBeingInstalled containsObject:[_metadata appId]])
120 return; 121 return;
121 type = NATIVE_APP_INSTALLER_CONTROLLER; 122 type = NATIVE_APP_INSTALLER_CONTROLLER;
122 } 123 }
123 // Inform the metadata that an infobar of |type| will be shown so that metrics 124 // Inform the metadata that an infobar of |type| will be shown so that metrics
124 // and ignored behavior can be handled. 125 // and ignored behavior can be handled.
125 [_metadata willBeShownInInfobarOfType:type]; 126 [_metadata willBeShownInInfobarOfType:type];
126 // Display the proper infobar. 127 // Display the proper infobar.
127 infobars::InfoBarManager* infoBarManager = [_tab infoBarManager]; 128 infobars::InfoBarManager* infoBarManager =
129 InfoBarManagerImpl::FromWebState(_webState);
128 NativeAppInfoBarDelegate::Create(infoBarManager, self, pageURL, type); 130 NativeAppInfoBarDelegate::Create(infoBarManager, self, pageURL, type);
129 [self recordInfobarDisplayedOfType:type 131 [self recordInfobarDisplayedOfType:type onLinkNavigation:isLinkNavigation];
130 onLinkNavigation:[self isLinkNavigation]];
131 } 132 }
132 133
133 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type 134 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
134 onLinkNavigation:(BOOL)isLinkNavigation { 135 onLinkNavigation:(BOOL)isLinkNavigation {
135 switch (type) { 136 switch (type) {
136 case NATIVE_APP_INSTALLER_CONTROLLER: 137 case NATIVE_APP_INSTALLER_CONTROLLER:
137 base::RecordAction( 138 base::RecordAction(
138 isLinkNavigation 139 isLinkNavigation
139 ? UserMetricsAction("MobileGALInstallInfoBarLinkNavigation") 140 ? UserMetricsAction("MobileGALInstallInfoBarLinkNavigation")
140 : UserMetricsAction("MobileGALInstallInfoBarDirectNavigation")); 141 : UserMetricsAction("MobileGALInstallInfoBarDirectNavigation"));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 registerForInstallationNotifications:self 174 registerForInstallationNotifications:self
174 withSelector:@selector(appDidInstall:) 175 withSelector:@selector(appDidInstall:)
175 forScheme:[_metadata anyScheme]]; 176 forScheme:[_metadata anyScheme]];
176 NSString* appIdString = [self appId]; 177 NSString* appIdString = [self appId];
177 // Defensively early return if native app metadata returns an nil string for 178 // Defensively early return if native app metadata returns an nil string for
178 // appId which can cause subsequent -addObject: to throw exceptions. 179 // appId which can cause subsequent -addObject: to throw exceptions.
179 if (![appIdString length]) 180 if (![appIdString length])
180 return; 181 return;
181 DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]); 182 DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]);
182 [_appsPossiblyBeingInstalled addObject:appIdString]; 183 [_appsPossiblyBeingInstalled addObject:appIdString];
184 // TODO(crbug.com/684063): Preferred method is to add a helper object to
185 // WebState and use the helper object to launch Store Kit.
183 [_tab openAppStore:appIdString]; 186 [_tab openAppStore:appIdString];
184 } 187 }
185 188
186 - (void)launchApp:(const GURL&)URL { 189 - (void)launchApp:(const GURL&)URL {
187 // TODO(crbug.com/353957): Pass the ChromeIdentity to 190 // TODO(crbug.com/353957): Pass the ChromeIdentity to
188 // -launchURLWithURL:identity: 191 // -launchURLWithURL:identity:
189 GURL launchURL([_metadata launchURLWithURL:URL identity:nil]); 192 GURL launchURL([_metadata launchURLWithURL:URL identity:nil]);
190 if (launchURL.is_valid()) { 193 if (launchURL.is_valid()) {
191 OpenUrlWithCompletionHandler(net::NSURLWithGURL(launchURL), nil); 194 OpenUrlWithCompletionHandler(net::NSURLWithGURL(launchURL), nil);
192 } 195 }
193 } 196 }
194 197
195 - (void)updateMetadataWithUserAction:(NativeAppActionType)userAction { 198 - (void)updateMetadataWithUserAction:(NativeAppActionType)userAction {
196 [_metadata updateWithUserAction:userAction]; 199 [_metadata updateWithUserAction:userAction];
197 } 200 }
198 201
199 #pragma mark - 202 #pragma mark -
200 #pragma mark CRWWebControllerObserver methods 203 #pragma mark CRWWebControllerObserver methods
201 204
202 - (void)pageLoaded:(CRWWebController*)webController { 205 - (void)pageLoaded:(CRWWebController*)webController {
203 if (![_tab isPrerenderTab]) 206 if (![_tab isPrerenderTab])
204 [self showInfoBarIfNecessary]; 207 [self showInfoBarIfNecessary];
205 } 208 }
206 209
207 - (void)webControllerWillClose:(CRWWebController*)webController { 210 - (void)webControllerWillClose:(CRWWebController*)webController {
208 [webController removeObserver:self]; 211 [webController removeObserver:self];
209 } 212 }
210 213
211 - (BOOL)isLinkNavigation {
212 if (![_tab navigationManager])
213 return NO;
214 web::NavigationItem* userItem = [_tab navigationManager]->GetLastUserItem();
215 if (!userItem)
216 return NO;
217 ui::PageTransition currentTransition = userItem->GetTransitionType();
218 return PageTransitionCoreTypeIs(currentTransition,
219 ui::PAGE_TRANSITION_LINK) ||
220 PageTransitionCoreTypeIs(currentTransition,
221 ui::PAGE_TRANSITION_AUTO_BOOKMARK);
222 }
223
224 - (void)appDidInstall:(NSNotification*)notification { 214 - (void)appDidInstall:(NSNotification*)notification {
225 [self removeAppFromNotification:notification]; 215 [self removeAppFromNotification:notification];
226 [self showInfoBarIfNecessary]; 216 [self showInfoBarIfNecessary];
227 } 217 }
228 218
229 - (void)removeAppFromNotification:(NSNotification*)notification { 219 - (void)removeAppFromNotification:(NSNotification*)notification {
230 DCHECK([[notification object] isKindOfClass:[InstallationNotifier class]]); 220 DCHECK([[notification object] isKindOfClass:[InstallationNotifier class]]);
231 NSString* schemeOfInstalledApp = [notification name]; 221 NSString* schemeOfInstalledApp = [notification name];
232 __block NSString* appIDToRemove = nil; 222 __block NSString* appIDToRemove = nil;
233 [_appsPossiblyBeingInstalled 223 [_appsPossiblyBeingInstalled
234 enumerateObjectsUsingBlock:^(id appID, BOOL* stop) { 224 enumerateObjectsUsingBlock:^(id appID, BOOL* stop) {
235 NSURL* appURL = 225 NSURL* appURL =
236 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager() 226 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
237 schemeForAppId:appID]; 227 schemeForAppId:appID];
238 if ([[appURL scheme] isEqualToString:schemeOfInstalledApp]) { 228 if ([[appURL scheme] isEqualToString:schemeOfInstalledApp]) {
239 appIDToRemove = appID; 229 appIDToRemove = appID;
240 *stop = YES; 230 *stop = YES;
241 } 231 }
242 }]; 232 }];
243 DCHECK(appIDToRemove); 233 DCHECK(appIDToRemove);
244 [_appsPossiblyBeingInstalled removeObject:appIDToRemove]; 234 [_appsPossiblyBeingInstalled removeObject:appIDToRemove];
245 } 235 }
246 236
247 @end 237 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698