/* 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/. */

// This file tests the normal operation of setAndFetchFaviconForPage.
function test() {
  // Initialization
  waitForExplicitFinish();
  let windowsToClose = [];
  let testURI = "https://www.mozilla.org/en-US/";
  let favIconLocation =
    "http://example.org/tests/toolkit/components/places/tests/browser/favicon-normal32.png";
  let favIconURI = NetUtil.newURI(favIconLocation);
  let favIconMimeType= "image/png";
  let pageURI;
  let favIconData;

  function testOnWindow(aOptions, aCallback) {
    whenNewWindowLoaded(aOptions, function(aWin) {
      windowsToClose.push(aWin);
      executeSoon(function() aCallback(aWin));
    });
  };

  // This function is called after calling finish() on the test.
  registerCleanupFunction(function() {
    windowsToClose.forEach(function(aWin) {
      aWin.close();
    });
  });

  function getIconFile(aCallback) {
    NetUtil.asyncFetch(favIconLocation, function(inputStream, status) {
      if (!Components.isSuccessCode(status)) {
        ok(false, "Could not get the icon file");
        // Handle error.
        return;
      }

      // Check the returned size versus the expected size.
      let size = inputStream.available();
      favIconData = NetUtil.readInputStreamToString(inputStream, size);
      is(size, favIconData.length, "Check correct icon size");
      // Check that the favicon loaded correctly before starting the actual tests.
      is(favIconData.length, 344, "Check correct icon length (344)");

      if (aCallback) {
        aCallback();
      } else {
        finish();
      }
    });
  }

  function testNormal(aWindow, aCallback) {
    pageURI = NetUtil.newURI("http://example.com/normal");
    waitForFaviconChanged(pageURI, favIconURI, aWindow,
      function testNormalCallback() {
        checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
          aCallback);
      }
    );

    addVisits({uri: pageURI, transition: TRANSITION_TYPED}, aWindow,
      function () {
        aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI,
          favIconURI, true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);
      }
    );
  }

  function testAboutURIBookmarked(aWindow, aCallback) {
    pageURI = NetUtil.newURI("about:testAboutURI_bookmarked");
    waitForFaviconChanged(pageURI, favIconURI, aWindow,
      function testAboutURIBookmarkedCallback() {
        checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
          aCallback);
      }
    );

    aWindow.PlacesUtils.bookmarks.insertBookmark(
      aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
      aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
    aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
      true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);
  }

  function testPrivateBrowsingBookmarked(aWindow, aCallback) {
    pageURI = NetUtil.newURI("http://example.com/privateBrowsing_bookmarked");
    waitForFaviconChanged(pageURI, favIconURI, aWindow,
      function testPrivateBrowsingBookmarkedCallback() {
        checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
          aCallback);
      }
    );

    aWindow.PlacesUtils.bookmarks.insertBookmark(
      aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
      aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
    aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
      true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_PRIVATE);
  }

  function testDisabledHistoryBookmarked(aWindow, aCallback) {
    pageURI = NetUtil.newURI("http://example.com/disabledHistory_bookmarked");
    waitForFaviconChanged(pageURI, favIconURI, aWindow,
      function testDisabledHistoryBookmarkedCallback() {
        checkFaviconDataForPage(pageURI, favIconMimeType, favIconData, aWindow,
          aCallback);
      }
    );

    // Disable history while changing the favicon.
    aWindow.Services.prefs.setBoolPref("places.history.enabled", false);

    aWindow.PlacesUtils.bookmarks.insertBookmark(
      aWindow.PlacesUtils.unfiledBookmarksFolderId, pageURI,
      aWindow.PlacesUtils.bookmarks.DEFAULT_INDEX, pageURI.spec);
    aWindow.PlacesUtils.favicons.setAndFetchFaviconForPage(pageURI, favIconURI,
      true, aWindow.PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE);

    // The setAndFetchFaviconForPage function calls CanAddURI synchronously, thus
    // we can set the preference back to true immediately.  We don't clear the
    // preference because not all products enable Places by default.
    aWindow.Services.prefs.setBoolPref("places.history.enabled", true);
  }

  getIconFile(function () {
    testOnWindow({}, function(aWin) {
      testNormal(aWin, function () {
        testOnWindow({}, function(aWin) {
          testAboutURIBookmarked(aWin, function () {
            testOnWindow({private: true}, function(aWin) {
              testPrivateBrowsingBookmarked(aWin, function () {
                testOnWindow({}, function(aWin) {
                  testDisabledHistoryBookmarked(aWin, finish);
                });
              });
            });
          });
        });
      });
    });
  });
}
