OLD | NEW |
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/ui/print/print_controller.h" | 5 #import "ios/chrome/browser/ui/print/print_controller.h" |
6 | 6 |
7 #import <MobileCoreServices/UTType.h> | 7 #import <MobileCoreServices/UTType.h> |
8 #import <Webkit/Webkit.h> | 8 #import <Webkit/Webkit.h> |
9 | 9 |
10 #include <memory> | 10 #include <memory> |
11 | 11 |
12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
13 #import "base/ios/ios_util.h" | 13 #import "base/ios/ios_util.h" |
14 #import "base/ios/weak_nsobject.h" | |
15 #include "base/location.h" | 14 #include "base/location.h" |
16 #include "base/logging.h" | 15 #include "base/logging.h" |
17 #include "base/mac/bind_objc_block.h" | 16 #include "base/mac/bind_objc_block.h" |
18 #include "base/mac/foundation_util.h" | 17 #include "base/mac/foundation_util.h" |
19 #import "base/mac/scoped_nsobject.h" | |
20 #include "base/memory/ref_counted.h" | 18 #include "base/memory/ref_counted.h" |
21 #include "base/metrics/user_metrics.h" | 19 #include "base/metrics/user_metrics.h" |
22 #include "base/metrics/user_metrics_action.h" | 20 #include "base/metrics/user_metrics_action.h" |
23 #include "components/strings/grit/components_strings.h" | 21 #include "components/strings/grit/components_strings.h" |
24 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" | 22 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" |
25 #import "ios/chrome/browser/ui/alert_coordinator/loading_alert_coordinator.h" | 23 #import "ios/chrome/browser/ui/alert_coordinator/loading_alert_coordinator.h" |
26 #include "ios/chrome/grit/ios_strings.h" | 24 #include "ios/chrome/grit/ios_strings.h" |
27 #include "ios/web/public/web_thread.h" | 25 #include "ios/web/public/web_thread.h" |
28 #import "net/base/mac/url_conversions.h" | 26 #import "net/base/mac/url_conversions.h" |
29 #include "net/http/http_response_headers.h" | 27 #include "net/http/http_response_headers.h" |
30 #include "net/url_request/url_fetcher.h" | 28 #include "net/url_request/url_fetcher.h" |
31 #include "net/url_request/url_fetcher_delegate.h" | 29 #include "net/url_request/url_fetcher_delegate.h" |
32 #include "net/url_request/url_request_context_getter.h" | 30 #include "net/url_request/url_request_context_getter.h" |
33 #include "ui/base/l10n/l10n_util_mac.h" | 31 #include "ui/base/l10n/l10n_util_mac.h" |
34 | 32 |
| 33 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 34 #error "This file requires ARC support." |
| 35 #endif |
| 36 |
35 using net::URLFetcher; | 37 using net::URLFetcher; |
36 using net::URLFetcherDelegate; | 38 using net::URLFetcherDelegate; |
37 using net::URLRequestContextGetter; | 39 using net::URLRequestContextGetter; |
38 | 40 |
39 @interface PrintController () | 41 @interface PrintController () |
40 | 42 |
41 // Presents a UIPrintInteractionController with a default completion handler. | 43 // Presents a UIPrintInteractionController with a default completion handler. |
42 // |isPDF| indicates if |printInteractionController| is being presented to print | 44 // |isPDF| indicates if |printInteractionController| is being presented to print |
43 // a PDF. | 45 // a PDF. |
44 + (void)displayPrintInteractionController: | 46 + (void)displayPrintInteractionController: |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
91 DCHECK(view_controller_); | 93 DCHECK(view_controller_); |
92 [owner_ finishedDownloadingPDF:view_controller_]; | 94 [owner_ finishedDownloadingPDF:view_controller_]; |
93 } | 95 } |
94 | 96 |
95 // The ViewController used to display an error if the download failed. | 97 // The ViewController used to display an error if the download failed. |
96 void SetViewController(UIViewController* view_controller) { | 98 void SetViewController(UIViewController* view_controller) { |
97 view_controller_ = view_controller; | 99 view_controller_ = view_controller; |
98 } | 100 } |
99 | 101 |
100 private: | 102 private: |
101 __unsafe_unretained PrintController* owner_; | 103 __weak PrintController* owner_; |
102 __unsafe_unretained UIViewController* view_controller_; | 104 __weak UIViewController* view_controller_; |
103 DISALLOW_COPY_AND_ASSIGN(PrintPDFFetcherDelegate); | 105 DISALLOW_COPY_AND_ASSIGN(PrintPDFFetcherDelegate); |
104 }; | 106 }; |
105 } // namespace | 107 } // namespace |
106 | 108 |
107 @implementation PrintController { | 109 @implementation PrintController { |
108 // URLFetcher to download the PDF pointed to by the WKWebView. | 110 // URLFetcher to download the PDF pointed to by the WKWebView. |
109 std::unique_ptr<URLFetcher> _fetcher; | 111 std::unique_ptr<URLFetcher> _fetcher; |
110 | 112 |
111 // A delegate to bridge between PrintController and the URLFetcher callback. | 113 // A delegate to bridge between PrintController and the URLFetcher callback. |
112 std::unique_ptr<PrintPDFFetcherDelegate> _fetcherDelegate; | 114 std::unique_ptr<PrintPDFFetcherDelegate> _fetcherDelegate; |
113 | 115 |
114 // Context getter required by the URLFetcher. | 116 // Context getter required by the URLFetcher. |
115 scoped_refptr<URLRequestContextGetter> _requestContextGetter; | 117 scoped_refptr<URLRequestContextGetter> _requestContextGetter; |
116 | 118 |
117 // A dialog which indicates that the print preview is being prepared. It | 119 // A dialog which indicates that the print preview is being prepared. It |
118 // offers a cancel button which will cancel the download. It is created when | 120 // offers a cancel button which will cancel the download. It is created when |
119 // downloading begins and is released when downloading ends (either due to | 121 // downloading begins and is released when downloading ends (either due to |
120 // cancellation or completion). | 122 // cancellation or completion). |
121 base::scoped_nsobject<LoadingAlertCoordinator> _PDFDownloadingDialog; | 123 LoadingAlertCoordinator* _PDFDownloadingDialog; |
122 | 124 |
123 // A dialog which indicates that the print preview failed. | 125 // A dialog which indicates that the print preview failed. |
124 base::scoped_nsobject<AlertCoordinator> _PDFDownloadingErrorDialog; | 126 AlertCoordinator* _PDFDownloadingErrorDialog; |
125 } | 127 } |
126 | 128 |
127 #pragma mark - Class methods. | 129 #pragma mark - Class methods. |
128 | 130 |
129 + (void)displayPrintInteractionController: | 131 + (void)displayPrintInteractionController: |
130 (UIPrintInteractionController*)printInteractionController | 132 (UIPrintInteractionController*)printInteractionController |
131 forPDF:(BOOL)isPDF { | 133 forPDF:(BOOL)isPDF { |
132 void (^completionHandler)(UIPrintInteractionController*, BOOL, NSError*) = ^( | 134 void (^completionHandler)(UIPrintInteractionController*, BOOL, NSError*) = ^( |
133 UIPrintInteractionController* printInteractionController, BOOL completed, | 135 UIPrintInteractionController* printInteractionController, BOOL completed, |
134 NSError* error) { | 136 NSError* error) { |
135 if (error) | 137 if (error) |
136 DLOG(ERROR) << "Air printing error: " << error.description; | 138 DLOG(ERROR) << "Air printing error: " << error.description; |
137 | 139 |
138 // When printing a NSData object given to the | 140 // When printing a NSData object given to the |
139 // UIPrintInteractionController's |printingItem| object, a PDF file | 141 // UIPrintInteractionController's |printingItem| object, a PDF file |
140 // representing the NSData object is created in the app's tmp directory | 142 // representing the NSData object is created in the app's tmp directory |
141 // by the OS and never deleted. So, this workaround deletes PDF files in | 143 // by the OS and never deleted. So, this workaround deletes PDF files in |
142 // tmp now that printing is done. When iOS9 is deprecated, this can | 144 // tmp now that printing is done. When iOS9 is deprecated, this can |
143 // be removed since PDFs will no longer need to be downloaded to print, | 145 // be removed since PDFs will no longer need to be downloaded to print, |
144 // and |printingItem| will no longer be used. | 146 // and |printingItem| will no longer be used. |
145 if (!base::ios::IsRunningOnIOS10OrLater() && isPDF) { | 147 if (!base::ios::IsRunningOnIOS10OrLater() && isPDF) { |
146 web::WebThread::PostBlockingPoolTask( | 148 web::WebThread::PostBlockingPoolTask( |
147 FROM_HERE, base::BindBlock(^{ | 149 FROM_HERE, base::BindBlockArc(^{ |
148 NSFileManager* manager = [NSFileManager defaultManager]; | 150 NSFileManager* manager = [NSFileManager defaultManager]; |
149 NSString* tempDir = NSTemporaryDirectory(); | 151 NSString* tempDir = NSTemporaryDirectory(); |
150 NSError* tempDirError = nil; | 152 NSError* tempDirError = nil; |
151 | 153 |
152 // Iterate over files in tmp directory. | 154 // Iterate over files in tmp directory. |
153 for (NSString* file in | 155 for (NSString* file in |
154 [manager contentsOfDirectoryAtPath:tempDir | 156 [manager contentsOfDirectoryAtPath:tempDir |
155 error:&tempDirError]) { | 157 error:&tempDirError]) { |
156 // If the file is a PDF file, delete it. | 158 // If the file is a PDF file, delete it. |
157 if ([[file pathExtension] isEqualToString:@"pdf"]) { | 159 if ([[file pathExtension] isEqualToString:@"pdf"]) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 [self downloadPDFFileWithURL:net::GURLWithNSURL(URL) | 230 [self downloadPDFFileWithURL:net::GURLWithNSURL(URL) |
229 viewController:viewController]; | 231 viewController:viewController]; |
230 } | 232 } |
231 CFRelease(MIMEType); | 233 CFRelease(MIMEType); |
232 } | 234 } |
233 CFRelease(UTI); | 235 CFRelease(UTI); |
234 } | 236 } |
235 } | 237 } |
236 | 238 |
237 if (!isPDFURL) { | 239 if (!isPDFURL) { |
238 base::scoped_nsobject<UIPrintPageRenderer> renderer( | 240 UIPrintPageRenderer* renderer = [[UIPrintPageRenderer alloc] init]; |
239 [[UIPrintPageRenderer alloc] init]); | |
240 [renderer addPrintFormatter:[view viewPrintFormatter] | 241 [renderer addPrintFormatter:[view viewPrintFormatter] |
241 startingAtPageAtIndex:0]; | 242 startingAtPageAtIndex:0]; |
242 printInteractionController.printPageRenderer = renderer; | 243 printInteractionController.printPageRenderer = renderer; |
243 [PrintController | 244 [PrintController |
244 displayPrintInteractionController:printInteractionController | 245 displayPrintInteractionController:printInteractionController |
245 forPDF:NO]; | 246 forPDF:NO]; |
246 } | 247 } |
247 } | 248 } |
248 | 249 |
249 - (void)dismissAnimated:(BOOL)animated { | 250 - (void)dismissAnimated:(BOOL)animated { |
250 _fetcher.reset(); | 251 _fetcher.reset(); |
251 [self dismissPDFDownloadingDialog]; | 252 [self dismissPDFDownloadingDialog]; |
252 [_PDFDownloadingErrorDialog stop]; | 253 [_PDFDownloadingErrorDialog stop]; |
253 _PDFDownloadingErrorDialog.reset(); | 254 _PDFDownloadingErrorDialog = nil; |
254 [[UIPrintInteractionController sharedPrintController] | 255 [[UIPrintInteractionController sharedPrintController] |
255 dismissAnimated:animated]; | 256 dismissAnimated:animated]; |
256 } | 257 } |
257 | 258 |
258 #pragma mark - Private Methods | 259 #pragma mark - Private Methods |
259 | 260 |
260 - (void)showPDFDownloadingDialog:(UIViewController*)viewController { | 261 - (void)showPDFDownloadingDialog:(UIViewController*)viewController { |
261 if (_PDFDownloadingDialog) | 262 if (_PDFDownloadingDialog) |
262 return; | 263 return; |
263 | 264 |
264 NSString* title = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_PREPARATION); | 265 NSString* title = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_PREPARATION); |
265 | 266 |
266 base::WeakNSObject<PrintController> weakSelf(self); | 267 __weak PrintController* weakSelf = self; |
267 ProceduralBlock cancelHandler = ^{ | 268 ProceduralBlock cancelHandler = ^{ |
268 base::scoped_nsobject<PrintController> strongSelf([weakSelf retain]); | 269 PrintController* strongSelf = weakSelf; |
269 if (strongSelf) | 270 if (strongSelf) |
270 strongSelf.get()->_fetcher.reset(); | 271 strongSelf->_fetcher.reset(); |
271 }; | 272 }; |
272 | 273 |
273 _PDFDownloadingDialog.reset([[LoadingAlertCoordinator alloc] | 274 _PDFDownloadingDialog = [[LoadingAlertCoordinator alloc] |
274 initWithBaseViewController:viewController | 275 initWithBaseViewController:viewController |
275 title:title | 276 title:title |
276 cancelHandler:cancelHandler]); | 277 cancelHandler:cancelHandler]; |
277 | 278 |
278 dispatch_after( | 279 dispatch_after( |
279 dispatch_time(DISPATCH_TIME_NOW, kPDFDownloadDialogDelay * NSEC_PER_SEC), | 280 dispatch_time(DISPATCH_TIME_NOW, kPDFDownloadDialogDelay * NSEC_PER_SEC), |
280 dispatch_get_main_queue(), ^{ | 281 dispatch_get_main_queue(), ^{ |
281 base::scoped_nsobject<PrintController> strongSelf([weakSelf retain]); | 282 PrintController* strongSelf = weakSelf; |
282 if (!strongSelf) | 283 if (!strongSelf) |
283 return; | 284 return; |
284 [strongSelf.get()->_PDFDownloadingDialog start]; | 285 [strongSelf->_PDFDownloadingDialog start]; |
285 }); | 286 }); |
286 } | 287 } |
287 | 288 |
288 - (void)dismissPDFDownloadingDialog { | 289 - (void)dismissPDFDownloadingDialog { |
289 [_PDFDownloadingDialog stop]; | 290 [_PDFDownloadingDialog stop]; |
290 _PDFDownloadingDialog.reset(); | 291 _PDFDownloadingDialog = nil; |
291 } | 292 } |
292 | 293 |
293 - (void)showPDFDownloadErrorWithURL:(const GURL)URL | 294 - (void)showPDFDownloadErrorWithURL:(const GURL)URL |
294 viewController:(UIViewController*)viewController { | 295 viewController:(UIViewController*)viewController { |
295 NSString* title = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_ERROR_TITLE); | 296 NSString* title = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_ERROR_TITLE); |
296 NSString* message = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_ERROR_SUBTITLE); | 297 NSString* message = l10n_util::GetNSString(IDS_IOS_PRINT_PDF_ERROR_SUBTITLE); |
297 | 298 |
298 _PDFDownloadingErrorDialog.reset([[AlertCoordinator alloc] | 299 _PDFDownloadingErrorDialog = |
299 initWithBaseViewController:viewController | 300 [[AlertCoordinator alloc] initWithBaseViewController:viewController |
300 title:title | 301 title:title |
301 message:message]); | 302 message:message]; |
302 | 303 |
303 base::WeakNSObject<PrintController> weakSelf(self); | 304 __weak PrintController* weakSelf = self; |
304 | 305 |
305 [_PDFDownloadingErrorDialog | 306 [_PDFDownloadingErrorDialog |
306 addItemWithTitle:l10n_util::GetNSString(IDS_IOS_PRINT_PDF_TRY_AGAIN) | 307 addItemWithTitle:l10n_util::GetNSString(IDS_IOS_PRINT_PDF_TRY_AGAIN) |
307 action:^{ | 308 action:^{ |
308 [weakSelf downloadPDFFileWithURL:URL | 309 [weakSelf downloadPDFFileWithURL:URL |
309 viewController:viewController]; | 310 viewController:viewController]; |
310 } | 311 } |
311 style:UIAlertActionStyleDefault]; | 312 style:UIAlertActionStyleDefault]; |
312 | 313 |
313 [_PDFDownloadingErrorDialog | 314 [_PDFDownloadingErrorDialog |
(...skipping 10 matching lines...) Expand all Loading... |
324 _fetcherDelegate->SetViewController(viewController); | 325 _fetcherDelegate->SetViewController(viewController); |
325 _fetcher = URLFetcher::Create(URL, URLFetcher::GET, _fetcherDelegate.get()); | 326 _fetcher = URLFetcher::Create(URL, URLFetcher::GET, _fetcherDelegate.get()); |
326 _fetcher->SetRequestContext(_requestContextGetter.get()); | 327 _fetcher->SetRequestContext(_requestContextGetter.get()); |
327 _fetcher->Start(); | 328 _fetcher->Start(); |
328 [self showPDFDownloadingDialog:viewController]; | 329 [self showPDFDownloadingDialog:viewController]; |
329 } | 330 } |
330 | 331 |
331 - (void)finishedDownloadingPDF:(UIViewController*)viewController { | 332 - (void)finishedDownloadingPDF:(UIViewController*)viewController { |
332 [self dismissPDFDownloadingDialog]; | 333 [self dismissPDFDownloadingDialog]; |
333 DCHECK(_fetcher); | 334 DCHECK(_fetcher); |
334 base::ScopedClosureRunner fetcherResetter(base::BindBlock(^{ | 335 base::ScopedClosureRunner fetcherResetter(base::BindBlockArc(^{ |
335 _fetcher.reset(); | 336 _fetcher.reset(); |
336 })); | 337 })); |
337 int responseCode = _fetcher->GetResponseCode(); | 338 int responseCode = _fetcher->GetResponseCode(); |
338 std::string response; | 339 std::string response; |
339 std::string MIMEType; | 340 std::string MIMEType; |
340 // If the request is not successful or does not match a PDF | 341 // If the request is not successful or does not match a PDF |
341 // MIME type, show an error. | 342 // MIME type, show an error. |
342 if (!_fetcher->GetStatus().is_success() || responseCode != 200 || | 343 if (!_fetcher->GetStatus().is_success() || responseCode != 200 || |
343 !_fetcher->GetResponseAsString(&response) || | 344 !_fetcher->GetResponseAsString(&response) || |
344 !_fetcher->GetResponseHeaders()->GetMimeType(&MIMEType) || | 345 !_fetcher->GetResponseHeaders()->GetMimeType(&MIMEType) || |
(...skipping 11 matching lines...) Expand all Loading... |
356 return; | 357 return; |
357 } | 358 } |
358 UIPrintInteractionController* printInteractionController = | 359 UIPrintInteractionController* printInteractionController = |
359 [UIPrintInteractionController sharedPrintController]; | 360 [UIPrintInteractionController sharedPrintController]; |
360 printInteractionController.printingItem = data; | 361 printInteractionController.printingItem = data; |
361 [PrintController displayPrintInteractionController:printInteractionController | 362 [PrintController displayPrintInteractionController:printInteractionController |
362 forPDF:YES]; | 363 forPDF:YES]; |
363 } | 364 } |
364 | 365 |
365 @end | 366 @end |
OLD | NEW |