Index: tools/perf/page_sets/mobile_first_story.py |
diff --git a/tools/perf/page_sets/mobile_first_story.py b/tools/perf/page_sets/mobile_first_story.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..129b9fa321cd29bdf45022647b21f6c032ca9280 |
--- /dev/null |
+++ b/tools/perf/page_sets/mobile_first_story.py |
@@ -0,0 +1,222 @@ |
+# Copyright 2015 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 logging |
+ |
+from telemetry.core import android_platform |
+from telemetry.core import platform as platform_module |
+from telemetry.internal.browser import browser_finder |
+from telemetry.internal.platform import android_device |
+from telemetry.page import action_runner |
+from telemetry import story as story_module |
+from telemetry.web_perf import timeline_based_measurement |
+ |
+# pylint: disable=import-error |
nednguyen
2015/12/08 19:08:42
Can you update PRESUBMIT of tools/perf to include
perezju
2015/12/09 12:30:18
Done.
|
+from devil.android.sdk import intent as intent_module |
+from devil.android.sdk import keyevent |
+from devil.utils import geometry |
+from devil.utils import timeout_retry |
+ |
+ |
+class SharedMobileFirstState(story_module.SharedState): |
+ def __init__(self, test, finder_options, story_set): |
+ super(SharedMobileFirstState, self).__init__( |
+ test, finder_options, story_set) |
+ self._test = test |
+ self._story_set = story_set |
+ self._android_platform = self._GetAndroidPlatform(finder_options) |
+ self._gmail_app = self._CreateGmailApp() |
+ self._browser = self._CreateBrowser(finder_options) |
+ self._current_story = None |
+ self._current_results = None |
+ self._new_tab_ids = set() |
+ |
+ def _GetAndroidPlatform(self, finder_options): |
+ device = android_device.GetDevice(finder_options) |
+ assert device, 'Benchmark requires an android device.' |
+ platform = platform_module.GetPlatformForDevice(device, finder_options) |
+ assert isinstance(platform, android_platform.AndroidPlatform) |
+ return platform |
+ |
+ def _CreateGmailApp(self): |
+ return self.platform.LaunchAndroidApplication( |
+ intent_module.Intent( |
+ package='com.google.android.gm', |
+ activity='com.google.android.gm.ui.MailActivityGmail')) |
+ |
+ def _CreateBrowser(self, finder_options): |
+ return browser_finder.FindBrowser(finder_options).Create(finder_options) |
+ |
+ @property |
+ def is_timeline_based(self): |
+ return isinstance( |
+ self._test, timeline_based_measurement.TimelineBasedMeasurement) |
+ |
+ @property |
+ def platform(self): |
+ return self._android_platform |
+ |
+ @property |
+ def gmail_app(self): |
+ return self._gmail_app |
+ |
+ @property |
+ def browser(self): |
+ return self._browser |
+ |
+ @property |
+ def results(self): |
+ return self._current_results |
+ |
+ def WillRunStory(self, story): |
+ self._current_story = story |
+ if self.is_timeline_based: |
+ self._test.WillRunStory(self.platform) |
+ |
+ def CanRunStory(self, story): |
+ return True # All stories must be run. |
+ |
+ def RunStory(self, results): |
+ self._current_results = results |
+ self._current_story.Run(self) |
+ |
+ def GetBrowserTab(self, new_tab=False): |
+ if new_tab: |
+ tab = self.browser.tabs.New() |
+ else: |
+ tab = self.browser.foreground_tab |
+ self._new_tab_ids.add(tab.id) |
+ return tab |
+ |
+ def CloseOldTabs(self): |
+ logging.info('Closing old tabs:') |
+ for tab in self.browser.tabs: |
+ if tab.id in self._new_tab_ids: |
+ logging.info('- keeping [%s] %s', tab.id, tab.url) |
+ else: |
+ logging.info('- closing [%s] %s', tab.id, tab.url) |
+ tab.Close() |
+ self._new_tab_ids = set() |
+ |
+ def DidRunStory(self, results): |
+ if self.is_timeline_based: |
+ self._test.DidRunStory(self.platform) |
+ self._current_story = None |
+ self._current_results = None |
+ |
+ def TearDownState(self): |
+ self._browser.Close() |
+ self._gmail_app.Close() |
+ |
+ |
+class _MobileFirstStory(story_module.Story): # pylint: disable=abstract-method |
+ DUMP_WAIT_TIME = 3 |
+ INTERACTION_LABEL = 'foreground' |
+ |
+ def __init__(self, name, memory_infra=False): |
+ super(_MobileFirstStory, self).__init__(SharedMobileFirstState, name=name) |
+ self._memory_infra = memory_infra |
+ |
+ def _TakeMemoryMeasurement(self, shared_state, tab): |
+ runner = action_runner.ActionRunner(tab) |
+ runner.tab.WaitForDocumentReadyStateToBeComplete() |
+ runner.Wait(1) # See crbug.com/540022#c17. |
+ with runner.CreateInteraction(self.INTERACTION_LABEL): |
+ runner.Wait(self.DUMP_WAIT_TIME) |
+ if shared_state.is_timeline_based and self._memory_infra: |
+ runner.ForceGarbageCollection() |
+ runner.tab.browser.platform.FlushEntireSystemCache() |
+ runner.Wait(self.DUMP_WAIT_TIME) |
+ if not runner.tab.browser.DumpMemory(): |
+ logging.error('Unable to get a memory dump for %s.', self.name) |
+ # TODO(perezju): Use platform to also measure memory for Android apps |
+ # with no access to memory-infra. |
+ |
+class ChromeAppStory(_MobileFirstStory): |
+ def __init__(self, name, url, last_page=False): |
+ super(ChromeAppStory, self).__init__(name=name, memory_infra=True) |
+ self._url = url |
+ self._last_page = last_page |
+ |
+ def Run(self, shared_state): |
+ navigate_on_new_tab = self._url is not None |
+ tab = shared_state.GetBrowserTab(new_tab=navigate_on_new_tab) |
+ if navigate_on_new_tab: |
+ tab.Navigate(self._url) |
+ self._TakeMemoryMeasurement(shared_state, tab) |
+ if self._last_page: |
+ shared_state.CloseOldTabs() |
+ |
+ |
+class GmailAppStory(_MobileFirstStory): |
+ def __init__(self, name): |
+ super(GmailAppStory, self).__init__(name=name) |
+ |
+ def Run(self, shared_state): |
+ # Go to the app switcher and tap on Gmail. |
+ shared_state.platform.android_action_runner.InputKeyEvent( |
+ keyevent.KEYCODE_APP_SWITCH) |
+ shared_state.platform.system_ui.WaitForUiNode( |
+ resource_id='activity_description', text='Gmail').Tap() |
+ |
+ # If there is a "Back" button, tap on it to go to converation list view. |
+ navigate_up = shared_state.gmail_app.ui.GetUiNode( |
+ content_desc='Navigate up') |
+ if navigate_up: |
+ logging.info('Tapping on "Navigate up" button.') |
+ navigate_up.Tap() |
+ |
+ # Tap on the last email on the conversation list view. |
+ logging.info('Tapping on last email in list view.') |
+ shared_state.gmail_app.ui.WaitForUiNode( |
+ resource_id='conversation_list_view')[-1].Tap() |
+ |
+ # Wait for the email body to show, and take a memory measurement. |
+ logging.info('Waiting for conversation_webview') |
+ webview_view = shared_state.gmail_app.ui.WaitForUiNode( |
+ resource_id='conversation_webview') |
+ webview_content = self._GetSingleWebview(shared_state.gmail_app) |
+ self._TakeMemoryMeasurement(shared_state, webview_content) |
+ |
+ # Tap on the first link found on the email body, causes Chrome to launch. |
+ link_bounds = geometry.Rectangle.FromDict( |
+ webview_content.EvaluateJavaScript( |
+ 'document.links[0].getBoundingClientRect()')) |
+ webview_view.Tap(link_bounds.center, dp_units=True) |
+ |
+ def _GetSingleWebview(self, app): |
+ def get_webviews(): |
+ return app.GetWebViews() |
+ |
+ webviews = timeout_retry.WaitFor(get_webviews, wait_period=1, max_tries=5) |
+ assert webviews, 'No webviews found.' |
+ |
+ webview_content = webviews.pop() |
+ logging.info('Will work with webview: %s', webview_content.id) |
+ if len(webviews): |
+ logging.warning('Ignoring (%d) other webviews found: %s.', |
+ len(webviews), ', '.join(w.id for w in webviews)) |
+ |
+ return webview_content |
+ |
+ |
+class GooglerMobileFirstStorySet(story_module.StorySet): |
+ """Mobile First Googler story set.""" |
+ |
+ def __init__(self): |
+ super(GooglerMobileFirstStorySet, self).__init__( |
+ archive_data_file='data/googler_mobile_first.json', |
+ cloud_storage_bucket=story_module.PARTNER_BUCKET) |
+ self.AddStory(GmailAppStory('gmail_read_email')) |
+ self.AddStory(ChromeAppStory( |
+ name='chromium_code_review', |
+ url=None)) # Grabs url from email body. |
+ self.AddStory(ChromeAppStory( |
+ name='chromium_issue', |
+ url='http://crbug.com/567696')) |
+ self.AddStory(ChromeAppStory( |
+ name='chromium_code_search', |
+ url='https://code.google.com/p/chromium/codesearch' |
+ '#chromium/src/tools/perf/benchmarks/memory_infra.py', |
+ last_page=True)) |