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

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

Issue 2897213002: Removed NativeAppNavigationController and related code (Closed)
Patch Set: rebase Created 3 years, 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller .h"
6
7 #import <StoreKit/StoreKit.h>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/metrics/user_metrics.h"
11 #include "base/metrics/user_metrics_action.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "components/image_fetcher/ios/ios_image_data_fetcher_wrapper.h"
14 #include "components/infobars/core/infobar_manager.h"
15 #include "ios/chrome/browser/infobars/infobar_manager_impl.h"
16 #import "ios/chrome/browser/installation_notifier.h"
17 #include "ios/chrome/browser/native_app_launcher/native_app_infobar_delegate.h"
18 #import "ios/chrome/browser/native_app_launcher/native_app_navigation_controller _protocol.h"
19 #include "ios/chrome/browser/native_app_launcher/native_app_navigation_util.h"
20 #import "ios/chrome/browser/open_url_util.h"
21 #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h"
22 #import "ios/chrome/browser/tabs/legacy_tab_helper.h"
23 #import "ios/chrome/browser/tabs/tab.h"
24 #include "ios/public/provider/chrome/browser/chrome_browser_provider.h"
25 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_metad ata.h"
26 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_types .h"
27 #import "ios/public/provider/chrome/browser/native_app_launcher/native_app_white list_manager.h"
28 #include "ios/web/public/browser_state.h"
29 #include "ios/web/public/web_state/web_state.h"
30 #import "ios/web/public/web_state/web_state_observer_bridge.h"
31 #include "ios/web/public/web_thread.h"
32 #import "net/base/mac/url_conversions.h"
33
34 #if !defined(__has_feature) || !__has_feature(objc_arc)
35 #error "This file requires ARC support."
36 #endif
37
38 using base::UserMetricsAction;
39
40 @interface NativeAppNavigationController ()<
41 CRWWebStateObserver,
42 NativeAppNavigationControllerProtocol>
43 // Shows a native app infobar by looking at the page's URL and by checking
44 // wheter that infobar should be bypassed or not.
45 - (void)showInfoBarIfNecessary;
46
47 // Returns a pointer to the NSMutableSet of |_appsPossiblyBeingInstalled|
48 - (NSMutableSet*)appsPossiblyBeingInstalled;
49
50 // Records what type of infobar was opened.
51 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
52 onLinkNavigation:(BOOL)isLinkNavigation;
53
54 @end
55
56 @implementation NativeAppNavigationController {
57 // WebState provides access to the *TabHelper objects.
58 web::WebState* _webState;
59 // ImageFetcher needed to fetch the icons.
60 std::unique_ptr<image_fetcher::IOSImageDataFetcherWrapper> _imageFetcher;
61 id<NativeAppMetadata> _metadata;
62 // A set of appIds encoded as NSStrings.
63 NSMutableSet* _appsPossiblyBeingInstalled;
64 // Allows this class to subscribe for CRWWebStateObserver callbacks.
65 std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
66 }
67
68 // Designated initializer. Use this instead of -init.
69 - (instancetype)initWithWebState:(web::WebState*)webState {
70 self = [super init];
71 if (self) {
72 DCHECK(webState);
73 _webState = webState;
74 _imageFetcher = base::MakeUnique<image_fetcher::IOSImageDataFetcherWrapper>(
75 _webState->GetBrowserState()->GetRequestContext(),
76 web::WebThread::GetBlockingPool());
77 _appsPossiblyBeingInstalled = [[NSMutableSet alloc] init];
78 _webStateObserver =
79 base::MakeUnique<web::WebStateObserverBridge>(webState, self);
80 }
81 return self;
82 }
83
84 - (void)copyStateFrom:(NativeAppNavigationController*)controller {
85 DCHECK(controller);
86 _appsPossiblyBeingInstalled = [[NSMutableSet alloc]
87 initWithSet:[controller appsPossiblyBeingInstalled]];
88 for (NSString* appIdString in _appsPossiblyBeingInstalled) {
89 DCHECK([appIdString isKindOfClass:[NSString class]]);
90 NSURL* appURL =
91 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
92 schemeForAppId:appIdString];
93 [[InstallationNotifier sharedInstance]
94 registerForInstallationNotifications:self
95 withSelector:@selector(appDidInstall:)
96 forScheme:[appURL scheme]];
97 }
98 [self showInfoBarIfNecessary];
99 }
100
101 - (void)dealloc {
102 [[InstallationNotifier sharedInstance] unregisterForNotifications:self];
103 }
104
105 - (NSMutableSet*)appsPossiblyBeingInstalled {
106 return _appsPossiblyBeingInstalled;
107 }
108
109 - (void)showInfoBarIfNecessary {
110 // Find a potential matching native app.
111 GURL pageURL = _webState->GetLastCommittedURL();
112 _metadata = [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
113 nativeAppForURL:pageURL];
114 if (!_metadata || [_metadata shouldBypassInfoBars])
115 return;
116
117 // Select the infobar type.
118 NativeAppControllerType type;
119 bool isLinkNavigation = native_app_launcher::IsLinkNavigation(_webState);
120 if ([_metadata canOpenURL:pageURL]) { // App is installed.
121 type = isLinkNavigation && ![_metadata shouldAutoOpenLinks]
122 ? NATIVE_APP_OPEN_POLICY_CONTROLLER
123 : NATIVE_APP_LAUNCHER_CONTROLLER;
124 } else { // App is not installed.
125 // Check if the user already opened the store for this app.
126 if ([_appsPossiblyBeingInstalled containsObject:[_metadata appId]])
127 return;
128 type = NATIVE_APP_INSTALLER_CONTROLLER;
129 }
130 // Inform the metadata that an infobar of |type| will be shown so that metrics
131 // and ignored behavior can be handled.
132 [_metadata willBeShownInInfobarOfType:type];
133 // Display the proper infobar.
134 infobars::InfoBarManager* infoBarManager =
135 InfoBarManagerImpl::FromWebState(_webState);
136 NativeAppInfoBarDelegate::Create(infoBarManager, self, pageURL, type);
137 [self recordInfobarDisplayedOfType:type onLinkNavigation:isLinkNavigation];
138 }
139
140 - (void)recordInfobarDisplayedOfType:(NativeAppControllerType)type
141 onLinkNavigation:(BOOL)isLinkNavigation {
142 switch (type) {
143 case NATIVE_APP_INSTALLER_CONTROLLER:
144 base::RecordAction(
145 isLinkNavigation
146 ? UserMetricsAction("MobileGALInstallInfoBarLinkNavigation")
147 : UserMetricsAction("MobileGALInstallInfoBarDirectNavigation"));
148 break;
149 case NATIVE_APP_LAUNCHER_CONTROLLER:
150 base::RecordAction(UserMetricsAction("MobileGALLaunchInfoBar"));
151 break;
152 case NATIVE_APP_OPEN_POLICY_CONTROLLER:
153 base::RecordAction(UserMetricsAction("MobileGALOpenPolicyInfoBar"));
154 break;
155 default:
156 NOTREACHED();
157 break;
158 }
159 }
160
161 #pragma mark - NativeAppNavigationControllerProtocol methods
162
163 - (NSString*)appId {
164 return [_metadata appId];
165 }
166
167 - (NSString*)appName {
168 return [_metadata appName];
169 }
170
171 - (void)fetchSmallIconWithCompletionBlock:(void (^)(UIImage*))block {
172 [_metadata fetchSmallIconWithImageFetcher:_imageFetcher.get()
173 completionBlock:block];
174 }
175
176 - (void)openStore {
177 // Register to get a notification when the app is installed.
178 [[InstallationNotifier sharedInstance]
179 registerForInstallationNotifications:self
180 withSelector:@selector(appDidInstall:)
181 forScheme:[_metadata anyScheme]];
182 NSString* appIdString = [self appId];
183 // Defensively early return if native app metadata returns an nil string for
184 // appId which can cause subsequent -addObject: to throw exceptions.
185 if (![appIdString length])
186 return;
187 DCHECK(![_appsPossiblyBeingInstalled containsObject:appIdString]);
188 [_appsPossiblyBeingInstalled addObject:appIdString];
189 StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState);
190 if (tabHelper)
191 tabHelper->OpenAppStore(appIdString);
192 }
193
194 - (void)launchApp:(const GURL&)URL {
195 // TODO(crbug.com/353957): Pass the ChromeIdentity to
196 // -launchURLWithURL:identity:
197 GURL launchURL([_metadata launchURLWithURL:URL identity:nil]);
198 if (launchURL.is_valid()) {
199 OpenUrlWithCompletionHandler(net::NSURLWithGURL(launchURL), nil);
200 }
201 }
202
203 - (void)updateMetadataWithUserAction:(NativeAppActionType)userAction {
204 [_metadata updateWithUserAction:userAction];
205 }
206
207 #pragma mark - CRWWebStateObserver methods
208
209 - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success {
210 Tab* tab = LegacyTabHelper::GetTabForWebState(_webState);
211 if (success && ![tab isPrerenderTab])
212 [self showInfoBarIfNecessary];
213 }
214
215 - (void)webStateDestroyed:(web::WebState*)webState {
216 _webState = nullptr;
217 _webStateObserver.reset();
218 }
219
220 #pragma mark - Private methods
221
222 - (void)appDidInstall:(NSNotification*)notification {
223 [self removeAppFromNotification:notification];
224 [self showInfoBarIfNecessary];
225 }
226
227 - (void)removeAppFromNotification:(NSNotification*)notification {
228 DCHECK([[notification object] isKindOfClass:[InstallationNotifier class]]);
229 NSString* schemeOfInstalledApp = [notification name];
230 __block NSString* appIDToRemove = nil;
231 [_appsPossiblyBeingInstalled
232 enumerateObjectsUsingBlock:^(id appID, BOOL* stop) {
233 NSURL* appURL =
234 [ios::GetChromeBrowserProvider()->GetNativeAppWhitelistManager()
235 schemeForAppId:appID];
236 if ([[appURL scheme] isEqualToString:schemeOfInstalledApp]) {
237 appIDToRemove = appID;
238 *stop = YES;
239 }
240 }];
241 DCHECK(appIDToRemove);
242 [_appsPossiblyBeingInstalled removeObject:appIDToRemove];
243 }
244
245 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698