<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>Page Visibility API Operation While Changing Tabs</title>
        <meta name="flags" content="interact" />
        <script type="text/javascript" src="/resources/testharness.js"></script>
        <script type="text/javascript" src="resources/pagevistestharness.js"></script>

    </head>
    <body>
        <h1>Description</h1>
        <p>This test validates that the page properly becomes hidden and visible due to switching tabs.</p>

        <h1>Manual Test Steps:</h1>
        <p>
            <ol>
                <li> Ensure this page is the foreground and click the "Start Test"</li>
                <li> Switch to another tab</li>
                <li> Return to the current tab containing this test page</li>
            </ol>
            Note: This test will automatically timeout and fail if not completed within 60 seconds.
        </p>

        <button onclick="start_test();">Start Test</button>

        <div id="log"></div>

        <br />
        IFrame with default style:
        <br />
        <iframe id="childDocShown" src="resources/blank_page_green.html">
            iframes unsupported
        </iframe>
        <hr />
        IFrame with "display:none" style:
        <br />
        <iframe id="childDocHidden" src="resources/blank_page_green.html" style="display:none">
            iframes unsupported
        </iframe>

        <script type="text/javascript" >
            var child_doc_shown = null;
            var child_doc_hidden = null;
            var transition_mode;
            var manual_test = null;

            var expected_notification_count = 2;
            var notification_count = new Array();
            var page_docs = new Array();
            var notification_handlers = new Array();
            var two_notifications = false;

            var PAGE_HIDDEN_VAL = "hidden";
            var PAGE_VISIBLE_VAL = "visible";

            setup({ explicit_done: true });

            function test_transition_init()
            {
                child_doc_shown = document.getElementById("childDocShown").contentDocument;
                child_doc_hidden = document.getElementById("childDocHidden").contentDocument;

                // fill in data for page documents
                page_docs.push([document, "document"]);
                page_docs.push([child_doc_shown, "document.getElementById(\"childDocShown\").contentDocument"]);
                page_docs.push([child_doc_hidden, "document.getElementById(\"childDocHidden\").contentDocument"]);

                notification_handlers[0] = function(){ VerifyNotification(0); };
                notification_handlers[1] = function(){ VerifyNotification(1); };
                notification_handlers[2] = function(){ VerifyNotification(2); };

                for (var i in page_docs)
                {
                    notification_count[i] = 0;
                    page_docs[i][0].addEventListener("visibilitychange", notification_handlers[i]);
                }

                test_true(!document.hidden, "Page is visible on load.");
                test_true((!child_doc_shown.hidden) && (!child_doc_hidden.hidden),
                          "All IFrame child documents are visible on load.");

                document.addEventListener("visibilitychange", notification_handlers[0]);
                document.addEventListener("visibilitychange", VerifyTwoNotifications);

                manual_test = AddManual("Browser tab switch has occurred.");
            }

            function VerifyNotification(doc_index)
            {
                doc = page_docs[doc_index][0];
                docName = page_docs[doc_index][1];

                notification_count[doc_index]++;
                switch (notification_count[doc_index])
                {
                    case 1:
                        // First step, check page visibility after tab deselection / minimization.
                        // hidden should change to true; visibilityState should change to "hidden"
                        test_true(doc.hidden, docName + ".hidden == true (after tab switch)");
                        test_true(doc.visibilityState == PAGE_HIDDEN_VAL,
                                  docName + ".visibilityState == \"hidden\" (after tab switch)");

                        break;

                    case 2:
                        //Second step, check page visibility after tab reselection / maximization / restoration.
                        // hidden should change to false; visibilityState should change to "visible"
                        test_true(!doc.hidden,
                                  docName + ".hidden == false (after return to original tab)");
                        test_true(doc.visibilityState == PAGE_VISIBLE_VAL,
                                  docName + ".visibilityState == \"visible\" (after return to original tab)");

                        // perform tests specific to the main document
                        if (doc == document)
                        {
                            //Verify that a second registration to a different callback also occurred
                            test_true(two_notifications, "Two registrations (different callbacks) occurred.");

                            //Verify that a second registration to the same callback did not occur
                            test_equals(notification_count[doc_index],
                                        expected_notification_count,
                                        "Two registrations (same callback) did not occur.");

                            // pass the manual item associated with these tests
                            AddManualResult(manual_test, true);

                            document.removeEventListener("visibilitychange", VerifyTwoNotifications);

                            // schedule the rollup
                            setTimeout(VerifyAllNotifications, 200);
                        }

                        //Remove all event listeners and verify that the event does not fire
                        doc.removeEventListener("visibilitychange", notification_handlers[doc_index]);
                        break;
                    case 3:
                        //This step should not have occurred since the event handlers were cleared
                        test_true(false, "Event did not fire when event listener is removed.");

                        //On final step, schedule the rollup
                        setTimeout(done, 2000);
                        break;

                    default:
                        break;
                }
            }

            function VerifyAllNotifications()
            {
                //On final step, schedule the rollup
                setTimeout(done, 1000);
            }

            function VerifyTwoNotifications()
            {
                //This is a duplicate registration on visibilitychange and
                //should never get fired.  Check that duplicate_notification
                //is false to verify that this never occurred.
                two_notifications = true;
            }

            // Manual Test helper functions
            function AddManual(test)
            {
                // add asynchronous test for manual tests
                return async_test(test);
            }

            function AddManualResult(oManualTest, passState)
            {
                // add assertion to manual test for the pass state
                oManualTest.step(function() {assert_true(passState)});

                // end manual test
                oManualTest.done();
            }

            function start_test()
            {
                test_transition_init();
            }
        </script>
    </body>
</html>
