1from autotest_lib.client.common_lib import error
2from autotest_lib.client.common_lib import ui_utils
3from autotest_lib.client.cros.input_playback import keyboard
4import logging
5import time
6
7
8class UIPrinterHelper(object):
9    """Helper lib for ChromeOS UI automation."""
10
11    def __init__(self, ui_handler=None, chrome=None):
12        """ui_handler or chrome must be provided. ui_handler is an already
13        existing ui object."""
14        if not ui_handler and chrome:
15            self.ui = ui_utils.UI_Handler()
16            self.ui.start_ui_root(chrome)
17        elif not chrome and ui_handler:
18            self.ui = ui_handler
19        else:
20            raise error.TestError(
21                "Either the chrome object or ui_handler must be provided.")
22        self._keyboard = None
23
24    def print_to_custom_printer(self, printer_name, isPDF=False):
25        """Open the printer menu, select the printer given and click print."""
26        self.open_printer_menu()
27        self.open_see_more_print_sub_menu()
28        self.select_printer_from_see_more_menu(printer_name)
29        if not self.check_print_window_open():
30            raise error.TestError("Print not open after setting printer.")
31        self.click_print(isPDF)
32        if self._keyboard:
33            self._keyboard.close()
34
35    def check_print_window_open(self):
36        """Check if the print window is still open."""
37        start_time = time.time()
38
39        # Giving up to 5 seconds for the window to load.
40        while time.time() - start_time < 5:
41            if (self.ui.item_present('Destination', role='inlineTextBox') and
42                    self.ui.item_present('Cancel', role='button')) and not (
43                    self.ui.item_present('Loading preview')):
44                return True
45
46        logging.info("Print Window was not open {}"
47                     .format(self.ui.get_name_role_list()))
48        self.ui.screenshoter.take_ss()
49        return False
50
51    def open_printer_menu(self, retry=0):
52        """Open the printer menu via the Chrome Dropdown."""
53        if not self._is_chrome_menu_open():
54            self.ui.doDefault_on_obj('Chrome')
55        self.ui.wait_for_ui_obj('/Print/', role='menuItem', isRegex=True)
56        self.ui.doDefault_on_obj('/Print/', isRegex=True)
57        if retry == 0:
58            try:
59                self.wait_for_print_ready()
60            except error.TestError:
61                self.open_printer_menu(retry=1)
62        else:
63            self.wait_for_print_ready()
64
65    def wait_for_print_ready(self):
66        """Wait for the print page to fully load."""
67        try:
68            self.ui.wait_for_ui_obj('Fit to width', role='button', timeout=30)
69        except:
70            logging.info("Missing {} in {}".format("Fit to width",
71                         self.ui.get_name_role_list()))
72            raise error.TestError("Fit to width no load")
73        self.ui.wait_for_ui_obj('Loading preview', remove=True)
74
75    def open_see_more_print_sub_menu(self):
76        """Open see more sub menu via the clicking it in the dropdown."""
77        if not self._keyboard:
78            self._keyboard = keyboard.Keyboard()
79
80        # Some tests have a notification which causes the chrome menu
81        # to remain open, and loose focus on the print page.
82        if self._is_chrome_menu_open():
83            self._keyboard.press_key("escape")
84            self.verify_print_menu_open()
85
86        self.ui.wait_for_ui_obj('Destination Save as PDF')
87        self.ui.doDefault_on_obj("Destination Save as PDF", role='popUpButton')
88
89        self.ui.wait_for_ui_obj("See more destinations", role='menuItem')
90        self.ui.doDefault_on_obj("See more destinations", role='menuItem')
91        self.is_see_more_menu_open()
92
93    def _is_chrome_menu_open(self):
94        """Return True if the chrome dropdown menu is still open."""
95        return self.ui.item_present("/Print/", role="menuItem", isRegex=True)
96
97    def select_printer_from_see_more_menu(self, printer_name):
98        """Click a printer from the "see more" sub menu within print page."""
99        if not self.is_see_more_menu_open():
100            raise error.TestError(
101                "Cannot select printer from sub menu as its not open.")
102        # Easier to find via regex since the actual cell has the name twice.
103        if not self.is_str_regex(printer_name):
104            printer_name = self.make_str_regex(printer_name)
105        self.ui.wait_for_ui_obj(printer_name, isRegex=True, role='cell')
106        self.ui.doDefault_on_obj(printer_name, isRegex=True, role='cell')
107        self.ui.wait_for_ui_obj(printer_name, role='cell', remove=True, isRegex=True)
108        # Wait for the "Setting up " loading icon to finish
109        self.ui.wait_for_ui_obj('Setting up ', remove=True)
110
111    def click_print(self, isPDF=False):
112        """Click the print button. Click save if PDF."""
113        self.verify_print_menu_open()
114        self.ui.doDefault_on_obj('Save' if isPDF else 'Print', role='button')
115        if isPDF:
116            pass  # TODO implement the save menu
117
118    def is_see_more_menu_open(self):
119        """Return True if the print menu is open."""
120        try:
121            self.ui.wait_for_ui_obj("Select a destination")
122        except error.TestError:
123            return False
124        return True
125
126    def is_print_menu_open(self):
127        """Return True if the print menu is open."""
128        return self.ui.item_present("Print", role="window")
129
130    def verify_print_menu_open(self):
131        """Verify print menu is open. If not raise TestError."""
132        if not self.is_print_menu_open():
133            raise error.TestError(
134                "Cannot open See more print menu when print screen not open")
135
136    def is_str_regex(self, var):
137        """Return True if the given var starts and ends with "/"."""
138        if len(var) < 1:
139            return False
140        if var[0] == "/" and var[-1] == "/":
141            return True
142        return False
143
144    def make_str_regex(self, var):
145        """Return the provided var with a leading and ending "/"."""
146        return ("/" + var + "/")
147