Chromium Code Reviews| 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 __unsafe_unretained PrintController* owner_; |
|
sdefresne
2017/04/20 13:16:51
Maybe change all __unsafe_unretained to __weak for
stkhapugin
2017/04/20 13:35:10
+1, __unsafe_unretained was probably used here to
gambard
2017/04/20 13:38:26
Done.
| |
| 102 __unsafe_unretained UIViewController* view_controller_; | 104 __unsafe_unretained 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 |