1# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import logging
6import pprint
7import sys
8import time
9from autotest_lib.client.bin import test, utils
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.common_lib.cros import chrome
12from autotest_lib.client.cros import constants, cros_logging
13from autotest_lib.client.cros import httpd
14
15
16class desktopui_FlashSanityCheck(test.test):
17    """
18    Sanity test that ensures flash instance is launched when a swf is played.
19    """
20    version = 4
21
22    _messages_log_reader = None
23    _ui_log_reader = None
24    _test_url = None
25    _testServer = None
26
27    def initialize(self):
28        logging.info('initialize() - Run html server.')
29        self._test_url = 'http://localhost:8000/index.html'
30        self._testServer = httpd.HTTPListener(8000, docroot=self.bindir)
31        self._testServer.run()
32        logging.info('initialize() - Wait 5 seconds for server to run.')
33        time.sleep(5)
34
35    def cleanup(self):
36        if self._testServer is not None:
37            self._testServer.stop()
38
39    def run_flash_sanity_test(self, browser, time_to_wait_secs):
40        """Run the Flash sanity test.
41
42        @param browser: The Browser object to run the test with.
43        @param time_to_wait_secs: wait time for swf file to load.
44
45        """
46        tab = None
47        # BUG(485108): Work around a telemetry timing out after login.
48        try:
49            logging.info('Getting tab from telemetry...')
50            tab = browser.tabs[0]
51        except:
52            logging.warning('Unexpected exception getting tab: %s',
53                            pprint.pformat(sys.exc_info()[0]))
54        if tab is None:
55            return False
56
57        logging.info('Initialize reading system logs.')
58        self._messages_log_reader = cros_logging.LogReader()
59        self._messages_log_reader.set_start_by_current()
60        self._ui_log_reader = cros_logging.LogReader('/var/log/ui/ui.LATEST')
61        self._ui_log_reader.set_start_by_current()
62        logging.info('Done initializing system logs.')
63
64        # Ensure that the swf got pulled.
65        pulled = False
66        try:
67            latch = self._testServer.add_wait_url('/Trivial.swf')
68            tab.Navigate(self._test_url)
69            tab.WaitForDocumentReadyStateToBeComplete()
70            logging.info('Waiting up to %ds for document.', time_to_wait_secs)
71            latch.wait(time_to_wait_secs)
72            pulled = True
73        except:
74            logging.warning('Unexpected exception wating for document: %s',
75                            pprint.pformat(sys.exc_info()[0]))
76        if not pulled:
77            return False
78
79        logging.info('Waiting for Pepper process.')
80        # Verify that we see a ppapi process and assume it is Flash.
81        ppapi = utils.wait_for_value_changed(
82            lambda: (utils.get_process_list('chrome', '--type=ppapi')),
83            old_value=[],
84            timeout_sec=5)
85        logging.info('ppapi process list at start: %s', ', '.join(ppapi))
86        if not ppapi:
87            msg = 'flash/platform/pepper/pep_'
88            if not self._ui_log_reader.can_find(msg):
89                raise error.TestFail(
90                    'Flash did not start (logs) and no ppapi process found.')
91            # There is a chrome bug where the command line of the ppapi and
92            # other processes is shown as "type=zygote". Bail out if we see more
93            # than 2. Notice, we already did the waiting, so there is no need to
94            # do more of it.
95            zygote = utils.get_process_list('chrome', '--type=zygote')
96            if len(zygote) > 2:
97                logging.warning('Flash probably launched by Chrome as zygote: '
98                                '<%s>.', ', '.join(zygote))
99                return False
100
101        # We have a ppapi process. Let it run for a little and see if it is
102        # still alive.
103        logging.info('Running Flash content for a little while.')
104        time.sleep(5)
105        logging.info('Verifying the Pepper process is still around.')
106        ppapi = utils.wait_for_value_changed(
107            lambda: (utils.get_process_list('chrome', '--type=ppapi')),
108            old_value=[],
109            timeout_sec=3)
110        # Notice that we are not checking for equality of ppapi on purpose.
111        logging.info('PPapi process list found: <%s>', ', '.join(ppapi))
112
113        # Any better pattern matching?
114        msg = ' Received crash notification for ' + constants.BROWSER
115        if self._messages_log_reader.can_find(msg):
116            raise error.TestFail('Browser crashed during test.')
117
118        if not ppapi:
119            raise error.TestFail('Pepper process disappeared during test.')
120
121        # At a minimum Flash identifies itself during process start.
122        msg = 'flash/platform/pepper/pep_'
123        if not self._ui_log_reader.can_find(msg):
124            raise error.TestFail('Saw ppapi process but no Flash output.')
125
126        return True
127
128    def run_once(self, time_to_wait_secs=5):
129        utils.verify_flash_installed()
130        retries = 10
131        flash_tested = False
132        while not flash_tested and retries > 0:
133            retries = retries - 1
134            with chrome.Chrome() as cr:
135                flash_tested = self.run_flash_sanity_test(cr.browser,
136                                                          time_to_wait_secs)
137        if not flash_tested:
138            raise error.TestFail('Unable to test Flash due to other problems.')
139