Bug 1313312 - Separate out Puppeteer code into a core and mix-in class. draft
authorHenrik Skupin <mail@hskupin.info>
Mon, 07 Nov 2016 20:41:11 +0100
changeset 434947 a4144888d83c5a0f9f0bf7d83e23771c61c1f542
parent 434821 b693673578be7952596020d0dd4021d0425a038e
child 536168 759fc574cbc5e287a8914bb1b87aa642d26c1031
push id34882
push userbmo:hskupin@gmail.com
push dateMon, 07 Nov 2016 19:41:48 +0000
bugs1313312
milestone52.0a1
Bug 1313312 - Separate out Puppeteer code into a core and mix-in class. MozReview-Commit-ID: IERAJWGQc3e
dom/media/test/external/external_media_harness/testcase.py
dom/media/test/external/requirements.txt
testing/firefox-ui/harness/firefox_ui_harness/testcases.py
testing/firefox-ui/harness/requirements.txt
testing/firefox-ui/tests/functional/keyboard_shortcuts/test_browser_window.py
testing/firefox-ui/tests/functional/locationbar/test_access_locationbar.py
testing/firefox-ui/tests/functional/locationbar/test_escape_autocomplete.py
testing/firefox-ui/tests/functional/locationbar/test_favicon_in_autocomplete.py
testing/firefox-ui/tests/functional/locationbar/test_suggest_bookmarks.py
testing/firefox-ui/tests/functional/private_browsing/test_about_private_browsing.py
testing/firefox-ui/tests/functional/security/test_dv_certificate.py
testing/firefox-ui/tests/functional/security/test_ev_certificate.py
testing/firefox-ui/tests/functional/security/test_no_certificate.py
testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py
testing/firefox-ui/tests/functional/security/test_safe_browsing_warning_pages.py
testing/firefox-ui/tests/functional/security/test_ssl_disabled_error_page.py
testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py
testing/firefox-ui/tests/functional/security/test_submit_unencrypted_info_warning.py
testing/firefox-ui/tests/functional/sessionstore/test_restore_windows_after_restart.py
testing/firefox-ui/tests/puppeteer/test_about_window.py
testing/firefox-ui/tests/puppeteer/test_appinfo.py
testing/firefox-ui/tests/puppeteer/test_l10n.py
testing/firefox-ui/tests/puppeteer/test_notifications.py
testing/firefox-ui/tests/puppeteer/test_page_info_window.py
testing/firefox-ui/tests/puppeteer/test_places.py
testing/firefox-ui/tests/puppeteer/test_prefs.py
testing/firefox-ui/tests/puppeteer/test_security.py
testing/firefox-ui/tests/puppeteer/test_software_update.py
testing/firefox-ui/tests/puppeteer/test_toolbars.py
testing/firefox-ui/tests/puppeteer/test_update_wizard.py
testing/firefox-ui/tests/puppeteer/test_utils.py
testing/firefox-ui/tests/puppeteer/test_windows.py
testing/firefox-ui/tests/update/direct/test_direct_update.py
testing/firefox-ui/tests/update/fallback/test_fallback_update.py
testing/puppeteer/firefox/firefox_puppeteer/__init__.py
testing/puppeteer/firefox/firefox_puppeteer/api/keys.py
testing/puppeteer/firefox/firefox_puppeteer/api/software_update.py
testing/puppeteer/firefox/firefox_puppeteer/api/utils.py
testing/puppeteer/firefox/firefox_puppeteer/base.py
testing/puppeteer/firefox/firefox_puppeteer/decorators.py
testing/puppeteer/firefox/firefox_puppeteer/mixins.py
testing/puppeteer/firefox/firefox_puppeteer/puppeteer.py
testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/deck.py
testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/window.py
testing/puppeteer/firefox/firefox_puppeteer/ui/base.py
testing/puppeteer/firefox/firefox_puppeteer/ui/browser/tabbar.py
testing/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py
testing/puppeteer/firefox/firefox_puppeteer/ui/browser/window.py
testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/deck.py
testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/window.py
testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py
testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py
testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py
--- a/dom/media/test/external/external_media_harness/testcase.py
+++ b/dom/media/test/external/external_media_harness/testcase.py
@@ -6,25 +6,25 @@ import re
 import os
 import time
 
 from marionette import BrowserMobProxyTestCaseMixin, MarionetteTestCase, Marionette
 from marionette_driver import Wait
 from marionette_driver.errors import TimeoutException
 from marionette.marionette_test import SkipTest
 
-from firefox_puppeteer.testcases import BaseFirefoxTestCase
+from firefox_puppeteer import PuppeteerMixin
 from external_media_tests.utils import (timestamp_now, verbose_until)
 from external_media_tests.media_utils.video_puppeteer import (
     VideoException,
     VideoPuppeteer
 )
 
 
-class MediaTestCase(BaseFirefoxTestCase, MarionetteTestCase):
+class MediaTestCase(PuppeteerMixin, MarionetteTestCase):
 
     """
     Necessary methods for MSE playback
 
     :param video_urls: Urls you are going to play as part of the tests.
     """
 
     def __init__(self, *args, **kwargs):
--- a/dom/media/test/external/requirements.txt
+++ b/dom/media/test/external/requirements.txt
@@ -12,9 +12,9 @@ moznetwork==0.27
 mozprocess==0.23
 mozprofile==0.28
 mozrunner==6.12
 moztest==0.7
 mozversion==1.4
 wptserve==1.3.0
 marionette-client==3.1.0
 marionette-driver==2.0.0
-firefox-puppeteer >= 52.0.0, <53.0.0
+firefox-puppeteer >= 52.1.0, <53.0.0
--- a/testing/firefox-ui/harness/firefox_ui_harness/testcases.py
+++ b/testing/firefox-ui/harness/firefox_ui_harness/testcases.py
@@ -7,24 +7,33 @@ import pprint
 from datetime import datetime
 
 import mozfile
 
 from marionette import MarionetteTestCase
 from marionette_driver import Wait
 from marionette_driver.errors import NoSuchWindowException
 
+from firefox_puppeteer import PuppeteerMixin
 from firefox_puppeteer.api.prefs import Preferences
 from firefox_puppeteer.api.software_update import SoftwareUpdate
-from firefox_puppeteer.testcases import BaseFirefoxTestCase
 from firefox_puppeteer.ui.update_wizard import UpdateWizardDialog
 
 
-class FirefoxTestCase(BaseFirefoxTestCase, MarionetteTestCase):
-    """ Integrate MarionetteTestCase with BaseFirefoxTestCase by reordering MRO """
+class FirefoxTestCase(PuppeteerMixin, MarionetteTestCase):
+    """Base TestCase class for Firefox Desktop tests.
+
+    This class enhances the MarionetteTestCase class with PuppeteerMixin on top
+    of MarionetteTestCase by reordering the MRO.
+
+    If you're extending the inheritance tree further to make specialized
+    TestCases, favour the use of super() as opposed to explicit calls to a
+    parent class.
+
+    """
     pass
 
 
 class UpdateTestCase(FirefoxTestCase):
 
     TIMEOUT_UPDATE_APPLY = 300
     TIMEOUT_UPDATE_CHECK = 30
     TIMEOUT_UPDATE_DOWNLOAD = 360
@@ -50,17 +59,17 @@ class UpdateTestCase(FirefoxTestCase):
         self.update_mar_channels = set(kwargs.pop('update_mar_channels'))
         self.default_mar_channels = None
 
         self.updates = []
 
     def setUp(self, is_fallback=False):
         super(UpdateTestCase, self).setUp()
 
-        self.software_update = SoftwareUpdate(lambda: self.marionette)
+        self.software_update = SoftwareUpdate(self.marionette)
         self.download_duration = None
 
         # Bug 604364 - Preparation to test multiple update steps
         self.current_update_index = 0
 
         # Ensure that there exists no already partially downloaded update
         self.remove_downloaded_update()
 
