| 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 |