OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/downloads/download_manager_controller.h" | 5 #import "ios/chrome/browser/ui/downloads/download_manager_controller.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
12 #include "base/ios/weak_nsobject.h" | |
13 #include "base/location.h" | 12 #include "base/location.h" |
14 #include "base/mac/bind_objc_block.h" | 13 #include "base/mac/bind_objc_block.h" |
15 #include "base/mac/objc_property_releaser.h" | 14 |
16 #include "base/mac/scoped_nsobject.h" | |
17 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
18 #include "base/metrics/histogram_macros.h" | 16 #include "base/metrics/histogram_macros.h" |
19 #include "base/metrics/user_metrics.h" | 17 #include "base/metrics/user_metrics.h" |
20 #include "base/metrics/user_metrics_action.h" | 18 #include "base/metrics/user_metrics_action.h" |
21 #include "base/strings/sys_string_conversions.h" | 19 #include "base/strings/sys_string_conversions.h" |
22 #include "base/threading/sequenced_worker_pool.h" | 20 #include "base/threading/sequenced_worker_pool.h" |
23 #include "components/strings/grit/components_strings.h" | 21 #include "components/strings/grit/components_strings.h" |
24 #import "ios/chrome/browser/installation_notifier.h" | 22 #import "ios/chrome/browser/installation_notifier.h" |
25 #include "ios/chrome/browser/native_app_launcher/ios_appstore_ids.h" | 23 #include "ios/chrome/browser/native_app_launcher/ios_appstore_ids.h" |
26 #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" | 24 #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h" |
(...skipping 16 matching lines...) Expand all Loading... |
43 #include "net/base/filename_util.h" | 41 #include "net/base/filename_util.h" |
44 #include "net/http/http_response_headers.h" | 42 #include "net/http/http_response_headers.h" |
45 #include "net/http/http_util.h" | 43 #include "net/http/http_util.h" |
46 #include "net/url_request/url_fetcher.h" | 44 #include "net/url_request/url_fetcher.h" |
47 #include "net/url_request/url_fetcher_delegate.h" | 45 #include "net/url_request/url_fetcher_delegate.h" |
48 #include "net/url_request/url_request_context_getter.h" | 46 #include "net/url_request/url_request_context_getter.h" |
49 #include "net/url_request/url_request_status.h" | 47 #include "net/url_request/url_request_status.h" |
50 #include "ui/base/l10n/l10n_util_mac.h" | 48 #include "ui/base/l10n/l10n_util_mac.h" |
51 #import "ui/gfx/ios/uikit_util.h" | 49 #import "ui/gfx/ios/uikit_util.h" |
52 | 50 |
| 51 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 52 #error "This file requires ARC support." |
| 53 #endif |
| 54 |
53 using base::UserMetricsAction; | 55 using base::UserMetricsAction; |
54 using net::HttpResponseHeaders; | 56 using net::HttpResponseHeaders; |
55 using net::URLFetcher; | 57 using net::URLFetcher; |
56 using net::URLFetcherDelegate; | 58 using net::URLFetcherDelegate; |
57 using net::URLRequestContextGetter; | 59 using net::URLRequestContextGetter; |
58 using net::URLRequestStatus; | 60 using net::URLRequestStatus; |
59 | 61 |
60 @interface DownloadManagerController () | 62 @interface DownloadManagerController () |
61 | 63 |
62 // Creates the portrait and landscape mode constraints that are switched every | 64 // Creates the portrait and landscape mode constraints that are switched every |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 // request to get information about the file. | 326 // request to get information about the file. |
325 class DownloadHeadDelegate : public URLFetcherDelegate { | 327 class DownloadHeadDelegate : public URLFetcherDelegate { |
326 public: | 328 public: |
327 explicit DownloadHeadDelegate(DownloadManagerController* owner) | 329 explicit DownloadHeadDelegate(DownloadManagerController* owner) |
328 : owner_(owner) {} | 330 : owner_(owner) {} |
329 void OnURLFetchComplete(const URLFetcher* source) override { | 331 void OnURLFetchComplete(const URLFetcher* source) override { |
330 [owner_ onHeadFetchComplete]; | 332 [owner_ onHeadFetchComplete]; |
331 }; | 333 }; |
332 | 334 |
333 private: | 335 private: |
334 DownloadManagerController* owner_; // weak. | 336 __weak DownloadManagerController* owner_; |
335 DISALLOW_COPY_AND_ASSIGN(DownloadHeadDelegate); | 337 DISALLOW_COPY_AND_ASSIGN(DownloadHeadDelegate); |
336 }; | 338 }; |
337 | 339 |
338 // URLFetcher delegate that bridges from C++ to this Obj-C class for the | 340 // URLFetcher delegate that bridges from C++ to this Obj-C class for the |
339 // request to download the contents of the file. | 341 // request to download the contents of the file. |
340 class DownloadContentDelegate : public URLFetcherDelegate { | 342 class DownloadContentDelegate : public URLFetcherDelegate { |
341 public: | 343 public: |
342 explicit DownloadContentDelegate(DownloadManagerController* owner) | 344 explicit DownloadContentDelegate(DownloadManagerController* owner) |
343 : owner_(owner) {} | 345 : owner_(owner) {} |
344 void OnURLFetchDownloadProgress(const URLFetcher* source, | 346 void OnURLFetchDownloadProgress(const URLFetcher* source, |
345 int64_t current, | 347 int64_t current, |
346 int64_t total, | 348 int64_t total, |
347 int64_t current_network_bytes) override { | 349 int64_t current_network_bytes) override { |
348 [owner_ onContentFetchProgress:current]; | 350 [owner_ onContentFetchProgress:current]; |
349 } | 351 } |
350 void OnURLFetchComplete(const URLFetcher* source) override { | 352 void OnURLFetchComplete(const URLFetcher* source) override { |
351 [owner_ onContentFetchComplete]; | 353 [owner_ onContentFetchComplete]; |
352 }; | 354 }; |
353 | 355 |
354 private: | 356 private: |
355 DownloadManagerController* owner_; // weak. | 357 __weak DownloadManagerController* owner_; |
356 DISALLOW_COPY_AND_ASSIGN(DownloadContentDelegate); | 358 DISALLOW_COPY_AND_ASSIGN(DownloadContentDelegate); |
357 }; | 359 }; |
358 | 360 |
359 } // namespace | 361 } // namespace |
360 | 362 |
361 @interface DownloadManagerController () { | 363 @interface DownloadManagerController () { |
362 int _downloadManagerId; | 364 int _downloadManagerId; |
363 | 365 |
364 // Coordinator for displaying the alert informing the user that no application | 366 // Coordinator for displaying the alert informing the user that no application |
365 // on the device can open the file. | 367 // on the device can open the file. |
366 base::scoped_nsobject<AlertCoordinator> _alertCoordinator; | 368 AlertCoordinator* _alertCoordinator; |
367 | 369 |
368 // The size of the file to be downloaded, as determined by the Content-Length | 370 // The size of the file to be downloaded, as determined by the Content-Length |
369 // header field in the initial HEAD request. This is set to |kNoFileSizeGiven| | 371 // header field in the initial HEAD request. This is set to |kNoFileSizeGiven| |
370 // if the Content-Length header is not given. | 372 // if the Content-Length header is not given. |
371 long long _totalFileSize; | 373 long long _totalFileSize; |
372 | 374 |
373 // YES if |_fileTypeLabel| is vertically centered in |_documentContainer|. NO | 375 // YES if |_fileTypeLabel| is vertically centered in |_documentContainer|. NO |
374 // if |_fileTypeLabel| is lower to account for another view in | 376 // if |_fileTypeLabel| is lower to account for another view in |
375 // |_documentContainer|. | 377 // |_documentContainer|. |
376 BOOL _isFileTypeLabelCentered; | 378 BOOL _isFileTypeLabelCentered; |
377 BOOL _isDisplayingError; | 379 BOOL _isDisplayingError; |
378 BOOL _didSuccessfullyFinishHeadFetch; | 380 BOOL _didSuccessfullyFinishHeadFetch; |
379 // WebState provides access to the *TabHelper objects. | 381 // WebState provides access to the *TabHelper objects. |
380 web::WebState* _webState; | 382 web::WebState* _webState; |
381 std::unique_ptr<URLFetcher> _fetcher; | 383 std::unique_ptr<URLFetcher> _fetcher; |
382 std::unique_ptr<DownloadHeadDelegate> _headFetcherDelegate; | 384 std::unique_ptr<DownloadHeadDelegate> _headFetcherDelegate; |
383 std::unique_ptr<DownloadContentDelegate> _contentFetcherDelegate; | 385 std::unique_ptr<DownloadContentDelegate> _contentFetcherDelegate; |
384 base::FilePath _downloadFilePath; | 386 base::FilePath _downloadFilePath; |
385 base::scoped_nsobject<MDCActivityIndicator> _activityIndicator; | 387 MDCActivityIndicator* _activityIndicator; |
386 // Set to YES when a download begins and is used to determine if the | 388 // Set to YES when a download begins and is used to determine if the |
387 // DownloadFileResult histogram needs to be recorded on -dealloc. | 389 // DownloadFileResult histogram needs to be recorded on -dealloc. |
388 BOOL _recordDownloadResultHistogram; | 390 BOOL _recordDownloadResultHistogram; |
389 // Set to YES when a file is downloaded and is used to determine if the | 391 // Set to YES when a file is downloaded and is used to determine if the |
390 // DownloadedFileAction histogram needs to be recorded on -dealloc. | 392 // DownloadedFileAction histogram needs to be recorded on -dealloc. |
391 BOOL _recordFileActionHistogram; | 393 BOOL _recordFileActionHistogram; |
392 base::mac::ObjCPropertyReleaser _propertyReleaser_DownloadManagerController; | |
393 } | 394 } |
394 | 395 |
395 // The container that holds the |documentIcon|, the |progressBar|, the | 396 // The container that holds the |documentIcon|, the |progressBar|, the |
396 // |foldIcon|, the |fileTypeLabel|, and the |timeLeftLabel|. | 397 // |foldIcon|, the |fileTypeLabel|, and the |timeLeftLabel|. |
397 @property(nonatomic, retain) IBOutlet UIView* documentContainer; | 398 @property(nonatomic, strong) IBOutlet UIView* documentContainer; |
398 | 399 |
399 // The progress bar that displays download progress. | 400 // The progress bar that displays download progress. |
400 @property(nonatomic, retain) IBOutlet UIView* progressBar; | 401 @property(nonatomic, strong) IBOutlet UIView* progressBar; |
401 | 402 |
402 // The image of the document. | 403 // The image of the document. |
403 @property(nonatomic, retain) IBOutlet UIImageView* documentIcon; | 404 @property(nonatomic, strong) IBOutlet UIImageView* documentIcon; |
404 | 405 |
405 // The image of the document fold. | 406 // The image of the document fold. |
406 @property(nonatomic, retain) IBOutlet UIImageView* foldIcon; | 407 @property(nonatomic, strong) IBOutlet UIImageView* foldIcon; |
407 | 408 |
408 // The error image displayed inside the document. | 409 // The error image displayed inside the document. |
409 @property(nonatomic, retain) IBOutlet UIImageView* errorIcon; | 410 @property(nonatomic, strong) IBOutlet UIImageView* errorIcon; |
410 | 411 |
411 // The label that displays the file type of the file to be downloaded. | 412 // The label that displays the file type of the file to be downloaded. |
412 @property(nonatomic, retain) IBOutlet UILabel* fileTypeLabel; | 413 @property(nonatomic, strong) IBOutlet UILabel* fileTypeLabel; |
413 | 414 |
414 // The label that displays the estimate of how much time is still needed to | 415 // The label that displays the estimate of how much time is still needed to |
415 // finish the file download. | 416 // finish the file download. |
416 @property(nonatomic, retain) IBOutlet UILabel* timeLeftLabel; | 417 @property(nonatomic, strong) IBOutlet UILabel* timeLeftLabel; |
417 | 418 |
418 // The label that displays the name of the file to be downloaded, as it will | 419 // The label that displays the name of the file to be downloaded, as it will |
419 // be saved on the user's device. | 420 // be saved on the user's device. |
420 @property(nonatomic, retain) IBOutlet UILabel* fileNameLabel; | 421 @property(nonatomic, strong) IBOutlet UILabel* fileNameLabel; |
421 | 422 |
422 // The label that displays the size of the file to be downloaded or the error | 423 // The label that displays the size of the file to be downloaded or the error |
423 // message. | 424 // message. |
424 @property(nonatomic, retain) IBOutlet UILabel* errorOrSizeLabel; | 425 @property(nonatomic, strong) IBOutlet UILabel* errorOrSizeLabel; |
425 | 426 |
426 // The label that displays error messages when errors occur. | 427 // The label that displays error messages when errors occur. |
427 @property(nonatomic, retain) IBOutlet UILabel* errorLabel; | 428 @property(nonatomic, strong) IBOutlet UILabel* errorLabel; |
428 | 429 |
429 // The container that holds the |downloadButton|, |cancelButton|, | 430 // The container that holds the |downloadButton|, |cancelButton|, |
430 // |openInButton|, and |googleDriveButton|. | 431 // |openInButton|, and |googleDriveButton|. |
431 @property(nonatomic, retain) IBOutlet UIView* actionBar; | 432 @property(nonatomic, strong) IBOutlet UIView* actionBar; |
432 | 433 |
433 // View that appears at the top of the action bar and acts as a border. | 434 // View that appears at the top of the action bar and acts as a border. |
434 @property(nonatomic, retain) IBOutlet UIView* actionBarBorder; | 435 @property(nonatomic, strong) IBOutlet UIView* actionBarBorder; |
435 | 436 |
436 // The button which starts the file download. | 437 // The button which starts the file download. |
437 @property(nonatomic, retain) IBOutlet MDCButton* downloadButton; | 438 @property(nonatomic, strong) IBOutlet MDCButton* downloadButton; |
438 | 439 |
439 // The button which switches with the |downloadButton| during a download. | 440 // The button which switches with the |downloadButton| during a download. |
440 // Pressing it cancels the download. | 441 // Pressing it cancels the download. |
441 @property(nonatomic, retain) IBOutlet MDCButton* cancelButton; | 442 @property(nonatomic, strong) IBOutlet MDCButton* cancelButton; |
442 | 443 |
443 // The button that switches with the |cancelButton| when a file download | 444 // The button that switches with the |cancelButton| when a file download |
444 // completes. Pressing it opens the UIDocumentInteractionController, letting | 445 // completes. Pressing it opens the UIDocumentInteractionController, letting |
445 // the user select another app in which to open the downloaded file. | 446 // the user select another app in which to open the downloaded file. |
446 @property(nonatomic, retain) IBOutlet MDCButton* openInButton; | 447 @property(nonatomic, strong) IBOutlet MDCButton* openInButton; |
447 | 448 |
448 // The button that opens a view controller to allow the user to install | 449 // The button that opens a view controller to allow the user to install |
449 // Google Drive. | 450 // Google Drive. |
450 @property(nonatomic, retain) IBOutlet MDCButton* googleDriveButton; | 451 @property(nonatomic, strong) IBOutlet MDCButton* googleDriveButton; |
451 | 452 |
452 // The controller that displays the list of other apps that the downloaded file | 453 // The controller that displays the list of other apps that the downloaded file |
453 // can be opened in. | 454 // can be opened in. |
454 @property(nonatomic, retain) | 455 @property(nonatomic, strong) |
455 UIDocumentInteractionController* docInteractionController; | 456 UIDocumentInteractionController* docInteractionController; |
456 | 457 |
457 // Contains all the constraints that should be applied only in portrait mode. | 458 // Contains all the constraints that should be applied only in portrait mode. |
458 @property(nonatomic, retain) NSArray* portraitConstraintsArray; | 459 @property(nonatomic, strong) NSArray* portraitConstraintsArray; |
459 | 460 |
460 // Contains all the constraints that should be applied only in landscape mode. | 461 // Contains all the constraints that should be applied only in landscape mode. |
461 @property(nonatomic, retain) NSArray* landscapeConstraintsArray; | 462 @property(nonatomic, strong) NSArray* landscapeConstraintsArray; |
462 | 463 |
463 // Contains all the constraints that should be applied only in portrait mode | 464 // Contains all the constraints that should be applied only in portrait mode |
464 // when there is only one button showing in the action bar (i.e. the Google | 465 // when there is only one button showing in the action bar (i.e. the Google |
465 // Drive button is NOT showing). | 466 // Drive button is NOT showing). |
466 @property(nonatomic, retain) | 467 @property(nonatomic, strong) |
467 NSArray* portraitActionBarOneButtonConstraintsArray; | 468 NSArray* portraitActionBarOneButtonConstraintsArray; |
468 | 469 |
469 // Contains all the constraints that should be applied only in portrait mode | 470 // Contains all the constraints that should be applied only in portrait mode |
470 // when there are two buttons showing in the action bar (i.e. the Google Drive | 471 // when there are two buttons showing in the action bar (i.e. the Google Drive |
471 // button IS showing). | 472 // button IS showing). |
472 @property(nonatomic, retain) | 473 @property(nonatomic, strong) |
473 NSArray* portraitActionBarTwoButtonConstraintsArray; | 474 NSArray* portraitActionBarTwoButtonConstraintsArray; |
474 | 475 |
475 // Constraint that positions the file type label vertically in the center of the | 476 // Constraint that positions the file type label vertically in the center of the |
476 // document with an additional offset. | 477 // document with an additional offset. |
477 @property(nonatomic, retain) NSLayoutConstraint* fileTypeLabelCentered; | 478 @property(nonatomic, strong) NSLayoutConstraint* fileTypeLabelCentered; |
478 | 479 |
479 // Records the time the download started, to display an estimate of how much | 480 // Records the time the download started, to display an estimate of how much |
480 // time is required to finish the download. | 481 // time is required to finish the download. |
481 @property(nonatomic, retain) NSDate* downloadStartedTime; | 482 @property(nonatomic, strong) NSDate* downloadStartedTime; |
482 | 483 |
483 // Records the fraction (from 0.0 to 1.0) of the file that has been | 484 // Records the fraction (from 0.0 to 1.0) of the file that has been |
484 // downloaded. | 485 // downloaded. |
485 @property(nonatomic) double fractionDownloaded; | 486 @property(nonatomic) double fractionDownloaded; |
486 | 487 |
487 // Used to get a URL scheme that Drive responds to, to register with the | 488 // Used to get a URL scheme that Drive responds to, to register with the |
488 // InstallationNotifier. | 489 // InstallationNotifier. |
489 @property(nonatomic, retain) id<NativeAppMetadata> googleDriveMetadata; | 490 @property(nonatomic, strong) id<NativeAppMetadata> googleDriveMetadata; |
490 | 491 |
491 @end | 492 @end |
492 | 493 |
493 @implementation DownloadManagerController | 494 @implementation DownloadManagerController |
494 | 495 |
495 @synthesize documentContainer = _documentContainer; | 496 @synthesize documentContainer = _documentContainer; |
496 @synthesize progressBar = _progressBar; | 497 @synthesize progressBar = _progressBar; |
497 @synthesize documentIcon = _documentIcon; | 498 @synthesize documentIcon = _documentIcon; |
498 @synthesize foldIcon = _foldIcon; | 499 @synthesize foldIcon = _foldIcon; |
499 @synthesize errorIcon = _errorIcon; | 500 @synthesize errorIcon = _errorIcon; |
(...skipping 18 matching lines...) Expand all Loading... |
518 @synthesize fileTypeLabelCentered = _fileTypeLabelCentered; | 519 @synthesize fileTypeLabelCentered = _fileTypeLabelCentered; |
519 @synthesize downloadStartedTime = _downloadStartedTime; | 520 @synthesize downloadStartedTime = _downloadStartedTime; |
520 @synthesize fractionDownloaded = _fractionDownloaded; | 521 @synthesize fractionDownloaded = _fractionDownloaded; |
521 @synthesize googleDriveMetadata = _googleDriveMetadata; | 522 @synthesize googleDriveMetadata = _googleDriveMetadata; |
522 | 523 |
523 - (instancetype)initWithWebState:(web::WebState*)webState | 524 - (instancetype)initWithWebState:(web::WebState*)webState |
524 downloadURL:(const GURL&)url { | 525 downloadURL:(const GURL&)url { |
525 self = [super initWithNibName:@"DownloadManagerController" url:url]; | 526 self = [super initWithNibName:@"DownloadManagerController" url:url]; |
526 if (self) { | 527 if (self) { |
527 _downloadManagerId = g_download_manager_id++; | 528 _downloadManagerId = g_download_manager_id++; |
528 _propertyReleaser_DownloadManagerController.Init( | |
529 self, [DownloadManagerController class]); | |
530 | 529 |
531 DCHECK(webState); | 530 DCHECK(webState); |
532 _webState = webState; | 531 _webState = webState; |
533 _headFetcherDelegate.reset(new DownloadHeadDelegate(self)); | 532 _headFetcherDelegate.reset(new DownloadHeadDelegate(self)); |
534 _contentFetcherDelegate.reset(new DownloadContentDelegate(self)); | 533 _contentFetcherDelegate.reset(new DownloadContentDelegate(self)); |
535 _downloadFilePath = base::FilePath(); | 534 _downloadFilePath = base::FilePath(); |
536 | 535 |
537 [_documentContainer | 536 [_documentContainer |
538 setBackgroundColor:UIColorFromRGB(kUndownloadedDocumentColor)]; | 537 setBackgroundColor:UIColorFromRGB(kUndownloadedDocumentColor)]; |
539 | 538 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
610 [[InstallationNotifier sharedInstance] unregisterForNotifications:self]; | 609 [[InstallationNotifier sharedInstance] unregisterForNotifications:self]; |
611 [[NetworkActivityIndicatorManager sharedInstance] | 610 [[NetworkActivityIndicatorManager sharedInstance] |
612 clearNetworkTasksForGroup:[self getNetworkActivityKey]]; | 611 clearNetworkTasksForGroup:[self getNetworkActivityKey]]; |
613 [_docInteractionController setDelegate:nil]; | 612 [_docInteractionController setDelegate:nil]; |
614 [_docInteractionController dismissMenuAnimated:NO]; | 613 [_docInteractionController dismissMenuAnimated:NO]; |
615 if (!_downloadFilePath.empty()) { | 614 if (!_downloadFilePath.empty()) { |
616 // A local copy of _downloadFilePath must be made: the instance variable | 615 // A local copy of _downloadFilePath must be made: the instance variable |
617 // will be cleaned up during dealloc, but a local copy will be retained by | 616 // will be cleaned up during dealloc, but a local copy will be retained by |
618 // the block and won't be deleted until the block completes. | 617 // the block and won't be deleted until the block completes. |
619 base::FilePath downloadPathCopy = _downloadFilePath; | 618 base::FilePath downloadPathCopy = _downloadFilePath; |
620 web::WebThread::PostBlockingPoolTask(FROM_HERE, base::BindBlock(^{ | 619 web::WebThread::PostBlockingPoolTask(FROM_HERE, base::BindBlockArc(^{ |
621 DeleteFile(downloadPathCopy, false); | 620 DeleteFile(downloadPathCopy, false); |
622 })); | 621 })); |
623 } | 622 } |
624 if (_recordDownloadResultHistogram) { | 623 if (_recordDownloadResultHistogram) { |
625 UMA_HISTOGRAM_ENUMERATION(kUMADownloadFileResult, DOWNLOAD_OTHER, | 624 UMA_HISTOGRAM_ENUMERATION(kUMADownloadFileResult, DOWNLOAD_OTHER, |
626 DOWNLOAD_FILE_RESULT_COUNT); | 625 DOWNLOAD_FILE_RESULT_COUNT); |
627 } | 626 } |
628 if (_recordFileActionHistogram) { | 627 if (_recordFileActionHistogram) { |
629 UMA_HISTOGRAM_ENUMERATION(kUMADownloadedFileAction, NO_ACTION, | 628 UMA_HISTOGRAM_ENUMERATION(kUMADownloadedFileAction, NO_ACTION, |
630 DOWNLOADED_FILE_ACTION_COUNT); | 629 DOWNLOADED_FILE_ACTION_COUNT); |
631 } | 630 } |
632 [super dealloc]; | |
633 } | 631 } |
634 | 632 |
635 #pragma mark - Layout constraints | 633 #pragma mark - Layout constraints |
636 | 634 |
637 - (void)initConstraints { | 635 - (void)initConstraints { |
638 // Document Container | 636 // Document Container |
639 NSLayoutConstraint* portraitDocumentContainerWidth = | 637 NSLayoutConstraint* portraitDocumentContainerWidth = |
640 [_documentContainer.widthAnchor | 638 [_documentContainer.widthAnchor |
641 constraintEqualToConstant:kDocumentContainerWidthPortrait]; | 639 constraintEqualToConstant:kDocumentContainerWidthPortrait]; |
642 NSLayoutConstraint* portraitDocumentContainerHeight = | 640 NSLayoutConstraint* portraitDocumentContainerHeight = |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1022 UIColorFromRGB(kIndeterminateFileSizeColor); | 1020 UIColorFromRGB(kIndeterminateFileSizeColor); |
1023 _fileTypeLabel.textColor = | 1021 _fileTypeLabel.textColor = |
1024 [UIColor colorWithWhite:0 alpha:kFileTypeLabelBlackAlpha]; | 1022 [UIColor colorWithWhite:0 alpha:kFileTypeLabelBlackAlpha]; |
1025 } | 1023 } |
1026 [_errorOrSizeLabel setHidden:NO]; | 1024 [_errorOrSizeLabel setHidden:NO]; |
1027 | 1025 |
1028 [_downloadButton setHidden:NO]; | 1026 [_downloadButton setHidden:NO]; |
1029 } | 1027 } |
1030 | 1028 |
1031 - (void)initializeActivityIndicator { | 1029 - (void)initializeActivityIndicator { |
1032 _activityIndicator.reset([[MDCActivityIndicator alloc] | 1030 _activityIndicator = [[MDCActivityIndicator alloc] |
1033 initWithFrame:CGRectMake(0, 0, kActivityIndicatorWidth, | 1031 initWithFrame:CGRectMake(0, 0, kActivityIndicatorWidth, |
1034 kActivityIndicatorWidth)]); | 1032 kActivityIndicatorWidth)]; |
1035 [_activityIndicator setRadius:AlignValueToPixel(kActivityIndicatorWidth / 2)]; | 1033 [_activityIndicator setRadius:AlignValueToPixel(kActivityIndicatorWidth / 2)]; |
1036 [_activityIndicator setStrokeWidth:4]; | 1034 [_activityIndicator setStrokeWidth:4]; |
1037 [_activityIndicator | 1035 [_activityIndicator |
1038 setCycleColors:@[ [[MDCPalette cr_bluePalette] tint500] ]]; | 1036 setCycleColors:@[ [[MDCPalette cr_bluePalette] tint500] ]]; |
1039 [_activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; | 1037 [_activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; |
1040 [_documentContainer addSubview:_activityIndicator]; | 1038 [_documentContainer addSubview:_activityIndicator]; |
1041 _activityIndicator.get().center = _documentContainer.center; | 1039 _activityIndicator.center = _documentContainer.center; |
1042 [NSLayoutConstraint activateConstraints:@[ | 1040 [NSLayoutConstraint activateConstraints:@[ |
1043 [[_activityIndicator centerYAnchor] | 1041 [[_activityIndicator centerYAnchor] |
1044 constraintEqualToAnchor:_documentContainer.centerYAnchor], | 1042 constraintEqualToAnchor:_documentContainer.centerYAnchor], |
1045 [[_activityIndicator centerXAnchor] | 1043 [[_activityIndicator centerXAnchor] |
1046 constraintEqualToAnchor:_documentContainer.centerXAnchor], | 1044 constraintEqualToAnchor:_documentContainer.centerXAnchor], |
1047 [[_activityIndicator heightAnchor] | 1045 [[_activityIndicator heightAnchor] |
1048 constraintEqualToConstant:kActivityIndicatorWidth], | 1046 constraintEqualToConstant:kActivityIndicatorWidth], |
1049 [[_activityIndicator widthAnchor] | 1047 [[_activityIndicator widthAnchor] |
1050 constraintEqualToConstant:kActivityIndicatorWidth] | 1048 constraintEqualToConstant:kActivityIndicatorWidth] |
1051 ]]; | 1049 ]]; |
1052 } | 1050 } |
1053 | 1051 |
1054 #pragma mark - Errors | 1052 #pragma mark - Errors |
1055 | 1053 |
1056 - (void)displayUnableToOpenFileDialog { | 1054 - (void)displayUnableToOpenFileDialog { |
1057 // This code is called inside a xib file, I am using the topViewController. | 1055 // This code is called inside a xib file, I am using the topViewController. |
1058 UIViewController* topViewController = | 1056 UIViewController* topViewController = |
1059 [[[UIApplication sharedApplication] keyWindow] rootViewController]; | 1057 [[[UIApplication sharedApplication] keyWindow] rootViewController]; |
1060 | 1058 |
1061 NSString* title = | 1059 NSString* title = |
1062 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_UNABLE_TO_OPEN_FILE); | 1060 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_UNABLE_TO_OPEN_FILE); |
1063 NSString* message = | 1061 NSString* message = |
1064 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_NO_APP_MESSAGE); | 1062 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_NO_APP_MESSAGE); |
1065 | 1063 |
1066 _alertCoordinator.reset([[AlertCoordinator alloc] | 1064 _alertCoordinator = |
1067 initWithBaseViewController:topViewController | 1065 [[AlertCoordinator alloc] initWithBaseViewController:topViewController |
1068 title:title | 1066 title:title |
1069 message:message]); | 1067 message:message]; |
1070 | 1068 |
1071 // |googleDriveMetadata| contains the information necessary to either launch | 1069 // |googleDriveMetadata| contains the information necessary to either launch |
1072 // the Google Drive app or navigate to its StoreKit page. If the metadata is | 1070 // the Google Drive app or navigate to its StoreKit page. If the metadata is |
1073 // not present, do not show the upload button at all. | 1071 // not present, do not show the upload button at all. |
1074 StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState); | 1072 StoreKitTabHelper* tabHelper = StoreKitTabHelper::FromWebState(_webState); |
1075 if (self.googleDriveMetadata && tabHelper) { | 1073 if (self.googleDriveMetadata && tabHelper) { |
1076 NSString* googleDriveButtonTitle = | 1074 NSString* googleDriveButtonTitle = |
1077 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_UPLOAD_TO_GOOGLE_DRIVE); | 1075 l10n_util::GetNSString(IDS_IOS_DOWNLOAD_MANAGER_UPLOAD_TO_GOOGLE_DRIVE); |
1078 base::WeakNSObject<DownloadManagerController> weakSelf(self); | 1076 __weak DownloadManagerController* weakSelf = self; |
1079 [_alertCoordinator addItemWithTitle:googleDriveButtonTitle | 1077 [_alertCoordinator addItemWithTitle:googleDriveButtonTitle |
1080 action:^{ | 1078 action:^{ |
1081 [weakSelf openGoogleDriveInAppStore]; | 1079 [weakSelf openGoogleDriveInAppStore]; |
1082 } | 1080 } |
1083 style:UIAlertActionStyleDefault]; | 1081 style:UIAlertActionStyleDefault]; |
1084 } | 1082 } |
1085 [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL) | 1083 [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL) |
1086 action:nil | 1084 action:nil |
1087 style:UIAlertActionStyleCancel]; | 1085 style:UIAlertActionStyleCancel]; |
1088 | 1086 |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 #pragma mark - Downloading content | 1229 #pragma mark - Downloading content |
1232 | 1230 |
1233 - (void)beginStartingContentDownload { | 1231 - (void)beginStartingContentDownload { |
1234 // Ensure the directory that downloaded files are saved to exists. | 1232 // Ensure the directory that downloaded files are saved to exists. |
1235 base::FilePath downloadsDirectoryPath; | 1233 base::FilePath downloadsDirectoryPath; |
1236 if (![DownloadManagerController | 1234 if (![DownloadManagerController |
1237 fetchDownloadsDirectoryFilePath:&downloadsDirectoryPath]) { | 1235 fetchDownloadsDirectoryFilePath:&downloadsDirectoryPath]) { |
1238 [self displayError]; | 1236 [self displayError]; |
1239 return; | 1237 return; |
1240 } | 1238 } |
1241 base::WeakNSObject<DownloadManagerController> weakSelf(self); | 1239 __weak DownloadManagerController* weakSelf = self; |
1242 base::PostTaskAndReplyWithResult( | 1240 base::PostTaskAndReplyWithResult( |
1243 web::WebThread::GetBlockingPool() | 1241 web::WebThread::GetBlockingPool() |
1244 ->GetTaskRunnerWithShutdownBehavior( | 1242 ->GetTaskRunnerWithShutdownBehavior( |
1245 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN) | 1243 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN) |
1246 .get(), | 1244 .get(), |
1247 FROM_HERE, base::BindBlock(^{ | 1245 FROM_HERE, base::BindBlockArc(^{ |
1248 return CreateDirectory(downloadsDirectoryPath); | 1246 return CreateDirectory(downloadsDirectoryPath); |
1249 }), | 1247 }), |
1250 base::BindBlock(^(bool directoryCreated) { | 1248 base::BindBlockArc(^(bool directoryCreated) { |
1251 [weakSelf finishStartingContentDownload:directoryCreated]; | 1249 [weakSelf finishStartingContentDownload:directoryCreated]; |
1252 })); | 1250 })); |
1253 } | 1251 } |
1254 | 1252 |
1255 - (void)finishStartingContentDownload:(bool)directoryCreated { | 1253 - (void)finishStartingContentDownload:(bool)directoryCreated { |
1256 if (!directoryCreated) { | 1254 if (!directoryCreated) { |
1257 [self displayError]; | 1255 [self displayError]; |
1258 return; | 1256 return; |
1259 } | 1257 } |
1260 base::FilePath downloadsDirectoryPath; | 1258 base::FilePath downloadsDirectoryPath; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 withCompletionAnimation:(BOOL)completionAnimation { | 1290 withCompletionAnimation:(BOOL)completionAnimation { |
1293 CGRect documentIconFrame = [_documentIcon frame]; | 1291 CGRect documentIconFrame = [_documentIcon frame]; |
1294 CGRect oldProgressFrame = [_progressBar frame]; | 1292 CGRect oldProgressFrame = [_progressBar frame]; |
1295 CGRect newProgressFrame = oldProgressFrame; | 1293 CGRect newProgressFrame = oldProgressFrame; |
1296 newProgressFrame.size.height = | 1294 newProgressFrame.size.height = |
1297 self.fractionDownloaded * documentIconFrame.size.height; | 1295 self.fractionDownloaded * documentIconFrame.size.height; |
1298 newProgressFrame.origin.y = | 1296 newProgressFrame.origin.y = |
1299 CGRectGetMaxY(documentIconFrame) - newProgressFrame.size.height; | 1297 CGRectGetMaxY(documentIconFrame) - newProgressFrame.size.height; |
1300 if (animated && | 1298 if (animated && |
1301 newProgressFrame.size.height - oldProgressFrame.size.height > 1) { | 1299 newProgressFrame.size.height - oldProgressFrame.size.height > 1) { |
1302 base::WeakNSObject<UIView> weakProgressBar(_progressBar); | 1300 __weak UIView* weakProgressBar = _progressBar; |
1303 if (completionAnimation) { | 1301 if (completionAnimation) { |
1304 base::WeakNSObject<DownloadManagerController> weakSelf(self); | 1302 __weak DownloadManagerController* weakSelf = self; |
1305 [UIView animateWithDuration:kProgressBarAnimationDuration | 1303 [UIView animateWithDuration:kProgressBarAnimationDuration |
1306 animations:^{ | 1304 animations:^{ |
1307 [weakProgressBar setFrame:newProgressFrame]; | 1305 [weakProgressBar setFrame:newProgressFrame]; |
1308 } | 1306 } |
1309 completion:^(BOOL) { | 1307 completion:^(BOOL) { |
1310 [weakSelf runDownloadCompleteAnimation]; | 1308 [weakSelf runDownloadCompleteAnimation]; |
1311 }]; | 1309 }]; |
1312 } else { | 1310 } else { |
1313 [UIView animateWithDuration:kProgressBarAnimationDuration | 1311 [UIView animateWithDuration:kProgressBarAnimationDuration |
1314 animations:^{ | 1312 animations:^{ |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1354 [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1.0)], | 1352 [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1.0)], |
1355 [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)] | 1353 [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)] |
1356 ]; | 1354 ]; |
1357 NSArray* times = @[ @0.0, @0.33, @0.66, @1.0 ]; | 1355 NSArray* times = @[ @0.0, @0.33, @0.66, @1.0 ]; |
1358 [animation setValues:vals]; | 1356 [animation setValues:vals]; |
1359 [animation setKeyTimes:times]; | 1357 [animation setKeyTimes:times]; |
1360 [animation setDuration:kDownloadCompleteAnimationDuration]; | 1358 [animation setDuration:kDownloadCompleteAnimationDuration]; |
1361 [_documentContainer.layer addAnimation:animation | 1359 [_documentContainer.layer addAnimation:animation |
1362 forKey:kDocumentPopAnimationKey]; | 1360 forKey:kDocumentPopAnimationKey]; |
1363 | 1361 |
1364 base::WeakNSObject<UIImageView> weakFoldIcon(_foldIcon); | 1362 __weak UIImageView* weakFoldIcon = _foldIcon; |
1365 [UIView transitionWithView:_foldIcon | 1363 [UIView transitionWithView:_foldIcon |
1366 duration:kDownloadCompleteAnimationDuration | 1364 duration:kDownloadCompleteAnimationDuration |
1367 options:UIViewAnimationOptionTransitionCrossDissolve | 1365 options:UIViewAnimationOptionTransitionCrossDissolve |
1368 animations:^{ | 1366 animations:^{ |
1369 [weakFoldIcon setImage:[UIImage imageNamed:@"file_icon_fold_complete"]]; | 1367 [weakFoldIcon setImage:[UIImage imageNamed:@"file_icon_fold_complete"]]; |
1370 if (_totalFileSize == kNoFileSizeGiven) { | 1368 if (_totalFileSize == kNoFileSizeGiven) { |
1371 _fileTypeLabel.textColor = | 1369 _fileTypeLabel.textColor = |
1372 [UIColor colorWithWhite:1 alpha:kFileTypeLabelWhiteAlpha]; | 1370 [UIColor colorWithWhite:1 alpha:kFileTypeLabelWhiteAlpha]; |
1373 } | 1371 } |
1374 } | 1372 } |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 return; | 1479 return; |
1482 } | 1480 } |
1483 | 1481 |
1484 base::FilePath filePath; | 1482 base::FilePath filePath; |
1485 bool success = _fetcher->GetResponseAsFilePath(YES, &filePath); | 1483 bool success = _fetcher->GetResponseAsFilePath(YES, &filePath); |
1486 DCHECK(success); | 1484 DCHECK(success); |
1487 NSString* filePathString = base::SysUTF8ToNSString(filePath.value()); | 1485 NSString* filePathString = base::SysUTF8ToNSString(filePath.value()); |
1488 | 1486 |
1489 if (_totalFileSize == kNoFileSizeGiven) { | 1487 if (_totalFileSize == kNoFileSizeGiven) { |
1490 [_activityIndicator stopAnimating]; | 1488 [_activityIndicator stopAnimating]; |
1491 _activityIndicator.reset(); | 1489 _activityIndicator = nil; |
1492 | 1490 |
1493 // Display the file size. | 1491 // Display the file size. |
1494 NSError* error = nil; | 1492 NSError* error = nil; |
1495 NSDictionary* attributes = | 1493 NSDictionary* attributes = |
1496 [[NSFileManager defaultManager] attributesOfItemAtPath:filePathString | 1494 [[NSFileManager defaultManager] attributesOfItemAtPath:filePathString |
1497 error:&error]; | 1495 error:&error]; |
1498 if (!error) { | 1496 if (!error) { |
1499 NSNumber* fileSizeNumber = [attributes objectForKey:NSFileSize]; | 1497 NSNumber* fileSizeNumber = [attributes objectForKey:NSFileSize]; |
1500 NSString* fileSizeText = [NSByteCountFormatter | 1498 NSString* fileSizeText = [NSByteCountFormatter |
1501 stringFromByteCount:[fileSizeNumber longLongValue] | 1499 stringFromByteCount:[fileSizeNumber longLongValue] |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1600 + (BOOL)fetchDownloadsDirectoryFilePath:(base::FilePath*)path { | 1598 + (BOOL)fetchDownloadsDirectoryFilePath:(base::FilePath*)path { |
1601 if (!GetTempDir(path)) { | 1599 if (!GetTempDir(path)) { |
1602 return NO; | 1600 return NO; |
1603 } | 1601 } |
1604 *path = path->Append("downloads"); | 1602 *path = path->Append("downloads"); |
1605 return YES; | 1603 return YES; |
1606 } | 1604 } |
1607 | 1605 |
1608 + (void)clearDownloadsDirectory { | 1606 + (void)clearDownloadsDirectory { |
1609 web::WebThread::PostBlockingPoolTask( | 1607 web::WebThread::PostBlockingPoolTask( |
1610 FROM_HERE, base::BindBlock(^{ | 1608 FROM_HERE, base::BindBlockArc(^{ |
1611 base::FilePath downloadsDirectory; | 1609 base::FilePath downloadsDirectory; |
1612 if (![DownloadManagerController | 1610 if (![DownloadManagerController |
1613 fetchDownloadsDirectoryFilePath:&downloadsDirectory]) { | 1611 fetchDownloadsDirectoryFilePath:&downloadsDirectory]) { |
1614 return; | 1612 return; |
1615 } | 1613 } |
1616 DeleteFile(downloadsDirectory, true); | 1614 DeleteFile(downloadsDirectory, true); |
1617 })); | 1615 })); |
1618 } | 1616 } |
1619 | 1617 |
1620 #pragma mark - UIDocumentInteractionControllerDelegate | 1618 #pragma mark - UIDocumentInteractionControllerDelegate |
(...skipping 21 matching lines...) Expand all Loading... |
1642 | 1640 |
1643 #pragma mark - CRWNativeContent | 1641 #pragma mark - CRWNativeContent |
1644 | 1642 |
1645 - (void)close { | 1643 - (void)close { |
1646 // Makes sure that all outstanding network requests are shut down before | 1644 // Makes sure that all outstanding network requests are shut down before |
1647 // this controller is closed. | 1645 // this controller is closed. |
1648 _fetcher.reset(); | 1646 _fetcher.reset(); |
1649 } | 1647 } |
1650 | 1648 |
1651 @end | 1649 @end |
OLD | NEW |