@@ -217,29 +226,30 @@ class UpdateTestCase(FirefoxTestCase):
         :param timeout: How long to wait for the download to finish. Optional, default to 360s.
         """
 
         def download_via_update_wizard(dialog):
             """ Download the update via the old update wizard dialog.
 
             :param dialog: Instance of :class:`UpdateWizardDialog`.
             """
-            prefs = Preferences(lambda: self.marionette)
+            prefs = Preferences(self.marionette)
             prefs.set_pref(self.PREF_APP_UPDATE_ALTWINDOWTYPE, dialog.window_type)
 
             try:
                 # If updates have already been found, proceed to download
                 if dialog.wizard.selected_panel in [dialog.wizard.updates_found_basic,
                                                     dialog.wizard.error_patching,
                                                     ]:
                     dialog.select_next_page()
 
                 # If incompatible add-on are installed, skip over the wizard page
                 # TODO: Remove once we no longer support version Firefox 45.0ESR
-                if self.utils.compare_version(self.appinfo.version, '49.0a1') == -1:
+                if self.puppeteer.utils.compare_version(self.puppeteer.appinfo.version,
+                                                        '49.0a1') == -1:
                     if dialog.wizard.selected_panel == dialog.wizard.incompatible_list:
                         dialog.select_next_page()
 
                 # Updates were stored in the cache, so no download is necessary
                 if dialog.wizard.selected_panel in [dialog.wizard.finished,
                                                     dialog.wizard.finished_background,
                                                     ]:
                     pass
@@ -309,17 +319,17 @@ class UpdateTestCase(FirefoxTestCase):
             self.software_update.force_fallback()
 
         # Restart Firefox to apply the downloaded update
         self.restart(callback=lambda: about_window.deck.apply.button.click())
 
     def download_and_apply_forced_update(self):
         # The update wizard dialog opens automatically after the restart but with a short delay
         dialog = Wait(self.marionette, ignored_exceptions=[NoSuchWindowException]).until(
-            lambda _: self.windows.switch_to(lambda win: type(win) is UpdateWizardDialog)
+            lambda _: self.puppeteer.windows.switch_to(lambda win: type(win) is UpdateWizardDialog)
         )
 
         # In case of a broken complete update the about window has to be used
         if self.updates[self.current_update_index]['patch']['is_complete']:
             about_window = None
             try:
                 self.assertEqual(dialog.wizard.selected_panel,
                                  dialog.wizard.error)
--- a/testing/firefox-ui/harness/requirements.txt
+++ b/testing/firefox-ui/harness/requirements.txt
@@ -1,5 +1,5 @@
-firefox-puppeteer >= 52.0.0, <53.0.0
+firefox-puppeteer >= 52.1.0, <53.0.0
 marionette-client >= 2.3.0
 mozfile >= 1.2
 mozinfo >= 0.8
 mozinstall >= 1.12
--- a/testing/firefox-ui/tests/functional/keyboard_shortcuts/test_browser_window.py
+++ b/testing/firefox-ui/tests/functional/keyboard_shortcuts/test_browser_window.py
@@ -32,17 +32,17 @@ class TestBrowserWindowShortcuts(Firefox
         current_name = self.marionette.execute_script("""
             return window.document.activeElement.localName;
         """)
 
         # This doesn't test anything if we're already at input.
         self.assertNotEqual(current_name, "input")
 
         # TODO: To be moved to the upcoming search library
-        if self.platform == 'linux':
+        if self.puppeteer.platform == 'linux':
             key = 'searchFocusUnix.commandkey'
         else:
             key = 'searchFocus.commandkey'
         self.browser.send_shortcut(self.browser.get_entity(key), accel=True)
 
         # TODO: Check that the right input box is focused
         # Located below searchbar as class="autocomplete-textbox textbox-input"
         # Anon locator has not been released yet (bug 1080764)
--- a/testing/firefox-ui/tests/functional/locationbar/test_access_locationbar.py
+++ b/testing/firefox-ui/tests/functional/locationbar/test_access_locationbar.py
@@ -8,17 +8,17 @@ from firefox_ui_harness.testcases import
 
 
 class TestAccessLocationBar(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         # Clear complete history so there's no interference from previous entries.
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
 
         self.test_urls = [
             'layout/mozilla_projects.html',
             'layout/mozilla.html',
             'layout/mozilla_mission.html'
         ]
         self.test_urls = [self.marionette.absolute_url(t)
                           for t in self.test_urls]
@@ -29,32 +29,32 @@ class TestAccessLocationBar(FirefoxTestC
 
     def test_access_locationbar_history(self):
 
         # Open some local pages, then about:blank
         def load_urls():
             with self.marionette.using_context('content'):
                 for url in self.test_urls:
                     self.marionette.navigate(url)
-        self.places.wait_for_visited(self.test_urls, load_urls)
+        self.puppeteer.places.wait_for_visited(self.test_urls, load_urls)
         with self.marionette.using_context('content'):
             self.marionette.navigate('about:blank')
 
         # Need to blur url bar or autocomplete won't load - bug 1038614
         self.marionette.execute_script("""arguments[0].blur();""", script_args=[self.urlbar])
 
         # Clear contents of url bar to focus, then arrow down for list of visited sites
         # Verify that autocomplete is open and results are displayed
         self.locationbar.clear()
-        self.urlbar.send_keys(self.keys.ARROW_DOWN)
+        self.urlbar.send_keys(self.puppeteer.keys.ARROW_DOWN)
         Wait(self.marionette).until(lambda _: self.autocomplete_results.is_open)
         Wait(self.marionette).until(lambda _: len(self.autocomplete_results.visible_results) > 1)
 
         # Arrow down again to select first item in list, appearing in reversed order, as loaded.
         # Verify first item.
-        self.urlbar.send_keys(self.keys.ARROW_DOWN)
+        self.urlbar.send_keys(self.puppeteer.keys.ARROW_DOWN)
         Wait(self.marionette).until(lambda _: self.autocomplete_results.selected_index == '0')
         self.assertIn('mission', self.locationbar.value)
 
         # Navigate to the currently selected url
         # Verify it loads by comparing the page url to the test url
-        self.urlbar.send_keys(self.keys.ENTER)
+        self.urlbar.send_keys(self.puppeteer.keys.ENTER)
         self.assertEqual(self.locationbar.value, self.test_urls[-1])
--- a/testing/firefox-ui/tests/functional/locationbar/test_escape_autocomplete.py
+++ b/testing/firefox-ui/tests/functional/locationbar/test_escape_autocomplete.py
@@ -8,17 +8,17 @@ from firefox_ui_harness.testcases import
 
 
 class TestEscapeAutocomplete(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         # Clear complete history so there's no interference from previous entries.
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
 
         self.test_urls = [
             'layout/mozilla.html',
             'layout/mozilla_community.html',
         ]
         self.test_urls = [self.marionette.absolute_url(t)
                           for t in self.test_urls]
 
@@ -32,24 +32,24 @@ class TestEscapeAutocomplete(FirefoxTest
         FirefoxTestCase.tearDown(self)
 
     def test_escape_autocomplete(self):
         # Open some local pages
         def load_urls():
             with self.marionette.using_context('content'):
                 for url in self.test_urls:
                     self.marionette.navigate(url)
-        self.places.wait_for_visited(self.test_urls, load_urls)
+        self.puppeteer.places.wait_for_visited(self.test_urls, load_urls)
 
         # Clear the location bar, type the test string, check that autocomplete list opens
         self.locationbar.clear()
         self.locationbar.urlbar.send_keys(self.test_string)
         self.assertEqual(self.locationbar.value, self.test_string)
         Wait(self.marionette).until(lambda _: self.autocomplete_results.is_open)
 
         # Press escape, check location bar value, check autocomplete list closed
-        self.locationbar.urlbar.send_keys(self.keys.ESCAPE)
+        self.locationbar.urlbar.send_keys(self.puppeteer.keys.ESCAPE)
         self.assertEqual(self.locationbar.value, self.test_string)
         Wait(self.marionette).until(lambda _: not self.autocomplete_results.is_open)
 
         # Press escape again and check that locationbar returns to the page url
-        self.locationbar.urlbar.send_keys(self.keys.ESCAPE)
+        self.locationbar.urlbar.send_keys(self.puppeteer.keys.ESCAPE)
         self.assertEqual(self.locationbar.value, self.test_urls[-1])
--- a/testing/firefox-ui/tests/functional/locationbar/test_favicon_in_autocomplete.py
+++ b/testing/firefox-ui/tests/functional/locationbar/test_favicon_in_autocomplete.py
@@ -11,20 +11,20 @@ class TestFaviconInAutocomplete(FirefoxT
 
     PREF_SUGGEST_SEARCHES = 'browser.urlbar.suggest.searches'
     PREF_SUGGEST_BOOKMARK = 'browser.urlbar.suggest.bookmark'
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         # Disable suggestions for searches and bookmarks to get results only for history
-        self.prefs.set_pref(self.PREF_SUGGEST_SEARCHES, False)
-        self.prefs.set_pref(self.PREF_SUGGEST_BOOKMARK, False)
+        self.puppeteer.prefs.set_pref(self.PREF_SUGGEST_SEARCHES, False)
+        self.puppeteer.prefs.set_pref(self.PREF_SUGGEST_BOOKMARK, False)
 
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
 
         self.test_urls = [self.marionette.absolute_url('layout/mozilla.html')]
 
         self.test_string = 'mozilla'
         self.test_favicon = 'mozilla_favicon.ico'
 
         self.autocomplete_results = self.browser.navbar.locationbar.autocomplete_results
 
@@ -36,17 +36,17 @@ class TestFaviconInAutocomplete(FirefoxT
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_favicon_in_autocomplete(self):
         # Open the test page
         def load_urls():
             with self.marionette.using_context('content'):
                 self.marionette.navigate(self.test_urls[0])
-        self.places.wait_for_visited(self.test_urls, load_urls)
+        self.puppeteer.places.wait_for_visited(self.test_urls, load_urls)
 
         locationbar = self.browser.navbar.locationbar
 
         # Clear the location bar, type the test string, check that autocomplete list opens
         locationbar.clear()
         locationbar.urlbar.send_keys(self.test_string)
         self.assertEqual(locationbar.value, self.test_string)
         Wait(self.marionette).until(lambda _: self.autocomplete_results.is_complete)
--- a/testing/firefox-ui/tests/functional/locationbar/test_suggest_bookmarks.py
+++ b/testing/firefox-ui/tests/functional/locationbar/test_suggest_bookmarks.py
@@ -17,48 +17,48 @@ class TestStarInAutocomplete(FirefoxTest
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         self.bookmark_panel = None
         self.test_urls = [self.marionette.absolute_url('layout/mozilla_grants.html')]
 
         # Disable search suggestions to only get results for history and bookmarks
-        self.prefs.set_pref(self.PREF_SUGGEST_SEARCHES, False)
+        self.puppeteer.prefs.set_pref(self.PREF_SUGGEST_SEARCHES, False)
 
         with self.marionette.using_context('content'):
             self.marionette.navigate('about:blank')
 
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
 
     def tearDown(self):
         # Close the autocomplete results
         try:
             if self.bookmark_panel:
                 self.marionette.execute_script("""
                   arguments[0].hidePopup();
                 """, script_args=[self.bookmark_panel])
 
             self.browser.navbar.locationbar.autocomplete_results.close()
-            self.places.restore_default_bookmarks()
+            self.puppeteer.places.restore_default_bookmarks()
             self.marionette.clear_pref(self.PREF_SUGGEST_SEARCHES)
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_star_in_autocomplete(self):
         search_string = 'grants'
 
         def visit_urls():
             with self.marionette.using_context('content'):
                 for url in self.test_urls:
                     self.marionette.navigate(url)
 
         # Navigate to all the urls specified in self.test_urls and wait for them to
         # be registered as visited
-        self.places.wait_for_visited(self.test_urls, visit_urls)
+        self.puppeteer.places.wait_for_visited(self.test_urls, visit_urls)
 
         # Bookmark the current page using the bookmark menu
         self.browser.menubar.select_by_id('bookmarksMenu',
                                           'menu_bookmarkThisPage')
 
         # TODO: Replace hard-coded selector with library method when one is available
         self.bookmark_panel = self.marionette.find_element(By.ID, 'editBookmarkPanel')
         done_button = self.marionette.find_element(By.ID, 'editBookmarkPanelDoneButton')
@@ -66,17 +66,17 @@ class TestStarInAutocomplete(FirefoxTest
         Wait(self.marionette).until(
             lambda mn: self.bookmark_panel.get_attribute('panelopen') == 'true')
         done_button.click()
 
         # We must open the blank page so the autocomplete result isn't "Switch to tab"
         with self.marionette.using_context('content'):
             self.marionette.navigate('about:blank')
 
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
 
         # Focus the locationbar, delete any contents there, and type the search string
         locationbar = self.browser.navbar.locationbar
         locationbar.clear()
         locationbar.urlbar.send_keys(search_string)
         autocomplete_results = locationbar.autocomplete_results
 
         # Wait for the search string to be present, for the autocomplete results to appear
--- a/testing/firefox-ui/tests/functional/private_browsing/test_about_private_browsing.py
+++ b/testing/firefox-ui/tests/functional/private_browsing/test_about_private_browsing.py
@@ -11,17 +11,17 @@ from firefox_puppeteer.ui.browser.window
 
 class TestAboutPrivateBrowsing(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         # Use a fake local support URL
         support_url = 'about:blank?'
-        self.prefs.set_pref('app.support.baseURL', support_url)
+        self.puppeteer.prefs.set_pref('app.support.baseURL', support_url)
 
         self.pb_url = support_url + 'private-browsing'
 
     def tearDown(self):
         try:
             self.marionette.clear_pref('app.support.baseURL')
         finally:
             FirefoxTestCase.tearDown(self)
--- a/testing/firefox-ui/tests/functional/security/test_dv_certificate.py
+++ b/testing/firefox-ui/tests/functional/security/test_dv_certificate.py
@@ -16,17 +16,17 @@ class TestDVCertificate(FirefoxTestCase)
         self.identity_popup = self.browser.navbar.locationbar.identity_popup
 
         self.url = 'https://ssl-dv.mozqa.com'
 
     def tearDown(self):
         try:
             self.browser.switch_to()
             self.identity_popup.close(force=True)
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_dv_cert(self):
         with self.marionette.using_context('content'):
             self.marionette.navigate(self.url)
 
         # The lock icon should be shown
--- a/testing/firefox-ui/tests/functional/security/test_ev_certificate.py
+++ b/testing/firefox-ui/tests/functional/security/test_ev_certificate.py
@@ -16,17 +16,17 @@ class TestEVCertificate(FirefoxTestCase)
         self.identity_popup = self.locationbar.identity_popup
 
         self.url = 'https://ssl-ev.mozqa.com/'
 
     def tearDown(self):
         try:
             self.browser.switch_to()
             self.identity_popup.close(force=True)
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_ev_certificate(self):
         with self.marionette.using_context('content'):
             self.marionette.navigate(self.url)
 
         # The lock icon should be shown
@@ -34,17 +34,17 @@ class TestEVCertificate(FirefoxTestCase)
                       self.locationbar.connection_icon.value_of_css_property('list-style-image'))
 
         # Check the identity box
         self.assertEqual(self.locationbar.identity_box.get_attribute('className'),
                          'verifiedIdentity')
 
         # Get the information from the certificate
         cert = self.browser.tabbar.selected_tab.certificate
-        address = self.security.get_address_from_certificate(cert)
+        address = self.puppeteer.security.get_address_from_certificate(cert)
 
         # Check the identity popup label displays
         self.assertEqual(self.locationbar.identity_organization_label.get_attribute('value'),
                          cert['organization'])
         self.assertEqual(self.locationbar.identity_country_label.get_attribute('value'),
                          '(' + address['country'] + ')')
 
         # Open the identity popup
--- a/testing/firefox-ui/tests/functional/security/test_no_certificate.py
+++ b/testing/firefox-ui/tests/functional/security/test_no_certificate.py
@@ -18,17 +18,17 @@ class TestNoCertificate(FirefoxTestCase)
         self.identity_popup = self.locationbar.identity_popup
 
         self.url = self.marionette.absolute_url('layout/mozilla.html')
 
     def tearDown(self):
         try:
             self.browser.switch_to()
             self.identity_popup.close(force=True)
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_no_certificate(self):
         with self.marionette.using_context('content'):
             self.marionette.navigate(self.url)
 
         # Check the favicon
--- a/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py
+++ b/testing/firefox-ui/tests/functional/security/test_safe_browsing_notification.py
@@ -32,31 +32,31 @@ class TestSafeBrowsingNotificationBar(Fi
             # Malware URL object
             {
                 'button_property': 'safebrowsing.notAnAttackButton.label',
                 'report_page': 'stopbadware.org',
                 'unsafe_page': 'https://www.itisatrap.org/firefox/its-an-attack.html'
             }
         ]
 
-        self.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
-        self.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
+        self.puppeteer.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
+        self.puppeteer.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
 
         # Give the browser a little time, because SafeBrowsing.jsm takes a while
         # between start up and adding the example urls to the db.
         # hg.mozilla.org/mozilla-central/file/46aebcd9481e/browser/base/content/browser.js#l1194
         time.sleep(3)
 
         # TODO: Bug 1139544: While we don't have a reliable way to close the safe browsing
         # notification bar when a test fails, run this test in a new tab.
         self.browser.tabbar.open_tab()
 
     def tearDown(self):
         try:
-            self.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
+            self.puppeteer.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
             self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]])
             self.marionette.clear_pref('browser.safebrowsing.phishing.enabled')
             self.marionette.clear_pref('browser.safebrowsing.malware.enabled')
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_notification_bar(self):
         with self.marionette.using_context('content'):
@@ -96,17 +96,17 @@ class TestSafeBrowsingNotificationBar(Fi
 
         Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
             expected.element_present(By.ID, 'main-feature'),
             message='Expected target element "#main-feature" has not been found',
         )
         self.assertEquals(self.marionette.get_url(), self.browser.get_final_url(unsafe_page))
 
         # Clean up here since the permission gets set in this function
-        self.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
+        self.puppeteer.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
 
     # Check the not a forgery or attack button in the notification bar
     def check_not_badware_button(self, button_property, report_page):
         with self.marionette.using_context('chrome'):
             # TODO: update to use safe browsing notification bar class when bug 1139544 lands
             label = self.browser.get_property(button_property)
             button = (self.marionette.find_element(By.ID, 'content')
                       .find_element('anon attribute', {'label': label}))
--- a/testing/firefox-ui/tests/functional/security/test_safe_browsing_warning_pages.py
+++ b/testing/firefox-ui/tests/functional/security/test_safe_browsing_warning_pages.py
@@ -18,31 +18,31 @@ class TestSafeBrowsingWarningPages(Firef
             # Unwanted software URL
             'https://www.itisatrap.org/firefox/unwanted.html',
             # Phishing URL
             'https://www.itisatrap.org/firefox/its-a-trap.html',
             # Malware URL
             'https://www.itisatrap.org/firefox/its-an-attack.html'
         ]
 
-        self.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
-        self.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
+        self.puppeteer.prefs.set_pref('browser.safebrowsing.phishing.enabled', True)
+        self.puppeteer.prefs.set_pref('browser.safebrowsing.malware.enabled', True)
 
         # Give the browser a little time, because SafeBrowsing.jsm takes a
         # while between start up and adding the example urls to the db.
         # hg.mozilla.org/mozilla-central/file/46aebcd9481e/browser/base/content/browser.js#l1194
         time.sleep(3)
 
         # TODO: Bug 1139544: While we don't have a reliable way to close the safe browsing
         # notification bar when a test fails, run this test in a new tab.
         self.browser.tabbar.open_tab()
 
     def tearDown(self):
         try:
-            self.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
+            self.puppeteer.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
             self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]])
             self.marionette.clear_pref('browser.safebrowsing.malware.enabled')
             self.marionette.clear_pref('browser.safebrowsing.phishing.enabled')
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_warning_pages(self):
         with self.marionette.using_context("content"):
@@ -103,9 +103,9 @@ class TestSafeBrowsingWarningPages(Firef
         button = self.marionette.find_element(By.ID, 'ignoreWarningButton')
         button.click()
 
         Wait(self.marionette, timeout=self.browser.timeout_page_load).until(
             expected.element_present(By.ID, 'main-feature'))
         self.assertEquals(self.marionette.get_url(), self.browser.get_final_url(unsafe_page))
 
         # Clean up by removing safe browsing permission for unsafe page
-        self.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
+        self.puppeteer.utils.permissions.remove('https://www.itisatrap.org', 'safe-browsing')
--- a/testing/firefox-ui/tests/functional/security/test_ssl_disabled_error_page.py
+++ b/testing/firefox-ui/tests/functional/security/test_ssl_disabled_error_page.py
@@ -12,23 +12,23 @@ from firefox_ui_harness.testcases import
 
 class TestSSLDisabledErrorPage(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         self.url = 'https://tlsv1-0.mozqa.com'
 
-        self.utils.sanitize({"sessions": True})
+        self.puppeteer.utils.sanitize({"sessions": True})
 
         # Disable SSL 3.0, TLS 1.0 and TLS 1.1 for secure connections
         # by forcing the use of TLS 1.2
         # see: http://kb.mozillazine.org/Security.tls.version.*#Possible_values_and_their_effects
-        self.prefs.set_pref('security.tls.version.min', 3)
-        self.prefs.set_pref('security.tls.version.max', 3)
+        self.puppeteer.prefs.set_pref('security.tls.version.min', 3)
+        self.puppeteer.prefs.set_pref('security.tls.version.max', 3)
 
     def tearDown(self):
         try:
             self.marionette.clear_pref('security.tls.version.min')
             self.marionette.clear_pref('security.tls.version.max')
         finally:
             FirefoxTestCase.tearDown(self)
 
--- a/testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py
+++ b/testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py
@@ -27,24 +27,24 @@ class TestSSLStatusAfterRestart(FirefoxT
             {
                 'url': 'https://ssl-ov.mozqa.com/',
                 'identity': '',
                 'type': 'secure'
             }
         )
 
         # Set browser to restore previous session
-        self.prefs.set_pref('browser.startup.page', 3)
+        self.puppeteer.prefs.set_pref('browser.startup.page', 3)
 
         self.locationbar = self.browser.navbar.locationbar
         self.identity_popup = self.locationbar.identity_popup
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
             self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]])
             self.browser.switch_to()
             self.identity_popup.close(force=True)
             self.marionette.clear_pref('browser.startup.page')
         finally:
             FirefoxTestCase.tearDown(self)
 
     @skip_if_e10s
@@ -96,17 +96,17 @@ class TestSSLStatusAfterRestart(FirefoxT
             lambda _: self.identity_popup.view.security.more_info_button.click())
 
         # Verify that the current panel is the security panel
         self.assertEqual(page_info.deck.selected_panel, page_info.deck.security)
 
         # Verify the domain listed on the security panel
         # If this is a wildcard cert, check only the domain
         if cert['commonName'].startswith('*'):
-            self.assertIn(self.security.get_domain_from_common_name(cert['commonName']),
+            self.assertIn(self.puppeteer.security.get_domain_from_common_name(cert['commonName']),
                           page_info.deck.security.domain.get_attribute('value'),
                           'Expected domain found in certificate for ' + url)
         else:
             self.assertEqual(page_info.deck.security.domain.get_attribute('value'),
                              cert['commonName'],
                              'Domain value matches certificate common name.')
 
         # Verify the owner listed on the security panel
--- a/testing/firefox-ui/tests/functional/security/test_submit_unencrypted_info_warning.py
+++ b/testing/firefox-ui/tests/functional/security/test_submit_unencrypted_info_warning.py
@@ -13,17 +13,17 @@ from firefox_ui_harness.testcases import
 class TestSubmitUnencryptedInfoWarning(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         self.url = 'https://ssl-dv.mozqa.com/data/firefox/security/unencryptedsearch.html'
         self.test_string = 'mozilla'
 
-        self.prefs.set_pref('security.warn_submit_insecure', True)
+        self.puppeteer.prefs.set_pref('security.warn_submit_insecure', True)
 
     def tearDown(self):
         try:
             self.marionette.clear_pref('security.warn_submit_insecure')
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_submit_unencrypted_info_warning(self):
--- a/testing/firefox-ui/tests/functional/sessionstore/test_restore_windows_after_restart.py
+++ b/testing/firefox-ui/tests/functional/sessionstore/test_restore_windows_after_restart.py
@@ -59,17 +59,17 @@ class TestRestoreWindowsAfterRestart(Fir
         the browser, and then ensures that the standard tabs have been
         restored, and that the private ones have not.
         """
         self.open_windows(self.test_windows)
         self.open_windows(self.private_windows, is_private=True)
 
         self.restart()
 
-        windows = self.windows.all
+        windows = self.puppeteer.windows.all
 
         # There's no guarantee that Marionette will return us an
         # iterator for the opened windows that will match the
         # order within our window list. Instead, we'll convert
         # the list of URLs within each open window to a set of
         # tuples that will allow us to do a direct comparison
         # while allowing the windows to be in any order.
         opened_windows = set()
--- a/testing/firefox-ui/tests/puppeteer/test_about_window.py
+++ b/testing/firefox-ui/tests/puppeteer/test_about_window.py
@@ -10,17 +10,17 @@ class TestAboutWindow(FirefoxTestCase):
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         self.about_window = self.browser.open_about_window()
         self.deck = self.about_window.deck
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_basic(self):
         self.assertEqual(self.about_window.window_type, 'Browser:About')
 
     def test_elements(self):
         """Test correct retrieval of elements."""
@@ -59,10 +59,10 @@ class TestAboutWindow(FirefoxTestCase):
 
         open_strategies = ('menu',
                            opener,
                            )
 
         self.about_window.close()
         for trigger in open_strategies:
             about_window = self.browser.open_about_window(trigger=trigger)
-            self.assertEquals(about_window, self.windows.current)
+            self.assertEquals(about_window, self.puppeteer.windows.current)
             about_window.close()
--- a/testing/firefox-ui/tests/puppeteer/test_appinfo.py
+++ b/testing/firefox-ui/tests/puppeteer/test_appinfo.py
@@ -7,22 +7,23 @@ from firefox_ui_harness.testcases import
 
 
 class TestAppInfo(FirefoxTestCase):
 
     def test_valid_properties(self):
         binary = self.marionette.bin
         version_info = mozversion.get_version(binary=binary)
 
-        self.assertEqual(self.appinfo.ID, version_info['application_id'])
-        self.assertEqual(self.appinfo.name, version_info['application_name'])
-        self.assertEqual(self.appinfo.vendor, version_info['application_vendor'])
-        self.assertEqual(self.appinfo.version, version_info['application_version'])
+        self.assertEqual(self.puppeteer.appinfo.ID, version_info['application_id'])
+        self.assertEqual(self.puppeteer.appinfo.name, version_info['application_name'])
+        self.assertEqual(self.puppeteer.appinfo.vendor, version_info['application_vendor'])
+        self.assertEqual(self.puppeteer.appinfo.version, version_info['application_version'])
         # Bug 1298328 - Platform buildid mismatch due to incremental builds
-        # self.assertEqual(self.appinfo.platformBuildID, version_info['platform_buildid'])
-        self.assertEqual(self.appinfo.platformVersion, version_info['platform_version'])
-        self.assertIsNotNone(self.appinfo.locale)
-        self.assertIsNotNone(self.appinfo.user_agent)
-        self.assertIsNotNone(self.appinfo.XPCOMABI)
+        # self.assertEqual(self.puppeteer.appinfo.platformBuildID,
+        #                  version_info['platform_buildid'])
+        self.assertEqual(self.puppeteer.appinfo.platformVersion, version_info['platform_version'])
+        self.assertIsNotNone(self.puppeteer.appinfo.locale)
+        self.assertIsNotNone(self.puppeteer.appinfo.user_agent)
+        self.assertIsNotNone(self.puppeteer.appinfo.XPCOMABI)
 
     def test_invalid_properties(self):
         with self.assertRaises(AttributeError):
-            self.appinfo.unknown
+            self.puppeteer.appinfo.unknown
--- a/testing/firefox-ui/tests/puppeteer/test_l10n.py
+++ b/testing/firefox-ui/tests/puppeteer/test_l10n.py
@@ -8,17 +8,17 @@ from marionette_driver.errors import Mar
 from firefox_puppeteer.api.l10n import L10n
 from firefox_ui_harness.testcases import FirefoxTestCase
 
 
 class TestL10n(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
-        self.l10n = L10n(lambda: self.marionette)
+        self.l10n = L10n(self.marionette)
 
     def tearDown(self):
         FirefoxTestCase.tearDown(self)
 
     def test_dtd_entity_chrome(self):
         dtds = ['chrome://global/locale/about.dtd',
                 'chrome://browser/locale/baseMenuOverlay.dtd']
 
--- a/testing/firefox-ui/tests/puppeteer/test_notifications.py
+++ b/testing/firefox-ui/tests/puppeteer/test_notifications.py
@@ -12,27 +12,27 @@ from firefox_puppeteer.ui.browser.notifi
 )
 
 
 class TestNotifications(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
-        self.prefs.set_pref('extensions.install.requireSecureOrigin', False)
+        self.puppeteer.prefs.set_pref('extensions.install.requireSecureOrigin', False)
 
         self.addons_url = self.marionette.absolute_url('addons/extensions/')
-        self.utils.permissions.add(self.marionette.baseurl, 'install')
+        self.puppeteer.utils.permissions.add(self.marionette.baseurl, 'install')
 
     def tearDown(self):
         try:
             self.marionette.clear_pref('extensions.install.requireSecureOrigin')
             self.marionette.clear_pref('xpinstall.signatures.required')
 
-            self.utils.permissions.remove(self.addons_url, 'install')
+            self.puppeteer.utils.permissions.remove(self.addons_url, 'install')
 
             if self.browser.notification:
                 self.browser.notification.close(force=True)
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_open_close_notification(self):
         """Trigger and dismiss a notification"""
@@ -64,17 +64,17 @@ class TestNotifications(FirefoxTestCase)
         """Trigger a notification with an origin"""
         self.trigger_addon_notification('restartless_addon_signed.xpi')
         self.assertIn(self.browser.notification.origin, self.marionette.baseurl)
         self.assertIsNotNone(self.browser.notification.label)
 
     def test_addon_install_failed_notification(self):
         """Trigger add-on blocked notification using an unsigned add-on"""
         # Ensure that installing unsigned extensions will fail
-        self.prefs.set_pref('xpinstall.signatures.required', True)
+        self.puppeteer.prefs.set_pref('xpinstall.signatures.required', True)
 
         self.trigger_addon_notification(
             'restartless_addon_unsigned.xpi',
             notification=AddOnInstallFailedNotification)
 
     def trigger_addon_notification(self, addon, notification=AddOnInstallConfirmationNotification):
         with self.marionette.using_context('content'):
             self.marionette.navigate(self.addons_url)
--- a/testing/firefox-ui/tests/puppeteer/test_page_info_window.py
+++ b/testing/firefox-ui/tests/puppeteer/test_page_info_window.py
@@ -4,17 +4,17 @@
 
 from firefox_ui_harness.testcases import FirefoxTestCase
 
 
 class TestPageInfoWindow(FirefoxTestCase):
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_elements(self):
         """Test correct retrieval of elements."""
         page_info = self.browser.open_page_info_window()
 
         self.assertNotEqual(page_info.dtds, [])
@@ -63,36 +63,36 @@ class TestPageInfoWindow(FirefoxTestCase
             self.browser.menubar.select_by_id('tools-menu', 'menu_pageInfo')
 
         open_strategies = ('menu',
                            'shortcut',
                            opener,
                            )
 
         for trigger in open_strategies:
-            if trigger == 'shortcut' and self.platform == 'windows_nt':
+            if trigger == 'shortcut' and self.puppeteer.platform == 'windows_nt':
                 # The shortcut for page info window does not exist on windows.
                 self.assertRaises(ValueError, self.browser.open_page_info_window,
                                   trigger=trigger)
                 continue
 
             page_info = self.browser.open_page_info_window(trigger=trigger)
-            self.assertEquals(page_info, self.windows.current)
+            self.assertEquals(page_info, self.puppeteer.windows.current)
             page_info.close()
 
     def test_close_window(self):
         """Test various closing strategies."""
         def closer(win):
             win.send_shortcut(win.get_entity('closeWindow.key'), accel=True)
 
         # Close a tab by each trigger method
         close_strategies = ('menu',
                             'shortcut',
                             closer,
                             )
         for trigger in close_strategies:
             # menu only works on OS X
-            if trigger == 'menu' and self.platform != 'darwin':
+            if trigger == 'menu' and self.puppeteer.platform != 'darwin':
                 continue
 
             page_info = self.browser.open_page_info_window()
             page_info.close(trigger=trigger)
             self.assertTrue(page_info.closed)
--- a/testing/firefox-ui/tests/puppeteer/test_places.py
+++ b/testing/firefox-ui/tests/puppeteer/test_places.py
@@ -13,18 +13,18 @@ class TestPlaces(FirefoxTestCase):
         FirefoxTestCase.setUp(self)
 
         self.urls = [self.marionette.absolute_url('layout/mozilla_governance.html'),
                      self.marionette.absolute_url('layout/mozilla_grants.html'),
                      ]
 
     def tearDown(self):
         try:
-            self.places.restore_default_bookmarks()
-            self.places.remove_all_history()
+            self.puppeteer.places.restore_default_bookmarks()
+            self.puppeteer.places.remove_all_history()
         finally:
             FirefoxTestCase.tearDown(self)
 
     def get_all_urls_in_history(self):
         return self.marionette.execute_script("""
           let hs = Components.classes["@mozilla.org/browser/nav-history-service;1"]
                    .getService(Components.interfaces.nsINavHistoryService);
           let urls = [];
@@ -39,46 +39,47 @@ class TestPlaces(FirefoxTestCase):
           }
           root.containerOpen = false;
 
           return urls;
         """)
 
     def test_plugins(self):
         # TODO: Once we use a plugin, add a test case to verify that the data will be removed
-        self.places.clear_plugin_data()
+        self.puppeteer.places.clear_plugin_data()
 
     def test_bookmarks(self):
         star_button = self.marionette.find_element(By.ID, 'bookmarks-menu-button')
 
         # Visit URLs and bookmark them all
         for url in self.urls:
             with self.marionette.using_context('content'):
                 self.marionette.navigate(url)
 
-            Wait(self.marionette).until(lambda _: self.places.is_bookmark_star_button_ready())
+            Wait(self.marionette).until(
+                lambda _: self.puppeteer.places.is_bookmark_star_button_ready())
             star_button.click()
-            Wait(self.marionette).until(lambda _: self.places.is_bookmarked(url))
+            Wait(self.marionette).until(lambda _: self.puppeteer.places.is_bookmarked(url))
 
-            ids = self.places.get_folder_ids_for_url(url)
+            ids = self.puppeteer.places.get_folder_ids_for_url(url)
             self.assertEqual(len(ids), 1)
-            self.assertEqual(ids[0], self.places.bookmark_folders.unfiled)
+            self.assertEqual(ids[0], self.puppeteer.places.bookmark_folders.unfiled)
 
         # Restore default bookmarks, so the added URLs are gone
-        self.places.restore_default_bookmarks()
+        self.puppeteer.places.restore_default_bookmarks()
         for url in self.urls:
-            self.assertFalse(self.places.is_bookmarked(url))
+            self.assertFalse(self.puppeteer.places.is_bookmarked(url))
 
     def test_history(self):
         self.assertEqual(len(self.get_all_urls_in_history()), 0)
 
         # Visit pages and check that they are all present
         def load_urls():
             with self.marionette.using_context('content'):
                 for url in self.urls:
                     self.marionette.navigate(url)
-        self.places.wait_for_visited(self.urls, load_urls)
+        self.puppeteer.places.wait_for_visited(self.urls, load_urls)
 
         self.assertEqual(self.get_all_urls_in_history(), self.urls)
 
         # Check that both pages are no longer in the remove_all_history
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
         self.assertEqual(len(self.get_all_urls_in_history()), 0)
--- a/testing/firefox-ui/tests/puppeteer/test_prefs.py
+++ b/testing/firefox-ui/tests/puppeteer/test_prefs.py
@@ -26,121 +26,121 @@ class testPreferences(FirefoxTestCase):
             self.marionette.clear_pref('browser.tabs.loadBookmarksInBackground')
             self.marionette.clear_pref('browser.tabs.maxOpenBeforeWarn')
             self.marionette.clear_pref('browser.startup.homepage')
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_get_pref(self):
         # check correct types
-        self.assertTrue(isinstance(self.prefs.get_pref(self.bool_pref),
+        self.assertTrue(isinstance(self.puppeteer.prefs.get_pref(self.bool_pref),
                                    bool))
-        self.assertTrue(isinstance(self.prefs.get_pref(self.int_pref),
+        self.assertTrue(isinstance(self.puppeteer.prefs.get_pref(self.int_pref),
                                    int))
-        self.assertTrue(isinstance(self.prefs.get_pref(self.string_pref),
+        self.assertTrue(isinstance(self.puppeteer.prefs.get_pref(self.string_pref),
                                    basestring))
 
         # unknown
-        self.assertIsNone(self.prefs.get_pref(self.unknown_pref))
+        self.assertIsNone(self.puppeteer.prefs.get_pref(self.unknown_pref))
 
         # default branch
-        orig_value = self.prefs.get_pref(self.int_pref)
-        self.prefs.set_pref(self.int_pref, 99999)
-        self.assertEqual(self.prefs.get_pref(self.int_pref), 99999)
-        self.assertEqual(self.prefs.get_pref(self.int_pref, True), orig_value)
+        orig_value = self.puppeteer.prefs.get_pref(self.int_pref)
+        self.puppeteer.prefs.set_pref(self.int_pref, 99999)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.int_pref), 99999)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.int_pref, True), orig_value)
 
         # complex value
         properties_file = 'chrome://branding/locale/browserconfig.properties'
-        self.assertEqual(self.prefs.get_pref('browser.startup.homepage'),
+        self.assertEqual(self.puppeteer.prefs.get_pref('browser.startup.homepage'),
                          properties_file)
 
-        value = self.prefs.get_pref('browser.startup.homepage',
-                                    interface='nsIPrefLocalizedString')
+        value = self.puppeteer.prefs.get_pref('browser.startup.homepage',
+                                              interface='nsIPrefLocalizedString')
         self.assertNotEqual(value, properties_file)
 
     def test_set_pref_casted_values(self):
         # basestring as boolean
-        self.prefs.set_pref(self.bool_pref, '')
-        self.assertFalse(self.prefs.get_pref(self.bool_pref))
+        self.puppeteer.prefs.set_pref(self.bool_pref, '')
+        self.assertFalse(self.puppeteer.prefs.get_pref(self.bool_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.bool_pref)
 
-        self.prefs.set_pref(self.bool_pref, 'unittest')
-        self.assertTrue(self.prefs.get_pref(self.bool_pref))
+        self.puppeteer.prefs.set_pref(self.bool_pref, 'unittest')
+        self.assertTrue(self.puppeteer.prefs.get_pref(self.bool_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.bool_pref)
 
         # int as boolean
-        self.prefs.set_pref(self.bool_pref, 0)
-        self.assertFalse(self.prefs.get_pref(self.bool_pref))
+        self.puppeteer.prefs.set_pref(self.bool_pref, 0)
+        self.assertFalse(self.puppeteer.prefs.get_pref(self.bool_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.bool_pref)
 
-        self.prefs.set_pref(self.bool_pref, 5)
-        self.assertTrue(self.prefs.get_pref(self.bool_pref))
+        self.puppeteer.prefs.set_pref(self.bool_pref, 5)
+        self.assertTrue(self.puppeteer.prefs.get_pref(self.bool_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.bool_pref)
 
         # boolean as int
-        self.prefs.set_pref(self.int_pref, False)
-        self.assertEqual(self.prefs.get_pref(self.int_pref), 0)
+        self.puppeteer.prefs.set_pref(self.int_pref, False)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.int_pref), 0)
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.int_pref)
 
-        self.prefs.set_pref(self.int_pref, True)
-        self.assertEqual(self.prefs.get_pref(self.int_pref), 1)
+        self.puppeteer.prefs.set_pref(self.int_pref, True)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.int_pref), 1)
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.int_pref)
 
         # int as string
-        self.prefs.set_pref(self.string_pref, 54)
-        self.assertEqual(self.prefs.get_pref(self.string_pref), '54')
+        self.puppeteer.prefs.set_pref(self.string_pref, 54)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.string_pref), '54')
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.string_pref)
 
     def test_set_pref_invalid(self):
         self.assertRaises(AssertionError,
-                          self.prefs.set_pref, self.new_pref, None)
+                          self.puppeteer.prefs.set_pref, self.new_pref, None)
 
     def test_set_pref_new_preference(self):
-        self.prefs.set_pref(self.new_pref, True)
-        self.assertTrue(self.prefs.get_pref(self.new_pref))
+        self.puppeteer.prefs.set_pref(self.new_pref, True)
+        self.assertTrue(self.puppeteer.prefs.get_pref(self.new_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.new_pref)
 
-        self.prefs.set_pref(self.new_pref, 5)
-        self.assertEqual(self.prefs.get_pref(self.new_pref), 5)
+        self.puppeteer.prefs.set_pref(self.new_pref, 5)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.new_pref), 5)
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.new_pref)
 
-        self.prefs.set_pref(self.new_pref, 'test')
-        self.assertEqual(self.prefs.get_pref(self.new_pref), 'test')
+        self.puppeteer.prefs.set_pref(self.new_pref, 'test')
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.new_pref), 'test')
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.new_pref)
 
     def test_set_pref_new_values(self):
