summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/tests/favicons/head_favicons.js
blob: 73dd2a61ed60afdf2e160098d768ff1847c97ba3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* 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 common head.
{
  /* import-globals-from ../head_common.js */
  let commonFile = do_get_file("../head_common.js", false);
  let uri = Services.io.newFileURI(commonFile);
  Services.scriptloader.loadSubScript(uri.spec, this);
}

// Put any other stuff relative to this test folder below.

const systemPrincipal = Services.scriptSecurityManager.getSystemPrincipal();

// Used in createFavicon().
let uniqueFaviconId = 0;

/**
 * Checks that the favicon for the given page matches the provided data.
 *
 * @param aPageURI
 *        nsIURI object for the page to check.
 * @param aExpectedMimeType
 *        Expected MIME type of the icon, for example "image/png".
 * @param aExpectedData
 *        Expected icon data, expressed as an array of byte values.
 *        If set null, skip the test for the favicon data.
 * @param aCallback
 *        This function is called after the check finished.
 */
function checkFaviconDataForPage(
  aPageURI,
  aExpectedMimeType,
  aExpectedData,
  aCallback
) {
  PlacesUtils.favicons.getFaviconDataForPage(
    aPageURI,
    async function (aURI, aDataLen, aData, aMimeType) {
      Assert.equal(aExpectedMimeType, aMimeType);
      if (aExpectedData) {
        Assert.ok(compareArrays(aExpectedData, aData));
      }
      await check_guid_for_uri(aPageURI);
      aCallback();
    }
  );
}

/**
 * Checks that the given page has no associated favicon.
 *
 * @param aPageURI
 *        nsIURI object for the page to check.
 * @param aCallback
 *        This function is called after the check finished.
 */
function checkFaviconMissingForPage(aPageURI, aCallback) {
  PlacesUtils.favicons.getFaviconURLForPage(aPageURI, function (aURI) {
    Assert.ok(aURI === null);
    aCallback();
  });
}

function promiseFaviconMissingForPage(aPageURI) {
  return new Promise(resolve => checkFaviconMissingForPage(aPageURI, resolve));
}

function promiseFaviconChanged(aExpectedPageURI, aExpectedFaviconURI) {
  return new Promise(resolve => {
    PlacesTestUtils.waitForNotification("favicon-changed", async events => {
      for (let e of events) {
        if (e.url == aExpectedPageURI.spec) {
          Assert.equal(e.faviconUrl, aExpectedFaviconURI.spec);
          await check_guid_for_uri(aExpectedPageURI, e.pageGuid);
          resolve();
        }
      }
    });
  });
}

/**
 * Create favicon file to temp directory.
 *
 * @param {string} aFileName
 *        File name that will be created in temp directory.
 * @returns {object}
 *          {
 *            file: nsIFile,
 *            uri: nsIURI,
 *            data: byte Array,
 *            mimetype: String,
 *          }
 */
async function createFavicon(aFileName) {
  // Copy the favicon file we have to the specified file in temp directory.
  let originalFaviconFile = do_get_file("favicon-normal16.png");
  let tempDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
  let faviconFile = tempDir.clone();
  faviconFile.append(aFileName);
  await IOUtils.copy(originalFaviconFile.path, faviconFile.path);

  // Append some data that sniffers/encoders will ignore that will distinguish
  // the different favicons we'll create.
  let stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
    Ci.nsIFileOutputStream
  );
  const WRONLY_PERMISSION = 0o600;
  stream.init(
    faviconFile,
    FileUtils.MODE_WRONLY | FileUtils.MODE_APPEND,
    WRONLY_PERMISSION,
    0
  );
  uniqueFaviconId++;
  let uniqueStr = "uid:" + uniqueFaviconId;
  stream.write(uniqueStr, uniqueStr.length);
  stream.close();

  Assert.equal(faviconFile.leafName.substr(0, aFileName.length), aFileName);

  return {
    file: faviconFile,
    uri: uri(faviconFile),
    data: readFileData(faviconFile),
    mimeType: "image/png",
  };
}

/**
 * Create nsIURI for given favicon object.
 *
 * @param {object} aFavicon
 *        Favicon object created by createFavicon().
 * @returns {nsIURI}
 */
async function createDataURLForFavicon(aFavicon) {
  let dataURL = await toDataURL(aFavicon.data, aFavicon.mimeType);
  return uri(dataURL);
}

/**
 * Create data URL string from given byte array and type.
 *
 * @param {Array} data
 *        Byte array.
 * @param {string} type
 *        The type of this data.
 * @returns {string}
 */
function toDataURL(data, type) {
  let blob = new Blob([new Uint8Array(data)], { type });
  return new Promise((resolve, reject) => {
    let reader = new FileReader();
    reader.addEventListener("load", () => resolve(reader.result));
    reader.addEventListener("error", reject);
    reader.readAsDataURL(blob);
  });
}