Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(344)

Unified Diff: ios/chrome/browser/ui/omnibox_perftest.mm

Issue 2589803002: Upstream Chrome on iOS source code [6/11]. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ios/chrome/browser/ui/omnibox_perftest.mm
diff --git a/ios/chrome/browser/ui/omnibox_perftest.mm b/ios/chrome/browser/ui/omnibox_perftest.mm
new file mode 100644
index 0000000000000000000000000000000000000000..e4e24f8ca034b8e8f31214a7f94d7072ecca5165
--- /dev/null
+++ b/ios/chrome/browser/ui/omnibox_perftest.mm
@@ -0,0 +1,275 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <UIKit/UIKit.h>
+
+#include <memory>
+
+#include "base/mac/scoped_nsobject.h"
+#import "base/test/ios/wait_util.h"
+#include "base/time/time.h"
+#include "components/toolbar/test_toolbar_model.h"
+#include "ios/chrome/browser/autocomplete/autocomplete_classifier_factory.h"
+#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
+#include "ios/chrome/browser/search_engines/template_url_service_factory.h"
+#import "ios/chrome/browser/tabs/tab.h"
+#import "ios/chrome/browser/tabs/tab_model.h"
+#include "ios/chrome/browser/ui/omnibox/location_bar_view_ios.h"
+#import "ios/chrome/browser/ui/omnibox/omnibox_text_field_ios.h"
+#include "ios/chrome/browser/ui/toolbar/toolbar_model_delegate_ios.h"
+#include "ios/chrome/browser/ui/toolbar/toolbar_model_impl_ios.h"
+#import "ios/chrome/browser/ui/toolbar/web_toolbar_controller.h"
+#include "ios/chrome/test/base/perf_test_ios.h"
+#include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "ui/base/test/ios/keyboard_appearance_listener.h"
+
+namespace {
+
+// Descends down a view hierarchy until the first view of |specificClass|
+// is found. Returns nil if a view of |specificClass| cannot be found.
+UIView* FindViewByClass(UIView* topView, Class specificClass) {
+ if ([topView isKindOfClass:specificClass])
+ return [topView window] ? topView : nil;
+ for (UIView* subview in [topView subviews]) {
+ UIView* foundView = FindViewByClass(subview, specificClass);
+ if (foundView)
+ return foundView;
+ }
+ return nil;
+}
+
+// Constant for UI wait loop.
+const NSTimeInterval kSpinDelaySeconds = 0.01;
+
+class OmniboxPerfTest : public PerfTest {
+ public:
+ OmniboxPerfTest() : PerfTest("Omnibox") {}
+
+ protected:
+ void SetUp() override {
+ PerfTest::SetUp();
+ TestChromeBrowserState::Builder test_cbs_builder;
+ test_cbs_builder.AddTestingFactory(
+ ios::TemplateURLServiceFactory::GetInstance(),
+ ios::TemplateURLServiceFactory::GetDefaultFactory());
+ test_cbs_builder.AddTestingFactory(
+ ios::AutocompleteClassifierFactory::GetInstance(),
+ ios::AutocompleteClassifierFactory::GetDefaultFactory());
+ chrome_browser_state_ = test_cbs_builder.Build();
+
+ // Prepares testing profile for autocompletion.
+ ios::AutocompleteClassifierFactory::GetForBrowserState(
+ chrome_browser_state_.get());
+
+ // Sets up the listener for keyboard activation/deactivation notifications.
+ keyboard_listener_.reset([[KeyboardAppearanceListener alloc] init]);
+
+ // Create a real window to host the Toolbar.
+ CGRect screenBounds = [[UIScreen mainScreen] bounds];
+ window_.reset([[UIWindow alloc] initWithFrame:screenBounds]);
+ [window_ makeKeyAndVisible];
+
+ // Create a mock Tab and a TabModel that will always return the mock Tab as
+ // the current tab.
+ current_tab_.reset(
+ [(Tab*)[OCMockObject niceMockForClass:[Tab class]] retain]);
+ id tab_model = [OCMockObject mockForClass:[TabModel class]];
+ [[[tab_model stub] andReturn:current_tab_] currentTab];
+ tab_model_.reset([tab_model retain]);
+
+ // Creates the Toolbar for testing and sizes it to the width of the screen.
+ toolbar_model_delegate_.reset(
+ new ToolbarModelDelegateIOS(tab_model_.get()));
+ toolbar_model_ios_.reset(
+ new ToolbarModelImplIOS(toolbar_model_delegate_.get()));
+
+ // The OCMOCK_VALUE macro doesn't like std::unique_ptr, but it works just
+ // fine if a temporary variable is used.
+ ToolbarModelIOS* model_for_mock = toolbar_model_ios_.get();
+ id webToolbarDelegate =
+ [OCMockObject niceMockForProtocol:@protocol(WebToolbarDelegate)];
+ [[[webToolbarDelegate stub] andReturnValue:OCMOCK_VALUE(model_for_mock)]
+ toolbarModelIOS];
+ id urlLoader = [OCMockObject niceMockForProtocol:@protocol(UrlLoader)];
+ toolbar_.reset([[WebToolbarController alloc]
+ initWithDelegate:webToolbarDelegate
+ urlLoader:urlLoader
+ browserState:chrome_browser_state_.get()
+ preloadProvider:nil]);
+ UIView* toolbarView = [toolbar_ view];
+ CGRect toolbarFrame = toolbarView.frame;
+ toolbarFrame.origin = CGPointZero;
+ toolbarFrame.size.width = screenBounds.size.width;
+ toolbarView.frame = toolbarFrame;
+ // Add toolbar to window.
+ [window_ addSubview:toolbarView];
+ base::test::ios::WaitUntilCondition(^bool() {
+ return IsToolbarLoaded(window_.get());
+ });
+ }
+
+ void TearDown() override {
+ // Remove toolbar from window.
+ [[toolbar_ view] removeFromSuperview];
+ base::test::ios::WaitUntilCondition(^bool() {
+ return !IsToolbarLoaded(window_.get());
+ });
+ [toolbar_ browserStateDestroyed];
+ PerfTest::TearDown();
+ }
+
+ // Returns whether Omnibox has been loaded.
+ bool IsToolbarLoaded(UIView* topView) {
+ return FindViewByClass(topView, [OmniboxTextFieldIOS class]) != nil;
+ }
+
+ // Inserts the |text| string into the |textField| and return the amount
+ // of time it took to complete the insertion. This does not time
+ // any activities that may be triggered on other threads.
+ base::TimeDelta TimeInsertText(OmniboxTextFieldIOS* textField,
+ NSString* text) {
+ base::Time startTime = base::Time::NowFromSystemTime();
+ [textField insertTextWhileEditing:text];
+ base::TimeDelta elapsed = base::Time::NowFromSystemTime() - startTime;
+ // Adds a small delay so the run loop can update the screen.
+ // The user experience measurement should include this visual
+ // feedback to the user, but there is no way of catching when
+ // the typed character showed up in the omnibox on screen.
+ base::test::ios::SpinRunLoopWithMaxDelay(
+ base::TimeDelta::FromSecondsD(kSpinDelaySeconds));
+ return elapsed;
+ }
+
+ // Creates a dummy text field and make it be a first responder so keyboard
+ // comes up. In general, there's a lot of time spent in loading up various
+ // graphics assets on a keyboard which may distort the measurement of Chrome
+ // Omnibox focus timings. Call this function to preload keyboard before
+ // doing the real test.
+ base::TimeDelta PreLoadKeyboard() {
+ base::scoped_nsobject<UITextField> textField(
+ [[UITextField alloc] initWithFrame:CGRectMake(20, 100, 280, 29)]);
+ [textField setBorderStyle:UITextBorderStyleRoundedRect];
+ [window_ addSubview:textField];
+ base::TimeDelta elapsed = base::test::ios::TimeUntilCondition(
+ ^{
+ [textField becomeFirstResponder];
+ },
+ ^bool() {
+ return [keyboard_listener_ isKeyboardVisible];
+ },
+ nullptr, base::TimeDelta());
+ base::test::ios::TimeUntilCondition(
+ ^{
+ [textField resignFirstResponder];
+ },
+ ^bool() {
+ return ![keyboard_listener_ isKeyboardVisible];
+ },
+ nullptr, base::TimeDelta());
+ [textField removeFromSuperview];
+ return elapsed;
+ }
+
+ // Enables the on-screen keyboard as if user has tapped on |textField|.
+ // Returns the amount of time it took for the keyboard to appear.
+ base::TimeDelta EnableKeyboard(OmniboxTextFieldIOS* textField) {
+ return base::test::ios::TimeUntilCondition(
+ ^{
+ [textField becomeFirstResponder];
+ },
+ ^bool() {
+ return [keyboard_listener_ isKeyboardVisible];
+ },
+ nullptr, base::TimeDelta());
+ }
+
+ // Performs necessary cleanup (so next pass of unit test can start from
+ // a clean slate) and then exit from |textField| to dismiss keyboard.
+ void DisableKeyboard(OmniboxTextFieldIOS* textField) {
+ // Busy wait until keyboard is hidden.
+ base::test::ios::TimeUntilCondition(
+ ^{
+ [textField exitPreEditState];
+ [textField resignFirstResponder];
+ },
+ ^bool() {
+ return ![keyboard_listener_ isKeyboardVisible];
+ },
+ nullptr, base::TimeDelta());
+ }
+
+ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
+ base::scoped_nsobject<Tab> current_tab_;
+ base::scoped_nsobject<TabModel> tab_model_;
+ std::unique_ptr<ToolbarModelDelegateIOS> toolbar_model_delegate_;
+ std::unique_ptr<ToolbarModelIOS> toolbar_model_ios_;
+ base::scoped_nsobject<WebToolbarController> toolbar_;
+ base::scoped_nsobject<UIWindow> window_;
+ base::scoped_nsobject<KeyboardAppearanceListener> keyboard_listener_;
+};
+
+// Measures the amount of time it takes the Omnibox text field to activate
+// the on-screen keyboard.
+TEST_F(OmniboxPerfTest, TestTextFieldDidBeginEditing) {
+ LogPerfTiming("Keyboard preload", PreLoadKeyboard());
+ OmniboxTextFieldIOS* textField = (OmniboxTextFieldIOS*)FindViewByClass(
+ [toolbar_ view], [OmniboxTextFieldIOS class]);
+
+ // Time how long it takes to "focus" on omnibox.
+ RepeatTimedRuns("Begin editing",
+ ^base::TimeDelta(int index) {
+ return EnableKeyboard(textField);
+ },
+ ^() {
+ DisableKeyboard(textField);
+ });
+}
+
+// Measures the amount of time it takes to type in the first character
+// into the Omnibox.
+TEST_F(OmniboxPerfTest, TestTypeOneCharInTextField) {
+ OmniboxTextFieldIOS* textField = (OmniboxTextFieldIOS*)FindViewByClass(
+ [toolbar_ view], [OmniboxTextFieldIOS class]);
+ RepeatTimedRuns("Type first character",
+ ^base::TimeDelta(int index) {
+ EnableKeyboard(textField);
+ return TimeInsertText(textField, @"G");
+ },
+ ^() {
+ [textField setText:@""];
+ DisableKeyboard(textField);
+ });
+}
+
+// Measures the amount of time it takes to type in the word "google" one
+// letter at a time.
+TEST_F(OmniboxPerfTest, TestTypingInTextField) {
+ OmniboxTextFieldIOS* textField = (OmniboxTextFieldIOS*)FindViewByClass(
+ [toolbar_ view], [OmniboxTextFieldIOS class]);
+ // The characters to type into the omnibox text field.
+ NSArray* inputCharacters =
+ [NSArray arrayWithObjects:@"g", @"o", @"o", @"g", @"l", @"e", nil];
+ RepeatTimedRuns(
+ "Typing",
+ ^base::TimeDelta(int index) {
+ EnableKeyboard(textField);
+ NSMutableString* logMessage = [NSMutableString string];
+ base::TimeDelta elapsed;
+ for (NSString* input in inputCharacters) {
+ base::TimeDelta inputElapsed = TimeInsertText(textField, input);
+ [logMessage appendFormat:@"%@'%@':%.0f",
+ [logMessage length] ? @" " : @"", input,
+ inputElapsed.InMillisecondsF()];
+ elapsed += inputElapsed;
+ }
+ NSLog(@"%2d: %@", index, logMessage);
+ return elapsed;
+ },
+ ^() {
+ [textField setText:@""];
+ DisableKeyboard(textField);
+ });
+}
+}
« no previous file with comments | « ios/chrome/browser/ui/omnibox/truncating_attributed_label.mm ('k') | ios/chrome/browser/ui/open_in_controller.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698