-        self.prefs.set_pref(self.bool_pref, True)
-        self.assertTrue(self.prefs.get_pref(self.bool_pref))
+        self.puppeteer.prefs.set_pref(self.bool_pref, True)
+        self.assertTrue(self.puppeteer.prefs.get_pref(self.bool_pref))
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.bool_pref)
 
-        self.prefs.set_pref(self.int_pref, 99999)
-        self.assertEqual(self.prefs.get_pref(self.int_pref), 99999)
+        self.puppeteer.prefs.set_pref(self.int_pref, 99999)
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.int_pref), 99999)
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.int_pref)
 
-        self.prefs.set_pref(self.string_pref, 'test_string')
-        self.assertEqual(self.prefs.get_pref(self.string_pref), 'test_string')
+        self.puppeteer.prefs.set_pref(self.string_pref, 'test_string')
+        self.assertEqual(self.puppeteer.prefs.get_pref(self.string_pref), 'test_string')
         # Remove when all self.marionette methods are implemented
         # Please see Bug 1293588
         self.marionette.clear_pref(self.string_pref)
--- a/testing/firefox-ui/tests/puppeteer/test_security.py
+++ b/testing/firefox-ui/tests/puppeteer/test_security.py
@@ -15,17 +15,17 @@ class TestSecurity(FirefoxTestCase):
         with self.marionette.using_context(self.marionette.CONTEXT_CONTENT):
             self.marionette.navigate(url)
 
         cert = self.browser.tabbar.tabs[0].certificate
         self.assertIn(cert['commonName'], url)
         self.assertEqual(cert['organization'], 'Mozilla Corporation')
         self.assertEqual(cert['issuerOrganization'], 'DigiCert Inc')
 
-        address = self.security.get_address_from_certificate(cert)
+        address = self.puppeteer.security.get_address_from_certificate(cert)
         self.assertIsNotNone(address)
         self.assertIsNotNone(address['city'])
         self.assertIsNotNone(address['country'])
         self.assertIsNotNone(address['postal_code'])
         self.assertIsNotNone(address['state'])
         self.assertIsNotNone(address['street'])
 
     def test_get_certificate(self):
--- a/testing/firefox-ui/tests/puppeteer/test_software_update.py
+++ b/testing/firefox-ui/tests/puppeteer/test_software_update.py
@@ -8,17 +8,17 @@ from firefox_ui_harness.testcases import
 
 from firefox_puppeteer.api.software_update import SoftwareUpdate
 
 
 class TestSoftwareUpdate(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
-        self.software_update = SoftwareUpdate(lambda: self.marionette)
+        self.software_update = SoftwareUpdate(self.marionette)
 
         self.saved_mar_channels = self.software_update.mar_channels.channels
         self.software_update.mar_channels.channels = set(['expected', 'channels'])
 
     def tearDown(self):
         try:
             self.software_update.mar_channels.channels = self.saved_mar_channels
         finally:
@@ -67,17 +67,17 @@ class TestSoftwareUpdate(FirefoxTestCase
     def test_staging_directory(self):
         self.assertTrue(self.software_update.staging_directory)
 
 
 class TestUpdateChannel(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
-        self.software_update = SoftwareUpdate(lambda: self.marionette)
+        self.software_update = SoftwareUpdate(self.marionette)
 
         self.saved_channel = self.software_update.update_channel.default_channel
         self.software_update.update_channel.default_channel = 'expected_channel'
 
     def tearDown(self):
         try:
             self.software_update.update_channel.default_channel = self.saved_channel
         finally:
@@ -93,17 +93,17 @@ class TestUpdateChannel(FirefoxTestCase)
         self.software_update.update_channel.default_channel = 'new_channel'
         self.assertEqual(self.software_update.update_channel.default_channel, 'new_channel')
 
 
 class TestMARChannels(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
-        self.software_update = SoftwareUpdate(lambda: self.marionette)
+        self.software_update = SoftwareUpdate(self.marionette)
 
         self.saved_mar_channels = self.software_update.mar_channels.channels
         self.software_update.mar_channels.channels = set(['expected', 'channels'])
 
     def tearDown(self):
         try:
             self.software_update.mar_channels.channels = self.saved_mar_channels
         finally:
--- a/testing/firefox-ui/tests/puppeteer/test_toolbars.py
+++ b/testing/firefox-ui/tests/puppeteer/test_toolbars.py
@@ -14,17 +14,17 @@ class TestNavBar(FirefoxTestCase):
         FirefoxTestCase.setUp(self)
 
         self.navbar = self.browser.navbar
         self.url = self.marionette.absolute_url('layout/mozilla.html')
 
         with self.marionette.using_context('content'):
             self.marionette.navigate('about:blank')
 
-        # TODO: check why self.places.remove_all_history() does not work here
+        # TODO: check why self.puppeteer.places.remove_all_history() does not work here
         self.marionette.execute_script("""
             let count = gBrowser.sessionHistory.count;
             gBrowser.sessionHistory.PurgeHistory(count);
         """)
 
     def test_elements(self):
         self.assertEqual(self.navbar.back_button.get_attribute('localName'), 'toolbarbutton')
         self.assertEqual(self.navbar.forward_button.get_attribute('localName'), 'toolbarbutton')
--- a/testing/firefox-ui/tests/puppeteer/test_update_wizard.py
+++ b/testing/firefox-ui/tests/puppeteer/test_update_wizard.py
@@ -19,17 +19,17 @@ class TestUpdateWizard(FirefoxTestCase):
             """)
 
         self.dialog = self.browser.open_window(callback=opener,
                                                expected_window_class=UpdateWizardDialog)
         self.wizard = self.dialog.wizard
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             FirefoxTestCase.tearDown(self)
 
     def test_basic(self):
         self.assertEqual(self.dialog.window_type, 'Update:Wizard')
         self.assertNotEqual(self.dialog.dtds, [])
         self.assertNotEqual(self.dialog.properties, [])
 
--- a/testing/firefox-ui/tests/puppeteer/test_utils.py
+++ b/testing/firefox-ui/tests/puppeteer/test_utils.py
@@ -6,40 +6,40 @@ from firefox_ui_harness.testcases import
 
 
 class TestSanitize(FirefoxTestCase):
 
     def setUp(self):
         FirefoxTestCase.setUp(self)
 
         # Clear all previous history and cookies.
-        self.places.remove_all_history()
+        self.puppeteer.places.remove_all_history()
         self.marionette.delete_all_cookies()
 
         self.urls = [
             'layout/mozilla_projects.html',
             'layout/mozilla.html',
             'layout/mozilla_mission.html',
             'cookies/cookie_single.html'
         ]
         self.urls = [self.marionette.absolute_url(url) for url in self.urls]
 
         # Open the test urls, including the single cookie setting page.
         def load_urls():
             with self.marionette.using_context('content'):
                 for url in self.urls:
                     self.marionette.navigate(url)
-        self.places.wait_for_visited(self.urls, load_urls)
+        self.puppeteer.places.wait_for_visited(self.urls, load_urls)
 
     def tearDown(self):
         FirefoxTestCase.tearDown(self)
 
     def test_sanitize_history(self):
         """ Clears history. """
-        self.assertEqual(self.places.get_all_urls_in_history(), self.urls)
-        self.utils.sanitize(data_type={"history": True})
-        self.assertEqual(self.places.get_all_urls_in_history(), [])
+        self.assertEqual(self.puppeteer.places.get_all_urls_in_history(), self.urls)
+        self.puppeteer.utils.sanitize(data_type={"history": True})
+        self.assertEqual(self.puppeteer.places.get_all_urls_in_history(), [])
 
     def test_sanitize_cookies(self):
         """ Clears cookies. """
         self.assertIsNotNone(self.marionette.get_cookie('litmus_1'))
-        self.utils.sanitize(data_type={"cookies": True})
+        self.puppeteer.utils.sanitize(data_type={"cookies": True})
         self.assertIsNone(self.marionette.get_cookie('litmus_1'))
--- a/testing/firefox-ui/tests/puppeteer/test_windows.py
+++ b/testing/firefox-ui/tests/puppeteer/test_windows.py
@@ -22,75 +22,75 @@ class BaseWindowTestCase(FirefoxTestCase
         doesn't have enough time to get itself all sorted before
         the timeout gets hit, which results in the parent killing
         the content process manually, which generates a crash report,
         which causes these tests to orange. We side-step this by
         setting dom.ipc.tabs.shutdownTimeoutSecs to 0, which disables
         the shutdown timer.
         """
         FirefoxTestCase.setUp(self)
-        self.prefs.set_pref('dom.ipc.tabs.shutdownTimeoutSecs', 0)
+        self.puppeteer.prefs.set_pref('dom.ipc.tabs.shutdownTimeoutSecs', 0)
 
     def tearDown(self):
         try:
             self.marionette.clear_pref('dom.ipc.tabs.shutdownTimeoutSecs')
         finally:
             FirefoxTestCase.tearDown(self)
 
 
 class TestWindows(BaseWindowTestCase):
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             BaseWindowTestCase.tearDown(self)
 
     def test_switch_to(self):
         url = self.marionette.absolute_url('layout/mozilla.html')
 
         # Open two more windows
         for index in range(0, 2):
             self.marionette.execute_script(""" window.open(); """)
 
-        windows = self.windows.all
+        windows = self.puppeteer.windows.all
         self.assertEquals(len(windows), 3)
 
         # Switch to the 2nd window
-        self.windows.switch_to(windows[1].handle)
+        self.puppeteer.windows.switch_to(windows[1].handle)
         self.assertEquals(windows[1].handle, self.marionette.current_chrome_window_handle)
 
         # TODO: Needs updated tabs module for improved navigation
         with self.marionette.using_context('content'):
             self.marionette.navigate(url)
 
         # Switch to the last window and find 2nd window by URL
-        self.windows.switch_to(windows[2].handle)
+        self.puppeteer.windows.switch_to(windows[2].handle)
 
         # TODO: A window can have multiple tabs, so this may need an update
         # when the tabs module gets implemented
         def find_by_url(win):
             with win.marionette.using_context('content'):
                 return win.marionette.get_url() == url
 
-        self.windows.switch_to(find_by_url)
+        self.puppeteer.windows.switch_to(find_by_url)
         self.assertEquals(windows[1].handle, self.marionette.current_chrome_window_handle)
 
-        self.windows.switch_to(find_by_url)
+        self.puppeteer.windows.switch_to(find_by_url)
 
         # Switching to an unknown handles has to fail
         self.assertRaises(NoSuchWindowException,
-                          self.windows.switch_to, "humbug")
+                          self.puppeteer.windows.switch_to, "humbug")
         self.assertRaises(NoSuchWindowException,
-                          self.windows.switch_to, lambda win: False)
+                          self.puppeteer.windows.switch_to, lambda win: False)
 
-        self.windows.close_all([self.browser])
+        self.puppeteer.windows.close_all([self.browser])
         self.browser.switch_to()
 
-        self.assertEqual(len(self.windows.all), 1)
+        self.assertEqual(len(self.puppeteer.windows.all), 1)
 
     def test_switch_to_unknown_window_type(self):
         def open_by_js(_):
             with self.marionette.using_context('chrome'):
                 self.marionette.execute_script("""
                   window.open('chrome://browser/content/safeMode.xul', '_blank',
                               'chrome,centerscreen,resizable=no');
                 """)
@@ -99,50 +99,48 @@ class TestWindows(BaseWindowTestCase):
         win.close()
         self.browser.switch_to()
 
 
 class TestBaseWindow(BaseWindowTestCase):
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             BaseWindowTestCase.tearDown(self)
 
     def test_basics(self):
         # force BaseWindow instance
-        win1 = BaseWindow(lambda: self.marionette, self.browser.handle)
+        win1 = BaseWindow(self.marionette, self.browser.handle)
 
         self.assertEquals(win1.handle, self.marionette.current_chrome_window_handle)
         self.assertEquals(win1.window_element,
                           self.marionette.find_element(By.CSS_SELECTOR, ':root'))
         self.assertEquals(win1.window_element.get_attribute('windowtype'),
                           self.marionette.get_window_type())
         self.assertFalse(win1.closed)
 
         # Test invalid parameters for BaseWindow constructor
-        self.assertRaises(TypeError,
-                          BaseWindow, self.marionette, self.browser.handle)
         self.assertRaises(errors.UnknownWindowError,
-                          BaseWindow, lambda: self.marionette, 10)
+                          BaseWindow, self.marionette, 10)
 
         # Test invalid shortcuts
         self.assertRaises(KeyError,
                           win1.send_shortcut, 'l', acel=True)
 
     def test_open_close(self):
         # force BaseWindow instance
-        win1 = BaseWindow(lambda: self.marionette, self.browser.handle)
+        win1 = BaseWindow(self.marionette, self.browser.handle)
 
         # Open a new window (will be focused), and check states
         win2 = win1.open_window()
 
         # force BaseWindow instance
-        win2 = BaseWindow(lambda: self.marionette, win2.handle)
+        win2 = BaseWindow(self.marionette, win2.handle)
 
         self.assertEquals(len(self.marionette.chrome_window_handles), 2)
         self.assertNotEquals(win1.handle, win2.handle)
         self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle)
 
         win2.close()
 
         self.assertTrue(win2.closed)
