Commit 6bd3f30a authored by Eugene But's avatar Eugene But Committed by Commit Bot

Add Download.IOSDownloadedFileAction UMA to New Download Manager.

This is an existing histogram logged for the Old Download Manager.
The histogram is already a part of histograms.xml file.

Bug: 791806
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: I13a650e612384d9ba3c026fd7e80d3275c2525ae
Reviewed-on: https://chromium-review.googlesource.com/971805
Commit-Queue: Eugene But <eugenebut@chromium.org>
Reviewed-by: default avatarSylvain Defresne <sdefresne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544749}
parent 4819d080
...@@ -9,4 +9,17 @@ ...@@ -9,4 +9,17 @@
// app is installed after presenting Store Kit dialog from the Download Manager. // app is installed after presenting Store Kit dialog from the Download Manager.
extern const char kDownloadManagerGoogleDriveInstalled[]; extern const char kDownloadManagerGoogleDriveInstalled[];
// Values of the UMA Download.IOSDownloadedFileAction histogram. This enum is
// append only.
enum class DownloadedFileAction {
// Downloaded file was uploaded to Google Drive.
OpenedInDrive = 0,
// Downloaded file was open in the app other than Google Drive.
OpenedInOtherApp = 1,
// Downloaded file was discarded (the user closed the app, tab, or download
// manager UI).
NoAction = 2,
Count,
};
#endif // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_METRIC_NAMES_H_ #endif // IOS_CHROME_BROWSER_DOWNLOAD_DOWNLOAD_MANAGER_METRIC_NAMES_H_
...@@ -16,6 +16,9 @@ extern NSString* const kGoogleDriveITunesItemIdentifier; ...@@ -16,6 +16,9 @@ extern NSString* const kGoogleDriveITunesItemIdentifier;
// app is installed. // app is installed.
extern NSString* const kGoogleDriveAppURLScheme; extern NSString* const kGoogleDriveAppURLScheme;
// Bundle ID of Google Drive application.
extern NSString* const kGoogleDriveAppBundleID;
// Returns URL which can be used to check if Google Drive app is installed via // Returns URL which can be used to check if Google Drive app is installed via
// -[UIApplication canOpenURL:] call. // -[UIApplication canOpenURL:] call.
NSURL* GetGoogleDriveAppUrl(); NSURL* GetGoogleDriveAppUrl();
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
NSString* const kGoogleDriveITunesItemIdentifier = @"507874739"; NSString* const kGoogleDriveITunesItemIdentifier = @"507874739";
NSString* const kGoogleDriveAppURLScheme = @"googledrive"; NSString* const kGoogleDriveAppURLScheme = @"googledrive";
NSString* const kGoogleDriveAppBundleID = @"com.google.Drive";
NSURL* GetGoogleDriveAppUrl() { NSURL* GetGoogleDriveAppUrl() {
NSURLComponents* google_drive_url = [[NSURLComponents alloc] init]; NSURLComponents* google_drive_url = [[NSURLComponents alloc] init];
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#import "base/logging.h" #import "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics.h"
#include "base/metrics/user_metrics_action.h" #include "base/metrics/user_metrics_action.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
...@@ -30,9 +31,33 @@ ...@@ -30,9 +31,33 @@
#error "This file requires ARC support." #error "This file requires ARC support."
#endif #endif
namespace {
// Tracks download tasks which were not opened by the user yet. Reports various
// metrics in DownloadTaskObserver callbacks.
class UnopenedDownloadsTracker : public web::DownloadTaskObserver {
public:
// Starts tracking this download task.
void Add(web::DownloadTask* task) { task->AddObserver(this); }
// Stops tracking this download task.
void Remove(web::DownloadTask* task) { task->RemoveObserver(this); }
// DownloadTaskObserver overrides:
void OnDownloadDestroyed(web::DownloadTask* task) override {
// This download task was never open by the user.
task->RemoveObserver(this);
if (task->IsDone() && task->GetErrorCode() == net::OK) {
UMA_HISTOGRAM_ENUMERATION("Download.IOSDownloadedFileAction",
DownloadedFileAction::NoAction,
DownloadedFileAction::Count);
}
}
};
} // namespace
@interface DownloadManagerCoordinator ()< @interface DownloadManagerCoordinator ()<
ContainedPresenterDelegate, ContainedPresenterDelegate,
DownloadManagerViewControllerDelegate> { DownloadManagerViewControllerDelegate,
UIDocumentInteractionControllerDelegate> {
// View controller for presenting Download Manager UI. // View controller for presenting Download Manager UI.
DownloadManagerViewController* _viewController; DownloadManagerViewController* _viewController;
// A dialog which requests a confirmation from the user. // A dialog which requests a confirmation from the user.
...@@ -41,6 +66,7 @@ ...@@ -41,6 +66,7 @@
UIDocumentInteractionController* _openInController; UIDocumentInteractionController* _openInController;
DownloadManagerMediator _mediator; DownloadManagerMediator _mediator;
StoreKitCoordinator* _storeKitCoordinator; StoreKitCoordinator* _storeKitCoordinator;
UnopenedDownloadsTracker _unopenedDownloads;
} }
@end @end
...@@ -61,6 +87,7 @@ ...@@ -61,6 +87,7 @@
_viewController.delegate = self; _viewController.delegate = self;
_mediator.SetDownloadTask(_downloadTask); _mediator.SetDownloadTask(_downloadTask);
_mediator.SetConsumer(_viewController); _mediator.SetConsumer(_viewController);
_unopenedDownloads.Add(_downloadTask);
self.presenter.baseViewController = self.baseViewController; self.presenter.baseViewController = self.baseViewController;
self.presenter.presentedViewController = _viewController; self.presenter.presentedViewController = _viewController;
...@@ -144,6 +171,19 @@ ...@@ -144,6 +171,19 @@
[self start]; [self start];
} }
#pragma mark - UIDocumentInteractionControllerDelegate
- (void)documentInteractionController:
(UIDocumentInteractionController*)controller
willBeginSendingToApplication:(NSString*)applicationID {
DownloadedFileAction action = [applicationID isEqual:kGoogleDriveAppBundleID]
? DownloadedFileAction::OpenedInDrive
: DownloadedFileAction::OpenedInOtherApp;
UMA_HISTOGRAM_ENUMERATION("Download.IOSDownloadedFileAction", action,
DownloadedFileAction::Count);
_unopenedDownloads.Remove(_downloadTask);
}
#pragma mark - ContainedPresenterDelegate #pragma mark - ContainedPresenterDelegate
- (void)containedPresenterDidDismiss:(id<ContainedPresenter>)presenter { - (void)containedPresenterDidDismiss:(id<ContainedPresenter>)presenter {
...@@ -203,6 +243,7 @@ ...@@ -203,6 +243,7 @@
NSURL* URL = [NSURL fileURLWithPath:base::SysUTF8ToNSString(path.value())]; NSURL* URL = [NSURL fileURLWithPath:base::SysUTF8ToNSString(path.value())];
_openInController = _openInController =
[UIDocumentInteractionController interactionControllerWithURL:URL]; [UIDocumentInteractionController interactionControllerWithURL:URL];
_openInController.delegate = self;
BOOL menuShown = BOOL menuShown =
[_openInController presentOpenInMenuFromRect:layoutGuide.layoutFrame [_openInController presentOpenInMenuFromRect:layoutGuide.layoutFrame
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/mac/foundation_util.h" #include "base/mac/foundation_util.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "base/test/histogram_tester.h"
#include "base/test/user_action_tester.h" #include "base/test/user_action_tester.h"
#include "ios/chrome/browser/download/download_directory_util.h" #include "ios/chrome/browser/download/download_directory_util.h"
#include "ios/chrome/browser/download/download_manager_metric_names.h" #include "ios/chrome/browser/download/download_manager_metric_names.h"
...@@ -105,6 +106,7 @@ class DownloadManagerCoordinatorTest : public PlatformTest { ...@@ -105,6 +106,7 @@ class DownloadManagerCoordinatorTest : public PlatformTest {
id application_; id application_;
DownloadManagerCoordinator* coordinator_; DownloadManagerCoordinator* coordinator_;
base::UserActionTester user_action_tester_; base::UserActionTester user_action_tester_;
base::HistogramTester histogram_tester_;
}; };
// Tests starting the coordinator. Verifies that view controller is presented // Tests starting the coordinator. Verifies that view controller is presented
...@@ -355,11 +357,12 @@ TEST_F(DownloadManagerCoordinatorTest, InstallDrive) { ...@@ -355,11 +357,12 @@ TEST_F(DownloadManagerCoordinatorTest, InstallDrive) {
})); }));
} }
// Tests presenting Open In... menu. // Tests presenting Open In... menu without actually opening the download.
TEST_F(DownloadManagerCoordinatorTest, OpenIn) { TEST_F(DownloadManagerCoordinatorTest, OpenIn) {
web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType); auto task =
task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName)); std::make_unique<web::FakeDownloadTask>(GURL(kTestUrl), kTestMimeType);
coordinator_.downloadTask = &task; task->SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
coordinator_.downloadTask = task.get();
[coordinator_ start]; [coordinator_ start];
EXPECT_EQ(1U, base_view_controller_.childViewControllers.count); EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
...@@ -370,9 +373,9 @@ TEST_F(DownloadManagerCoordinatorTest, OpenIn) { ...@@ -370,9 +373,9 @@ TEST_F(DownloadManagerCoordinatorTest, OpenIn) {
// Start and complete the download. // Start and complete the download.
base::FilePath path; base::FilePath path;
ASSERT_TRUE(base::GetTempDir(&path)); ASSERT_TRUE(base::GetTempDir(&path));
task.Start(std::make_unique<net::URLFetcherFileWriter>( task->Start(std::make_unique<net::URLFetcherFileWriter>(
base::ThreadTaskRunnerHandle::Get(), path)); base::ThreadTaskRunnerHandle::Get(), path));
task.SetDone(true); task->SetDone(true);
// Stub UIDocumentInteractionController. // Stub UIDocumentInteractionController.
FakeDocumentInteractionController* document_interaction_controller = FakeDocumentInteractionController* document_interaction_controller =
...@@ -397,6 +400,110 @@ TEST_F(DownloadManagerCoordinatorTest, OpenIn) { ...@@ -397,6 +400,110 @@ TEST_F(DownloadManagerCoordinatorTest, OpenIn) {
CGRectZero, document_interaction_controller.presentedOpenInMenu.rect)); CGRectZero, document_interaction_controller.presentedOpenInMenu.rect));
ASSERT_EQ(view, document_interaction_controller.presentedOpenInMenu.view); ASSERT_EQ(view, document_interaction_controller.presentedOpenInMenu.view);
ASSERT_TRUE(document_interaction_controller.presentedOpenInMenu.animated); ASSERT_TRUE(document_interaction_controller.presentedOpenInMenu.animated);
// Download task is destroyed without opening the file.
task = nullptr;
histogram_tester_.ExpectUniqueSample(
"Download.IOSDownloadedFileAction",
static_cast<base::HistogramBase::Sample>(DownloadedFileAction::NoAction),
1);
}
// Tests opening the download in Google Drive app.
TEST_F(DownloadManagerCoordinatorTest, OpenInDrive) {
web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
coordinator_.downloadTask = &task;
[coordinator_ start];
EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
DownloadManagerViewController* viewController =
base_view_controller_.childViewControllers.firstObject;
ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
// Start and complete the download.
base::FilePath path;
ASSERT_TRUE(base::GetTempDir(&path));
task.Start(std::make_unique<net::URLFetcherFileWriter>(
base::ThreadTaskRunnerHandle::Get(), path));
// Stub UIDocumentInteractionController.
id document_interaction_controller =
[[FakeDocumentInteractionController alloc] init];
OCMStub([document_interaction_controller_class_
interactionControllerWithURL:[OCMArg any]])
.andReturn(document_interaction_controller);
// Present Open In... menu.
ASSERT_FALSE([document_interaction_controller presentedOpenInMenu]);
@autoreleasepool {
// This call will retain coordinator, which should outlive thread bundle.
[viewController.delegate downloadManagerViewController:viewController
presentOpenInMenuWithLayoutGuide:nil];
}
ASSERT_TRUE([document_interaction_controller presentedOpenInMenu]);
// Open the file in Google Drive app.
@autoreleasepool {
// This call will retain coordinator, which should outlive thread bundle.
[[document_interaction_controller delegate]
documentInteractionController:document_interaction_controller
willBeginSendingToApplication:kGoogleDriveAppBundleID];
}
histogram_tester_.ExpectUniqueSample("Download.IOSDownloadedFileAction",
static_cast<base::HistogramBase::Sample>(
DownloadedFileAction::OpenedInDrive),
1);
}
// Tests opening the download in app other than Google Drive app.
TEST_F(DownloadManagerCoordinatorTest, OpenInOtherApp) {
web::FakeDownloadTask task(GURL(kTestUrl), kTestMimeType);
task.SetSuggestedFilename(base::SysNSStringToUTF16(kTestSuggestedFileName));
coordinator_.downloadTask = &task;
[coordinator_ start];
EXPECT_EQ(1U, base_view_controller_.childViewControllers.count);
DownloadManagerViewController* viewController =
base_view_controller_.childViewControllers.firstObject;
ASSERT_EQ([DownloadManagerViewController class], [viewController class]);
// Start and complete the download.
base::FilePath path;
ASSERT_TRUE(base::GetTempDir(&path));
task.Start(std::make_unique<net::URLFetcherFileWriter>(
base::ThreadTaskRunnerHandle::Get(), path));
// Stub UIDocumentInteractionController.
id document_interaction_controller =
[[FakeDocumentInteractionController alloc] init];
OCMStub([document_interaction_controller_class_
interactionControllerWithURL:[OCMArg any]])
.andReturn(document_interaction_controller);
// Present Open In... menu.
ASSERT_FALSE([document_interaction_controller presentedOpenInMenu]);
@autoreleasepool {
// This call will retain coordinator, which should outlive thread bundle.
[viewController.delegate downloadManagerViewController:viewController
presentOpenInMenuWithLayoutGuide:nil];
}
ASSERT_TRUE([document_interaction_controller presentedOpenInMenu]);
// Open the file in Google Drive app.
@autoreleasepool {
// This call will retain coordinator, which should outlive thread bundle.
[[document_interaction_controller delegate]
documentInteractionController:document_interaction_controller
willBeginSendingToApplication:@"foo-app-id"];
}
histogram_tester_.ExpectUniqueSample(
"Download.IOSDownloadedFileAction",
static_cast<base::HistogramBase::Sample>(
DownloadedFileAction::OpenedInOtherApp),
1);
} }
// Tests closing view controller while the download is in progress. Coordinator // Tests closing view controller while the download is in progress. Coordinator
......
...@@ -19,13 +19,16 @@ ...@@ -19,13 +19,16 @@
// present any UI, but simply captures the presentation requests. // present any UI, but simply captures the presentation requests.
@interface FakeDocumentInteractionController : NSObject @interface FakeDocumentInteractionController : NSObject
@property(nonatomic, weak) id<UIDocumentInteractionControllerDelegate> delegate;
// Menu that is currently being presented.
@property(nonatomic, readonly) OpenInMenu* presentedOpenInMenu;
// Fake implementations of UIDocumentInteractionController methods: // Fake implementations of UIDocumentInteractionController methods:
- (BOOL)presentOpenInMenuFromRect:(CGRect)rect - (BOOL)presentOpenInMenuFromRect:(CGRect)rect
inView:(UIView*)view inView:(UIView*)view
animated:(BOOL)animated; animated:(BOOL)animated;
// Menu that is currently being presented.
@property(nonatomic, readonly) OpenInMenu* presentedOpenInMenu;
@end @end
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
@end @end
@implementation FakeDocumentInteractionController @implementation FakeDocumentInteractionController
@synthesize delegate = _delegate;
@synthesize presentedOpenInMenu = _presentedOpenInMenu; @synthesize presentedOpenInMenu = _presentedOpenInMenu;
- (BOOL)presentOpenInMenuFromRect:(CGRect)rect - (BOOL)presentOpenInMenuFromRect:(CGRect)rect
inView:(UIView*)view inView:(UIView*)view
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment