{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/comments/23766378","id":23766378,"diff_hunk":"@@ -0,0 +1,486 @@\n+# This Source Code Form is subject to the terms of the Mozilla Public\n+# License, v. 2.0. If a copy of the MPL was not distributed with this file,\n+# You can obtain one at http://mozilla.org/MPL/2.0/.\n+\n+from time import sleep\n+\n+from marionette import By, Wait\n+from marionette.errors import NoSuchWindowException\n+from marionette.keys import Keys\n+\n+import firefox_puppeteer.errors as errors\n+\n+from ..api.l10n import L10n\n+from ..base import BaseLib\n+from ..decorators import use_class_as_property\n+\n+\n+class Windows(BaseLib):\n+\n+    @property\n+    def all(self):\n+        \"\"\"Retrieves a list of all open chrome windows.\n+\n+        :returns: List of :class:`BaseWindow`'s corresponding to the\n+                  windows in `marionette.chrome_window_handles`.\n+        \"\"\"\n+        return [self.create_window_instance(handle) for handle in\n+                self.marionette.chrome_window_handles]\n+\n+    @property\n+    def current(self):\n+        \"\"\"Retrieves the currently selected chrome window.\n+\n+        :returns: The :class:`BaseWindow` for the currently active window.\n+        \"\"\"\n+        return self.create_window_instance(self.marionette.current_chrome_window_handle)\n+\n+    @property\n+    def focused_chrome_window_handle(self):\n+        \"\"\"Returns the currently focused chrome window handle\n+\n+        :returns: The `window handle` of the focused chrome window.\n+        \"\"\"\n+        with self.marionette.using_context('chrome'):\n+            return self.marionette.execute_script(\"\"\"\n+              Cu.import(\"resource://gre/modules/Services.jsm\");\n+              var win = Services.wm.getMostRecentWindow(\"\");\n+              return win.QueryInterface(Ci.nsIInterfaceRequestor)\n+                        .getInterface(Ci.nsIDOMWindowUtils)\n+                        .outerWindowID.toString();\n+            \"\"\")\n+\n+    def close(self, handle):\n+        \"\"\"Closes the chrome window with the given handle.\n+\n+        :param handle: The handle of the chrome window\n+        \"\"\"\n+        self.switch_to(handle)\n+\n+        # TODO: Maybe needs to wait as handled via an observer\n+        return self.marionette.close_chrome_window()\n+\n+    def close_all(self, exceptions=None):\n+        \"\"\"Closes all open chrome windows.\n+\n+        There is an optional `exceptions` list, which can be used to exclude\n+        specific chrome windows from being closed.\n+\n+        :param exceptions: Optional, list or a single entry of handles or\n+         :class:`BaseWindow` instances not to close\n+        \"\"\"\n+        handles_to_keep = exceptions or []\n+        if not isinstance(handles_to_keep, list):\n+            handles_to_keep = [handles_to_keep]\n+\n+        # Ensure we only have handles and no BaseWindow entries\n+        handles_to_keep = [entry.handle if isinstance(entry, BaseWindow) else entry\n+                           for entry in handles_to_keep]\n+\n+        # Find handles to close and close them all\n+        handles_to_close = set(self.marionette.chrome_window_handles) - set(handles_to_keep)\n+        for handle in handles_to_close:\n+            self.close(handle)\n+\n+    def create_window_instance(self, handle, expected_class=None):\n+        \"\"\"Creates a :class:`BaseWindow` instance for the given chrome window\n+\n+        :param handle: The handle of the chrome window\n+        :param expected_class: Optional, check for the correct window class\n+        \"\"\"\n+        current_handle = self.marionette.current_chrome_window_handle\n+        window = None\n+\n+        try:\n+            # Retrieve window type to determine the type of chrome window\n+            if handle != self.marionette.current_chrome_window_handle:\n+                self.switch_to(handle)\n+            window_type = self.marionette.get_window_type()\n+        finally:\n+            # Ensure to switch back to the original window\n+            if handle != current_handle:\n+                self.marionette.switch_to_window(current_handle)\n+\n+        if window_type == 'navigator:browser':\n+            window = BrowserWindow(lambda: self.marionette, handle)\n+        else:\n+            raise errors.UnknownWindowError('Unknown window type \"%s\" for handle: \"%s\"' %\n+                                            (window_type, handle))\n+\n+        if expected_class is not None and type(window) is not expected_class:\n+            raise errors.UnexpectedWindowTypeError('Expected window \"%s\" but got \"%s\"' %\n+                                                   (expected_class, type(window)))\n+\n+        return window\n+\n+    def focus(self, handle):\n+        \"\"\"Focuses the chrome window with the given handle.\n+\n+        :param handle: The handle of the chrome window\n+        \"\"\"\n+        self.switch_to(handle)\n+\n+        with self.marionette.using_context('chrome'):\n+            self.marionette.execute_script(\"\"\" window.focus(); \"\"\")\n+\n+        wait = Wait(self.marionette, timeout=5)\n+        wait.until(lambda m: handle == self.focused_chrome_window_handle)\n+\n+    def switch_to(self, target):\n+        \"\"\"Switches context to the specified chrome window.\n+\n+        :param target: The window to switch to. `target` can be a `handle` or a\n+                       callback that returns True in the context of the desired\n+                       window.\n+\n+        :returns: The old `window_handle`. This makes it easy to switch back\n+                  to the original window later.\n+        \"\"\"\n+        target_handle = None\n+\n+        if target in self.marionette.chrome_window_handles:\n+            target_handle = target\n+        elif callable(target):\n+            current_handle = self.marionette.current_chrome_window_handle\n+\n+            # switches context if callback for a chrome window returns `True`.\n+            for handle in self.marionette.chrome_window_handles:\n+                self.marionette.switch_to_window(handle)\n+                window = self.create_window_instance(handle)\n+                if target(window):\n+                    target_handle = handle\n+                    break\n+\n+            # if no handle has been found switch back to original window\n+            if not target_handle:\n+                self.marionette.switch_to_window(current_handle)\n+\n+        if target_handle is None:\n+            raise NoSuchWindowException(\"No window found for '{}'\"\n+                                        .format(target))","path":"firefox_puppeteer/ui/windows.py","position":160,"original_position":160,"commit_id":"b3a4d92e095d7a9e6f0b08294ddc7810747dcf76","original_commit_id":"b3a4d92e095d7a9e6f0b08294ddc7810747dcf76","user":{"login":"whimboo","id":129603,"avatar_url":"https://avatars.githubusercontent.com/u/129603?v=3","gravatar_id":"","url":"https://api.github.com/users/whimboo","html_url":"https://github.com/whimboo","followers_url":"https://api.github.com/users/whimboo/followers","following_url":"https://api.github.com/users/whimboo/following{/other_user}","gists_url":"https://api.github.com/users/whimboo/gists{/gist_id}","starred_url":"https://api.github.com/users/whimboo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whimboo/subscriptions","organizations_url":"https://api.github.com/users/whimboo/orgs","repos_url":"https://api.github.com/users/whimboo/repos","events_url":"https://api.github.com/users/whimboo/events{/privacy}","received_events_url":"https://api.github.com/users/whimboo/received_events","type":"User","site_admin":false},"body":"No we cannot because we also have to check if the given handle is correct. If I would move this code into the callback block, we would try to operate on an invalid handle. Also I do not want to move out the inner if block because thats only related to the callback block. For a normal handle we do not have to switch before.","created_at":"2015-01-29T13:19:53Z","updated_at":"2015-01-29T13:19:53Z","html_url":"https://github.com/mozilla/firefox-ui-tests/pull/50#discussion_r23766378","pull_request_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50","_links":{"self":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/comments/23766378"},"html":{"href":"https://github.com/mozilla/firefox-ui-tests/pull/50#discussion_r23766378"},"pull_request":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50","id":27943614,"html_url":"https://github.com/mozilla/firefox-ui-tests/pull/50","diff_url":"https://github.com/mozilla/firefox-ui-tests/pull/50.diff","patch_url":"https://github.com/mozilla/firefox-ui-tests/pull/50.patch","issue_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/50","number":50,"state":"open","locked":false,"title":"Bug 1123401 - Implement handling of chrome windows","user":{"login":"whimboo","id":129603,"avatar_url":"https://avatars.githubusercontent.com/u/129603?v=3","gravatar_id":"","url":"https://api.github.com/users/whimboo","html_url":"https://github.com/whimboo","followers_url":"https://api.github.com/users/whimboo/followers","following_url":"https://api.github.com/users/whimboo/following{/other_user}","gists_url":"https://api.github.com/users/whimboo/gists{/gist_id}","starred_url":"https://api.github.com/users/whimboo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whimboo/subscriptions","organizations_url":"https://api.github.com/users/whimboo/orgs","repos_url":"https://api.github.com/users/whimboo/repos","events_url":"https://api.github.com/users/whimboo/events{/privacy}","received_events_url":"https://api.github.com/users/whimboo/received_events","type":"User","site_admin":false},"body":"Just for a sneak peak. This PR is not ready yet and needs some more methods and cleanups. But if you have time lets give me feedback.","created_at":"2015-01-23T18:15:52Z","updated_at":"2015-01-29T13:19:53Z","closed_at":null,"merged_at":null,"merge_commit_sha":"655ed7f0aef24314eb46d7af0704d500b3342677","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50/commits","review_comments_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50/comments","review_comment_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/comments/{number}","comments_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/50/comments","statuses_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/statuses/b3a4d92e095d7a9e6f0b08294ddc7810747dcf76","head":{"label":"whimboo:windows","ref":"windows","sha":"b3a4d92e095d7a9e6f0b08294ddc7810747dcf76","user":{"login":"whimboo","id":129603,"avatar_url":"https://avatars.githubusercontent.com/u/129603?v=3","gravatar_id":"","url":"https://api.github.com/users/whimboo","html_url":"https://github.com/whimboo","followers_url":"https://api.github.com/users/whimboo/followers","following_url":"https://api.github.com/users/whimboo/following{/other_user}","gists_url":"https://api.github.com/users/whimboo/gists{/gist_id}","starred_url":"https://api.github.com/users/whimboo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whimboo/subscriptions","organizations_url":"https://api.github.com/users/whimboo/orgs","repos_url":"https://api.github.com/users/whimboo/repos","events_url":"https://api.github.com/users/whimboo/events{/privacy}","received_events_url":"https://api.github.com/users/whimboo/received_events","type":"User","site_admin":false},"repo":{"id":27267720,"name":"firefox-ui-tests","full_name":"whimboo/firefox-ui-tests","owner":{"login":"whimboo","id":129603,"avatar_url":"https://avatars.githubusercontent.com/u/129603?v=3","gravatar_id":"","url":"https://api.github.com/users/whimboo","html_url":"https://github.com/whimboo","followers_url":"https://api.github.com/users/whimboo/followers","following_url":"https://api.github.com/users/whimboo/following{/other_user}","gists_url":"https://api.github.com/users/whimboo/gists{/gist_id}","starred_url":"https://api.github.com/users/whimboo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/whimboo/subscriptions","organizations_url":"https://api.github.com/users/whimboo/orgs","repos_url":"https://api.github.com/users/whimboo/repos","events_url":"https://api.github.com/users/whimboo/events{/privacy}","received_events_url":"https://api.github.com/users/whimboo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/whimboo/firefox-ui-tests","description":"","fork":true,"url":"https://api.github.com/repos/whimboo/firefox-ui-tests","forks_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/forks","keys_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/keys{/key_id}","collaborators_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/teams","hooks_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/hooks","issue_events_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/issues/events{/number}","events_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/events","assignees_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/assignees{/user}","branches_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/branches{/branch}","tags_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/tags","blobs_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/git/refs{/sha}","trees_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/git/trees{/sha}","statuses_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/statuses/{sha}","languages_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/languages","stargazers_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/stargazers","contributors_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/contributors","subscribers_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/subscribers","subscription_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/subscription","commits_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/commits{/sha}","git_commits_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/git/commits{/sha}","comments_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/comments{/number}","issue_comment_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/issues/comments/{number}","contents_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/contents/{+path}","compare_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/compare/{base}...{head}","merges_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/merges","archive_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/downloads","issues_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/issues{/number}","pulls_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/pulls{/number}","milestones_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/milestones{/number}","notifications_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/labels{/name}","releases_url":"https://api.github.com/repos/whimboo/firefox-ui-tests/releases{/id}","created_at":"2014-11-28T13:17:46Z","updated_at":"2015-01-16T13:26:09Z","pushed_at":"2015-01-28T20:16:25Z","git_url":"git://github.com/whimboo/firefox-ui-tests.git","ssh_url":"git@github.com:whimboo/firefox-ui-tests.git","clone_url":"https://github.com/whimboo/firefox-ui-tests.git","svn_url":"https://github.com/whimboo/firefox-ui-tests","homepage":null,"size":523,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla:master","ref":"master","sha":"7c29bb51f543912cb9e3e13c78d3272be8920699","user":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"repo":{"id":25004372,"name":"firefox-ui-tests","full_name":"mozilla/firefox-ui-tests","owner":{"login":"mozilla","id":131524,"avatar_url":"https://avatars.githubusercontent.com/u/131524?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla","html_url":"https://github.com/mozilla","followers_url":"https://api.github.com/users/mozilla/followers","following_url":"https://api.github.com/users/mozilla/following{/other_user}","gists_url":"https://api.github.com/users/mozilla/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla/subscriptions","organizations_url":"https://api.github.com/users/mozilla/orgs","repos_url":"https://api.github.com/users/mozilla/repos","events_url":"https://api.github.com/users/mozilla/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla/firefox-ui-tests","description":"","fork":false,"url":"https://api.github.com/repos/mozilla/firefox-ui-tests","forks_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/forks","keys_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/teams","hooks_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/hooks","issue_events_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/events","assignees_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/tags","blobs_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/languages","stargazers_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/stargazers","contributors_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/contributors","subscribers_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/subscribers","subscription_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/subscription","commits_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/comments/{number}","contents_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/merges","archive_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/downloads","issues_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/labels{/name}","releases_url":"https://api.github.com/repos/mozilla/firefox-ui-tests/releases{/id}","created_at":"2014-10-09T19:09:05Z","updated_at":"2015-01-26T10:10:15Z","pushed_at":"2015-01-28T20:18:46Z","git_url":"git://github.com/mozilla/firefox-ui-tests.git","ssh_url":"git@github.com:mozilla/firefox-ui-tests.git","clone_url":"https://github.com/mozilla/firefox-ui-tests.git","svn_url":"https://github.com/mozilla/firefox-ui-tests","homepage":null,"size":866,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":3,"forks":4,"open_issues":3,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50"},"html":{"href":"https://github.com/mozilla/firefox-ui-tests/pull/50"},"issue":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/50"},"comments":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/issues/50/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/pulls/50/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla/firefox-ui-tests/statuses/b3a4d92e095d7a9e6f0b08294ddc7810747dcf76"}}}}