@@ -157,103 +155,103 @@ class TestBaseWindow(BaseWindowTestCase)
             window.marionette.execute_script(""" window.open(); """)
 
         def closer(window):
             window.marionette.execute_script(""" window.close(); """)
 
         win2 = win1.open_window(callback=opener)
 
         # force BaseWindow instance
-        win2 = BaseWindow(lambda: self.marionette, win2.handle)
+        win2 = BaseWindow(self.marionette, win2.handle)
 
         self.assertEquals(len(self.marionette.chrome_window_handles), 2)
         win2.close(callback=closer)
 
         win1.focus()
 
         # Check for an unexpected window class
         self.assertRaises(errors.UnexpectedWindowTypeError,
                           win1.open_window, expected_window_class=BaseWindow)
-        self.windows.close_all([win1])
+        self.puppeteer.windows.close_all([win1])
 
     def test_switch_to_and_focus(self):
         # force BaseWindow instance
-        win1 = BaseWindow(lambda: self.marionette, self.browser.handle)
+        win1 = BaseWindow(self.marionette, self.browser.handle)
 
         # Open a new window (will be focused), and check states
         win2 = win1.open_window()
 
         # force BaseWindow instance
-        win2 = BaseWindow(lambda: self.marionette, win2.handle)
+        win2 = BaseWindow(self.marionette, win2.handle)
 
         self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle)
-        self.assertEquals(win2.handle, self.windows.focused_chrome_window_handle)
+        self.assertEquals(win2.handle, self.puppeteer.windows.focused_chrome_window_handle)
         self.assertFalse(win1.focused)
         self.assertTrue(win2.focused)
 
         # Switch back to win1 without moving the focus, but focus separately
         win1.switch_to()
         self.assertEquals(win1.handle, self.marionette.current_chrome_window_handle)
         self.assertTrue(win2.focused)
 
         win1.focus()
         self.assertTrue(win1.focused)
 
         # Switch back to win2 by focusing it directly
         win2.focus()
         self.assertEquals(win2.handle, self.marionette.current_chrome_window_handle)
-        self.assertEquals(win2.handle, self.windows.focused_chrome_window_handle)
+        self.assertEquals(win2.handle, self.puppeteer.windows.focused_chrome_window_handle)
         self.assertTrue(win2.focused)
 
         # Close win2, and check that it keeps active but looses focus
         win2.switch_to()
         win2.close()
 
         win1.switch_to()
 
 
 class TestBrowserWindow(BaseWindowTestCase):
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             BaseWindowTestCase.tearDown(self)
 
     def test_basic(self):
         self.assertNotEqual(self.browser.dtds, [])
         self.assertNotEqual(self.browser.properties, [])
 
         self.assertFalse(self.browser.is_private)
 
         self.assertIsNotNone(self.browser.menubar)
         self.assertIsNotNone(self.browser.navbar)
         self.assertIsNotNone(self.browser.tabbar)
 
     def test_open_close(self):
         # open and close a new browser windows by menu
         win2 = self.browser.open_browser(trigger='menu')
-        self.assertEquals(win2, self.windows.current)
+        self.assertEquals(win2, self.puppeteer.windows.current)
         self.assertFalse(self.browser.is_private)
         win2.close(trigger='menu')
 
         # open and close a new browser window by shortcut
         win2 = self.browser.open_browser(trigger='shortcut')
-        self.assertEquals(win2, self.windows.current)
+        self.assertEquals(win2, self.puppeteer.windows.current)
         self.assertFalse(self.browser.is_private)
         win2.close(trigger='shortcut')
 
         # open and close a new private browsing window
         win2 = self.browser.open_browser(is_private=True)
-        self.assertEquals(win2, self.windows.current)
+        self.assertEquals(win2, self.puppeteer.windows.current)
         self.assertTrue(win2.is_private)
         win2.close()
 
         # open and close a new private browsing window
         win2 = self.browser.open_browser(trigger='shortcut', is_private=True)
-        self.assertEquals(win2, self.windows.current)
+        self.assertEquals(win2, self.puppeteer.windows.current)
         self.assertTrue(win2.is_private)
         win2.close()
 
         # force closing a window
         win2 = self.browser.open_browser()
-        self.assertEquals(win2, self.windows.current)
+        self.assertEquals(win2, self.puppeteer.windows.current)
         win2.close(force=True)
--- a/testing/firefox-ui/tests/update/direct/test_direct_update.py
+++ b/testing/firefox-ui/tests/update/direct/test_direct_update.py
@@ -7,15 +7,15 @@ from firefox_ui_harness.testcases import
 
 class TestDirectUpdate(UpdateTestCase):
 
     def setUp(self):
         UpdateTestCase.setUp(self, is_fallback=False)
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             UpdateTestCase.tearDown(self)
 
     def test_update(self):
         self.download_and_apply_available_update(force_fallback=False)
         self.check_update_applied()
--- a/testing/firefox-ui/tests/update/fallback/test_fallback_update.py
+++ b/testing/firefox-ui/tests/update/fallback/test_fallback_update.py
@@ -7,16 +7,16 @@ from firefox_ui_harness.testcases import
 
 class TestFallbackUpdate(UpdateTestCase):
 
     def setUp(self):
         UpdateTestCase.setUp(self, is_fallback=True)
 
     def tearDown(self):
         try:
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
         finally:
             UpdateTestCase.tearDown(self)
 
     def test_update(self):
         self.download_and_apply_available_update(force_fallback=True)
         self.download_and_apply_forced_update()
         self.check_update_applied()
--- a/testing/puppeteer/firefox/firefox_puppeteer/__init__.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/__init__.py
@@ -1,90 +1,9 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
-from decorators import use_class_as_property
-
-
-__version__ = '52.0.0'
+from firefox_puppeteer.mixins import PuppeteerMixin
+from firefox_puppeteer.puppeteer import Puppeteer
 
 
-class Puppeteer(object):
-    """The puppeteer class is used to expose libraries to test cases.
-
-    example:
-    `class MyTestCase(MarionetteTestCase, Puppeteer)`
-
-    Each library can be referenced by its puppeteer name as a member of a
-    the TestCase instance. For example, from within a test method, the
-    "current_window" member of the "Browser" class can be accessed via
-    "self.browser.current_window".
-    """
-
-    def __init__(self):
-        self.marionette = None
-
-    def get_marionette(self):
-        return self.marionette
-
-    @use_class_as_property('api.appinfo.AppInfo')
-    def appinfo(self):
-        """
-        Provides access to members of the appinfo  api.
-
-        See the :class:`~api.appinfo.AppInfo` reference.
-        """
-
-    @use_class_as_property('api.keys.Keys')
-    def keys(self):
-        """
-        Provides a definition of control keys to use with keyboard shortcuts.
-        For example, keys.CONTROL or keys.ALT.
-        See the :class:`~api.keys.Keys` reference.
-        """
-
-    @use_class_as_property('api.places.Places')
-    def places(self):
-        """Provides low-level access to several bookmark and history related actions.
-
-        See the :class:`~api.places.Places` reference.
-        """
-
-    @use_class_as_property('api.utils.Utils')
-    def utils(self):
-        """Provides an api for interacting with utility actions.
-
-        See the :class:`~api.utils.Utils` reference.
-        """
-
-    @property
-    def platform(self):
-        """Returns the lowercased platform name.
-
-        :returns: Platform name
-        """
-        return self.marionette.session_capabilities['platformName']
-
-    @use_class_as_property('api.prefs.Preferences')
-    def prefs(self):
-        """
-        Provides an api for setting and inspecting preferences, as see in
-        about:config.
-
-        See the :class:`~api.prefs.Preferences` reference.
-        """
-
-    @use_class_as_property('api.security.Security')
-    def security(self):
-        """
-        Provides an api for accessing security related properties and helpers.
-
-        See the :class:`~api.security.Security` reference.
-        """
-
-    @use_class_as_property('ui.windows.Windows')
-    def windows(self):
-        """
-        Provides shortcuts to the top-level windows.
-
-        See the :class:`~ui.window.Windows` reference.
-        """
+__version__ = '52.1.0'
--- a/testing/puppeteer/firefox/firefox_puppeteer/api/keys.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/api/keys.py
@@ -4,17 +4,14 @@
 
 import marionette_driver
 
 
 class Keys(marionette_driver.keys.Keys):
     """Proxy to marionette's keys with an "accel" provided for convenience
     testing across platforms."""
 
-    def __init__(self, marionette_getter):
-        self.marionette_getter = marionette_getter
-
-        caps = self.marionette_getter().session_capabilities
-        self.isDarwin = caps['platformName'] == 'darwin'
+    def __init__(self, marionette):
+        self.isDarwin = marionette.session_capabilities['platformName'] == 'darwin'
 
     @property
     def ACCEL(self):
         return self.META if self.isDarwin else self.CONTROL
--- a/testing/puppeteer/firefox/firefox_puppeteer/api/software_update.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/api/software_update.py
@@ -77,18 +77,18 @@ class ActiveUpdate(BaseLib):
     """)
 
 
 class MARChannels(BaseLib):
     """Class to handle the allowed MAR channels as listed in update-settings.ini."""
     INI_SECTION = 'Settings'
     INI_OPTION = 'ACCEPTED_MAR_CHANNEL_IDS'
 
-    def __init__(self, marionette_getter):
-        BaseLib.__init__(self, marionette_getter)
+    def __init__(self, marionette):
+        BaseLib.__init__(self, marionette)
 
         self._ini_file_path = self.marionette.execute_script("""
           Components.utils.import('resource://gre/modules/Services.jsm');
 
           let file = Services.dirsvc.get('GreD', Components.interfaces.nsIFile);
           file.append('update-settings.ini');
 
           return file.path;
@@ -163,25 +163,25 @@ class MARChannels(BaseLib):
 class SoftwareUpdate(BaseLib):
     """The SoftwareUpdate API adds support for an easy access to the update process."""
     PREF_APP_DISTRIBUTION = 'distribution.id'
     PREF_APP_DISTRIBUTION_VERSION = 'distribution.version'
     PREF_APP_UPDATE_URL = 'app.update.url'
     PREF_APP_UPDATE_URL_OVERRIDE = 'app.update.url.override'
     PREF_DISABLED_ADDONS = 'extensions.disabledAddons'
 
-    def __init__(self, marionette_getter):
-        BaseLib.__init__(self, marionette_getter)
+    def __init__(self, marionette):
+        BaseLib.__init__(self, marionette)
 
-        self.app_info = AppInfo(marionette_getter)
-        self.prefs = Preferences(marionette_getter)
+        self.app_info = AppInfo(marionette)
+        self.prefs = Preferences(marionette)
 
-        self._update_channel = UpdateChannel(marionette_getter)
-        self._mar_channels = MARChannels(marionette_getter)
-        self._active_update = ActiveUpdate(marionette_getter)
+        self._update_channel = UpdateChannel(marionette)
+        self._mar_channels = MARChannels(marionette)
+        self._active_update = ActiveUpdate(marionette)
 
     @property
     def ABI(self):
         """Get the customized ABI for the update service.
 
         :returns: ABI version
         """
         abi = self.app_info.XPCOMABI
@@ -373,20 +373,20 @@ class SoftwareUpdate(BaseLib):
 
         return url
 
 
 class UpdateChannel(BaseLib):
     """Class to handle the update channel as listed in channel-prefs.js"""
     REGEX_UPDATE_CHANNEL = re.compile(r'("app\.update\.channel", ")([^"].*)(?=")')
 
-    def __init__(self, marionette_getter):
-        BaseLib.__init__(self, marionette_getter)
+    def __init__(self, marionette):
+        BaseLib.__init__(self, marionette)
 
-        self.prefs = Preferences(marionette_getter)
+        self.prefs = Preferences(marionette)
 
         self.file_path = self.marionette.execute_script("""
           Components.utils.import('resource://gre/modules/Services.jsm');
 
           let file = Services.dirsvc.get('PrfDef', Components.interfaces.nsIFile);
           file.append('channel-prefs.js');
 
           return file.path;
--- a/testing/puppeteer/firefox/firefox_puppeteer/api/utils.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/api/utils.py
@@ -8,17 +8,17 @@ from firefox_puppeteer.base import BaseL
 
 
 class Utils(BaseLib):
     """Low-level access to utility actions."""
 
     def __init__(self, *args, **kwargs):
         BaseLib.__init__(self, *args, **kwargs)
 
-        self._permissions = Permissions(lambda: self.marionette)
+        self._permissions = Permissions(self.marionette)
 
     @property
     def permissions(self):
         """Handling of various permissions for hosts.
 
         :returns: Instance of the Permissions class.
         """
         return self._permissions
--- a/testing/puppeteer/firefox/firefox_puppeteer/base.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/base.py
@@ -1,23 +1,14 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 class BaseLib(object):
     """A base class that handles lazily setting the "client" class attribute."""
 
-    def __init__(self, marionette_getter):
-        if not callable(marionette_getter):
-            raise TypeError('Invalid callback for "marionette_getter": %s' % marionette_getter)
-
-        self._marionette = None
-        self._marionette_getter = marionette_getter
+    def __init__(self, marionette):
+        self._marionette = marionette
 
     @property
     def marionette(self):
-        if self._marionette is None:
-            self._marionette = self._marionette_getter()
         return self._marionette
-
-    def get_marionette(self):
-        return self.marionette
--- a/testing/puppeteer/firefox/firefox_puppeteer/decorators.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/decorators.py
@@ -23,13 +23,13 @@ class use_class_as_property(object):
         @wraps(func)
         def _(cls, *args, **kwargs):
             tag = '_{}_{}'.format(self.mod_name, self.cls_name)
             prop = getattr(cls, tag, None)
 
             if not prop:
                 module = import_module('.{}'.format(self.mod_name),
                                        'firefox_puppeteer')
-                prop = getattr(module, self.cls_name)(cls.get_marionette)
+                prop = getattr(module, self.cls_name)(cls.marionette)
                 setattr(cls, tag, prop)
             func(cls, *args, **kwargs)
             return prop
         return _
rename from testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
rename to testing/puppeteer/firefox/firefox_puppeteer/mixins.py
--- a/testing/puppeteer/firefox/firefox_puppeteer/testcases/base.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/mixins.py
@@ -1,44 +1,37 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-import unittest
-
-from firefox_puppeteer import Puppeteer
+from firefox_puppeteer.puppeteer import Puppeteer
 from firefox_puppeteer.ui.browser.window import BrowserWindow
 
 
-class BaseFirefoxTestCase(unittest.TestCase, Puppeteer):
-    """Base TestCase class for Firefox Desktop tests.
+class PuppeteerMixin(object):
+    """Mix-in class for Firefox specific API modules exposed to test scope.
 
-    This is designed to enhance MarionetteTestCase by inserting the Puppeteer
-    mixin class (so Firefox specific API modules are exposed to test scope) and
-    providing common set-up and tear-down code for Firefox tests.
+    It also provides common set-up and tear-down code for Firefox tests.
 
-    Child classes are expected to also subclass MarionetteTestCase such that
-    MarionetteTestCase is inserted into the MRO after FirefoxTestCase but before
-    unittest.TestCase.
+    Child test case classes are expected to also subclass MarionetteTestCase such
+    that PuppeteerMixin is followed by MarionetteTestCase. This will insert the
+    Puppeteer mixin before the MarionetteTestCase into the MRO.
 
     example:
-    `class AwesomeTestCase(FirefoxTestCase, MarionetteTestCase)`
+    `class MyTestCase(PuppeteerMixin, MarionetteTestCase)`
 
     The key role of MarionetteTestCase is to set self.marionette appropriately
-    in `__init__`. Any TestCase class that satisfies this requirement is
+    in `setUp()`. Any TestCase class that satisfies this requirement is
     compatible with this class.
 
     If you're extending the inheritance tree further to make specialized
     TestCases, favour the use of super() as opposed to explicit calls to a
     parent class.
 
     """
-    def __init__(self, *args, **kwargs):
-        super(BaseFirefoxTestCase, self).__init__(*args, **kwargs)
-
     def _check_and_fix_leaked_handles(self):
         handle_count = len(self.marionette.window_handles)
         url = []
 
         try:
             # Verify the existence of leaked tabs and print their URLs.
             if self._start_handle_count < handle_count:
                 message = ('A test must not leak window handles. This test started with '
@@ -50,52 +43,54 @@ class BaseFirefoxTestCase(unittest.TestC
                             url.append(' %s' % self.marionette.get_url())
                 self.assertListEqual(self._init_tab_handles, self.marionette.window_handles,
                                      message + ','.join(url))
         finally:
             # For clean-up make sure we work on a proper browser window
             if not self.browser or self.browser.closed:
                 # Find a proper replacement browser window
                 # TODO: We have to make this less error prone in case no browser is open.
-                self.browser = self.windows.switch_to(lambda win: type(win) is BrowserWindow)
+                self.browser = self.puppeteer.windows.switch_to(
+                    lambda win: type(win) is BrowserWindow)
 
             # Ensure to close all the remaining chrome windows to give following
             # tests a proper start condition and make them not fail.
-            self.windows.close_all([self.browser])
+            self.puppeteer.windows.close_all([self.browser])
             self.browser.focus()
 
             # Also close all remaining tabs
             self.browser.tabbar.close_all_tabs([self.browser.tabbar.tabs[0]])
             self.browser.tabbar.tabs[0].switch_to()
 
     def restart(self, **kwargs):
         """Restart Firefox and re-initialize data.
 
         :param flags: Specific restart flags for Firefox
         """
         self.marionette.restart(in_app=not kwargs.get('clean'), **kwargs)
 
         # Ensure that we always have a valid browser instance available
-        self.browser = self.windows.switch_to(lambda win: type(win) is BrowserWindow)
+        self.browser = self.puppeteer.windows.switch_to(lambda win: type(win) is BrowserWindow)
 
     def setUp(self, *args, **kwargs):
-        super(BaseFirefoxTestCase, self).setUp(*args, **kwargs)
+        super(PuppeteerMixin, self).setUp(*args, **kwargs)
 
         self._start_handle_count = len(self.marionette.window_handles)
         self._init_tab_handles = self.marionette.window_handles
         self.marionette.set_context('chrome')
 
-        self.browser = self.windows.current
+        self.puppeteer = Puppeteer(self.marionette)
+        self.browser = self.puppeteer.windows.current
         self.browser.focus()
         with self.marionette.using_context(self.marionette.CONTEXT_CONTENT):
             # Ensure that we have a default page opened
-            self.marionette.navigate(self.prefs.get_pref('browser.newtab.url'))
+            self.marionette.navigate(self.puppeteer.prefs.get_pref('browser.newtab.url'))
 
     def tearDown(self, *args, **kwargs):
         self.marionette.set_context('chrome')
 
         try:
             # This code should be run after all other tearDown code
             # so that in case of a failure, further tests will not run
             # in a state that is more inconsistent than necessary.
             self._check_and_fix_leaked_handles()
         finally:
-            super(BaseFirefoxTestCase, self).tearDown(*args, **kwargs)
+            super(PuppeteerMixin, self).tearDown(*args, **kwargs)
new file mode 100644
--- /dev/null
+++ b/testing/puppeteer/firefox/firefox_puppeteer/puppeteer.py
@@ -0,0 +1,84 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from decorators import use_class_as_property
+
+
+class Puppeteer(object):
+    """The puppeteer class is used to expose additional API and UI libraries.
+
+    Each library can be referenced by its puppeteer name as a member of a
+    Puppeteer instance. For example, the `current_window` member of the
+    `Browser` class can be accessed via `puppeteer.browser.current_window`.
+    """
+
+    def __init__(self, marionette):
+        self._marionette = marionette
+
+    @property
+    def marionette(self):
+        return self._marionette
+
+    @use_class_as_property('api.appinfo.AppInfo')
+    def appinfo(self):
+        """
+        Provides access to members of the appinfo  api.
+
+        See the :class:`~api.appinfo.AppInfo` reference.
+        """
+
+    @use_class_as_property('api.keys.Keys')
+    def keys(self):
+        """
+        Provides a definition of control keys to use with keyboard shortcuts.
+        For example, keys.CONTROL or keys.ALT.
+        See the :class:`~api.keys.Keys` reference.
+        """
+
+    @use_class_as_property('api.places.Places')
+    def places(self):
+        """Provides low-level access to several bookmark and history related actions.
+
+        See the :class:`~api.places.Places` reference.
+        """
+
+    @use_class_as_property('api.utils.Utils')
+    def utils(self):
+        """Provides an api for interacting with utility actions.
+
+        See the :class:`~api.utils.Utils` reference.
+        """
+
+    @property
+    def platform(self):
+        """Returns the lowercased platform name.
+
+        :returns: Platform name
+        """
+        return self.marionette.session_capabilities['platformName']
+
+    @use_class_as_property('api.prefs.Preferences')
+    def prefs(self):
+        """
+        Provides an api for setting and inspecting preferences, as see in
+        about:config.
+
+        See the :class:`~api.prefs.Preferences` reference.
+        """
+
+    @use_class_as_property('api.security.Security')
+    def security(self):
+        """
+        Provides an api for accessing security related properties and helpers.
+
+        See the :class:`~api.security.Security` reference.
+        """
+
+    @use_class_as_property('ui.windows.Windows')
+    def windows(self):
+        """
+        Provides shortcuts to the top-level windows.
+
+        See the :class:`~ui.window.Windows` reference.
+        """
deleted file mode 100644
--- a/testing/puppeteer/firefox/firefox_puppeteer/testcases/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-from firefox_puppeteer.testcases.base import BaseFirefoxTestCase
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/deck.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/deck.py
@@ -22,17 +22,17 @@ class Deck(UIBaseLib):
                    'checkingForUpdates': CheckingForUpdatesPanel,
                    'downloadAndInstall': DownloadAndInstallPanel,
                    'downloadFailed': DownloadFailedPanel,
                    'downloading': DownloadingPanel,
                    'noUpdatesFound': NoUpdatesFoundPanel,
                    }
 
         panel = self.element.find_element(By.ID, panel_id)
-        return mapping.get(panel_id, Panel)(lambda: self.marionette, self.window, panel)
+        return mapping.get(panel_id, Panel)(self.marionette, self.window, panel)
 
     # Properties for visual elements of the deck #
 
     @property
     def apply(self):
         """The :class:`ApplyPanel` instance for the apply panel.
 
         :returns: :class:`ApplyPanel` instance.
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/window.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/about_window/window.py
@@ -24,12 +24,12 @@ class AboutWindow(BaseWindow):
     def deck(self):
         """The :class:`Deck` instance which represents the deck.
 
         :returns: Reference to the deck.
         """
         self.switch_to()
 
         deck = self.window_element.find_element(By.ID, 'updateDeck')
-        return Deck(lambda: self.marionette, self, deck)
+        return Deck(self.marionette, self, deck)
 
 
 Windows.register_window(AboutWindow.window_type, AboutWindow)
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/base.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/base.py
@@ -6,22 +6,22 @@ from marionette_driver.marionette import
 
 from firefox_puppeteer.base import BaseLib
 from firefox_puppeteer.ui.windows import BaseWindow
 
 
 class UIBaseLib(BaseLib):
     """A base class for all UI element wrapper classes inside a chrome window."""
 
-    def __init__(self, marionette_getter, window, element):
+    def __init__(self, marionette, window, element):
 
         assert isinstance(window, BaseWindow)
         assert isinstance(element, HTMLElement)
 
-        BaseLib.__init__(self, marionette_getter)
+        BaseLib.__init__(self, marionette)
         self._window = window
         self._element = element
 
     @property
     def element(self):
         """Returns the reference to the underlying DOM element.
 
         :returns: Reference to the DOM element
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/tabbar.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/tabbar.py
@@ -21,17 +21,17 @@ class TabBar(UIBaseLib):
 
     @property
     def menupanel(self):
         """A :class:`MenuPanel` instance which represents the menu panel
         at the far right side of the tabs toolbar.
 
         :returns: :class:`MenuPanel` instance.
         """
-        return MenuPanel(lambda: self.marionette, self.window)
+        return MenuPanel(self.marionette, self.window)
 
     @property
     def newtab_button(self):
         """The DOM element which represents the new tab button.
 
         :returns: Reference to the new tab button.
         """
         return self.toolbar.find_element(By.ANON_ATTRIBUTE, {'anonid': 'tabs-newtab-button'})
@@ -39,17 +39,17 @@ class TabBar(UIBaseLib):
     @property
     def tabs(self):
         """List of all the :class:`Tab` instances of the current browser window.
 
         :returns: List of :class:`Tab` instances.
         """
         tabs = self.toolbar.find_elements(By.TAG_NAME, 'tab')
 
-        return [Tab(lambda: self.marionette, self.window, tab) for tab in tabs]
+        return [Tab(self.marionette, self.window, tab) for tab in tabs]
 
     @property
     def toolbar(self):
         """The DOM element which represents the tab toolbar.
 
         :returns: Reference to the tabs toolbar.
         """
         return self.element
@@ -201,20 +201,20 @@ class TabBar(UIBaseLib):
         """, script_args=[tab_element])
 
         return handle
 
 
 class Tab(UIBaseLib):
     """Wraps a tab DOM element."""
 
-    def __init__(self, marionette_getter, window, element):
-        UIBaseLib.__init__(self, marionette_getter, window, element)
+    def __init__(self, marionette, window, element):
+        UIBaseLib.__init__(self, marionette, window, element)
 
-        self._security = Security(lambda: self.marionette)
+        self._security = Security(self.marionette)
         self._handle = None
 
     # Properties for visual elements of tabs #
 
     @property
     def close_button(self):
         """The DOM element which represents the tab close button.
 
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/toolbars.py
@@ -44,17 +44,17 @@ class NavBar(UIBaseLib):
     def locationbar(self):
         """Provides access to the DOM elements contained in the
         locationbar.
 
         See the :class:`LocationBar` reference.
         """
         if not self._locationbar:
             urlbar = self.marionette.find_element(By.ID, 'urlbar')
-            self._locationbar = LocationBar(lambda: self.marionette, self.window, urlbar)
+            self._locationbar = LocationBar(self.marionette, self.window, urlbar)
 
         return self._locationbar
 
     @property
     def menu_button(self):
         """Provides access to the DOM element menu button in the navbar.
 
         :returns: Reference to the menu button element.
@@ -83,17 +83,17 @@ class LocationBar(UIBaseLib):
     @property
     def autocomplete_results(self):
         """Provides access to and methods for the location bar
         autocomplete results.
 
         See the :class:`AutocompleteResults` reference."""
         if not self._autocomplete_results:
             popup = self.marionette.find_element(By.ID, 'PopupAutoCompleteRichResult')
-            self._autocomplete_results = AutocompleteResults(lambda: self.marionette,
+            self._autocomplete_results = AutocompleteResults(self.marionette,
                                                              self.window, popup)
 
         return self._autocomplete_results
 
     def clear(self):
         """Clears the contents of the url bar (via the DELETE shortcut)."""
         self.focus('shortcut')
         self.urlbar.send_keys(keys.Keys.DELETE)
@@ -207,17 +207,17 @@ class LocationBar(UIBaseLib):
     def identity_popup(self):
         """Provides utility members for accessing and manipulating the
         identity popup.
 
         See the :class:`IdentityPopup` reference.
         """
         if not self._identity_popup:
             popup = self.marionette.find_element(By.ID, 'identity-popup')
-            self._identity_popup = IdentityPopup(lambda: self.marionette,
+            self._identity_popup = IdentityPopup(self.marionette,
                                                  self.window, popup)
 
         return self._identity_popup
 
     def load_url(self, url):
         """Load the specified url in the location bar by synthesized
         keystrokes.
 
@@ -447,17 +447,17 @@ class IdentityPopup(UIBaseLib):
     def view(self):
         """Provides utility members for accessing and manipulating the
         identity popup's multi view.
 
         See the :class:`IdentityPopupMultiView` reference.
         """
         if not self._view:
             view = self.marionette.find_element(By.ID, 'identity-popup-multiView')
-            self._view = IdentityPopupMultiView(lambda: self.marionette, self.window, view)
+            self._view = IdentityPopupMultiView(self.marionette, self.window, view)
 
         return self._view
 
 
 class IdentityPopupMultiView(UIBaseLib):
 
     def _create_view_for_id(self, view_id):
         """Creates an instance of :class:`IdentityPopupView` for the specified view id.
@@ -466,17 +466,17 @@ class IdentityPopupMultiView(UIBaseLib):
 
         :returns: :class:`IdentityPopupView` instance
         """
         mapping = {'identity-popup-mainView': IdentityPopupMainView,
                    'identity-popup-securityView': IdentityPopupSecurityView,
                    }
 
         view = self.marionette.find_element(By.ID, view_id)
-        return mapping.get(view_id, IdentityPopupView)(lambda: self.marionette, self.window, view)
+        return mapping.get(view_id, IdentityPopupView)(self.marionette, self.window, view)
 
     @property
     def main(self):
         """The DOM element which represents the main view.
 
         :returns: Reference to the main view.
         """
         return self._create_view_for_id('identity-popup-mainView')
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/window.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/browser/window.py
@@ -1,14 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
 # You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from marionette_driver import By, Wait
 from marionette_driver.errors import NoSuchElementException
+
 from firefox_puppeteer.ui.about_window.window import AboutWindow
 from firefox_puppeteer.ui.browser.notifications import (
     AddOnInstallBlockedNotification,
     AddOnInstallConfirmationNotification,
     AddOnInstallCompleteNotification,
     AddOnInstallFailedNotification,
     AddOnProgressNotification,
     BaseNotification)
@@ -74,17 +75,17 @@ class BrowserWindow(BaseWindow):
         the back, forward and home buttons. It also contains the location bar.
 
         See the :class:`~ui.browser.toolbars.NavBar` reference.
         """
         self.switch_to()
 
         if not self._navbar:
             navbar = self.window_element.find_element(By.ID, 'nav-bar')
-            self._navbar = NavBar(lambda: self.marionette, self, navbar)
+            self._navbar = NavBar(self.marionette, self, navbar)
 
         return self._navbar
 
     @property
     def notification(self):
         """Provides access to the currently displayed notification."""
 
         notifications_map = {
@@ -96,17 +97,17 @@ class BrowserWindow(BaseWindow):
         }
 
         try:
             notification = self.window_element.find_element(
                 By.CSS_SELECTOR, '#notification-popup popupnotification')
 
             notification_id = notification.get_attribute('id')
             return notifications_map.get(notification_id, BaseNotification)(
-                lambda: self.marionette, self, notification)
+                self.marionette, self, notification)
 
         except NoSuchElementException:
             return None  # no notification is displayed
 
     def wait_for_notification(self, notification_class=BaseNotification,
                               timeout=5):
         """Waits for the specified notification to be displayed.
 
@@ -137,17 +138,17 @@ class BrowserWindow(BaseWindow):
         """Provides access to the tab bar.
 
         See the :class:`~ui.browser.tabbar.TabBar` reference.
         """
         self.switch_to()
 
         if not self._tabbar:
             tabbrowser = self.window_element.find_element(By.ID, 'tabbrowser-tabs')
-            self._tabbar = TabBar(lambda: self.marionette, self, tabbrowser)
+            self._tabbar = TabBar(self.marionette, self, tabbrowser)
 
         return self._tabbar
 
     def close(self, trigger='menu', force=False):
         """Closes the current browser window by using the specified trigger.
 
         :param trigger: Optional, method to close the current browser window. This can
          be a string with one of `menu` or `shortcut`, or a callback which gets triggered
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/deck.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/deck.py
@@ -20,17 +20,17 @@ class Deck(UIBaseLib):
         mapping = {'feedPanel': FeedPanel,
                    'generalPanel': GeneralPanel,
                    'mediaPanel': MediaPanel,
                    'permPanel': PermissionsPanel,
                    'securityPanel': SecurityPanel
                    }
 
         panel = self.element.find_element(By.ID, panel_id)
-        return mapping.get(panel_id, Panel)(lambda: self.marionette, self.window, panel)
+        return mapping.get(panel_id, Panel)(self.marionette, self.window, panel)
 
     # Properties for visual elements of the deck #
 
     @property
     def feed(self):
         """The :class:`FeedPanel` instance for the feed panel.
 
         :returns: :class:`FeedPanel` instance.
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/window.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/pageinfo/window.py
@@ -28,17 +28,17 @@ class PageInfoWindow(BaseWindow):
 
     @property
     def deck(self):
         """The :class:`Deck` instance which represents the deck.
 
         :returns: Reference to the deck.
         """
         deck = self.window_element.find_element(By.ID, 'mainDeck')
-        return Deck(lambda: self.marionette, self, deck)
+        return Deck(self.marionette, self, deck)
 
     def close(self, trigger='shortcut', force=False):
         """Closes the current page info window by using the specified trigger.
 
         :param trigger: Optional, method to close the current window. This can
          be a string with one of `menu` (OS X only) or `shortcut`, or a callback
          which gets triggered with the current :class:`PageInfoWindow` as parameter.
          Defaults to `shortcut`.
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/dialog.py
@@ -29,17 +29,17 @@ class UpdateWizardDialog(BaseWindow):
     @property
     def wizard(self):
         """The :class:`Wizard` instance which represents the wizard.
 
         :returns: Reference to the wizard.
         """
         # The deck is also the root element
         wizard = self.marionette.find_element(By.ID, 'updates')
-        return Wizard(lambda: self.marionette, self, wizard)
+        return Wizard(self.marionette, self, wizard)
 
     def select_next_page(self):
         """Clicks on "Next" button, and waits for the next page to show up."""
         current_panel = self.wizard.selected_panel
 
         self.wizard.next_button.click()
         Wait(self.marionette).until(
             lambda _: self.wizard.selected_panel != current_panel,
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/update_wizard/wizard.py
@@ -37,17 +37,17 @@ class Wizard(UIBaseLib):
                    'updatesfoundbasic': UpdatesFoundBasicPanel,
 
                    # TODO: Remove once we no longer support version Firefox 45.0ESR
                    'incompatibleCheck': IncompatibleCheckPanel,
                    'incompatibleList': IncompatibleListPanel,
                    }
 
         panel = self.element.find_element(By.ID, panel_id)
-        return mapping.get(panel_id, Panel)(lambda: self.marionette, self.window, panel)
+        return mapping.get(panel_id, Panel)(self.marionette, self.window, panel)
 
     # Properties for visual buttons of the wizard #
 
     @property
     def _buttons(self):
         return self.element.find_element(By.ANON_ATTRIBUTE, {'anonid': 'Buttons'})
 
     @property
--- a/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py
+++ b/testing/puppeteer/firefox/firefox_puppeteer/ui/windows.py
@@ -108,19 +108,19 @@ class Windows(BaseLib):
                     self.switch_to(handle)
                 window_type = self.marionette.get_window_type()
             finally:
                 # Ensure to switch back to the original window
                 if handle != current_handle:
                     self.switch_to(current_handle)
 
             if window_type in self.windows_map:
-                window = self.windows_map[window_type](lambda: self.marionette, handle)
+                window = self.windows_map[window_type](self.marionette, handle)
             else:
-                window = BaseWindow(lambda: self.marionette, handle)
+                window = BaseWindow(self.marionette, handle)
 
             if expected_class is not None and type(window) is not expected_class:
                 raise errors.UnexpectedWindowTypeError('Expected window "%s" but got "%s"' %
                                                        (expected_class, type(window)))
 
             # Before continuing ensure the chrome window has been completed loading
             Wait(self.marionette).until(
                 lambda _: self.loaded(handle),
@@ -208,21 +208,21 @@ class Windows(BaseLib):
 
 class BaseWindow(BaseLib):
     """Base class for any kind of chrome window."""
 
     # l10n class attributes will be set by each window class individually
     dtds = []
     properties = []
 
-    def __init__(self, marionette_getter, window_handle):
-        BaseLib.__init__(self, marionette_getter)
-        self._l10n = L10n(self.get_marionette)
-        self._prefs = Preferences(self.get_marionette)
-        self._windows = Windows(self.get_marionette)
+    def __init__(self, marionette, window_handle):
+        BaseLib.__init__(self, marionette)
+        self._l10n = L10n(self.marionette)
+        self._prefs = Preferences(self.marionette)
+        self._windows = Windows(self.marionette)
 
         if window_handle not in self.marionette.chrome_window_handles:
             raise errors.UnknownWindowError('Window with handle "%s" does not exist' %
                                             window_handle)
         self._handle = window_handle
 
     def __eq__(self, other):
         return self.handle == other.handle