summaryrefslogtreecommitdiffstats
path: root/netwerk/test/unit/test_content_sniffer.js
blob: 6299c90ae572362e55c9926fda1f146be2b9d4cb (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
// This file tests nsIContentSniffer, introduced in bug 324985

"use strict";

const { HttpServer } = ChromeUtils.import("resource://testing-common/httpd.js");

const unknownType = "application/x-unknown-content-type";
const sniffedType = "application/x-sniffed";

const snifferCID = Components.ID("{4c93d2db-8a56-48d7-b261-9cf2a8d998eb}");
const snifferContract = "@mozilla.org/network/unittest/contentsniffer;1";
const categoryName = "net-content-sniffers";

var sniffing_enabled = true;

var isNosniff = false;

/**
 * This object is both a factory and an nsIContentSniffer implementation (so, it
 * is de-facto a service)
 */
var sniffer = {
  QueryInterface: ChromeUtils.generateQI(["nsIFactory", "nsIContentSniffer"]),
  createInstance: function sniffer_ci(iid) {
    return this.QueryInterface(iid);
  },

  getMIMETypeFromContent(request, data, length) {
    return sniffedType;
  },
};

var listener = {
  onStartRequest: function test_onStartR(request) {
    try {
      var chan = request.QueryInterface(Ci.nsIChannel);
      if (chan.contentType == unknownType) {
        do_throw("Type should not be unknown!");
      }
      if (isNosniff) {
        if (chan.contentType == sniffedType) {
          do_throw("Sniffer called for X-Content-Type-Options:nosniff");
        }
      } else if (
        sniffing_enabled &&
        this._iteration > 2 &&
        chan.contentType != sniffedType
      ) {
        do_throw(
          "Expecting <" +
            sniffedType +
            "> but got <" +
            chan.contentType +
            "> for " +
            chan.URI.spec
        );
      } else if (!sniffing_enabled && chan.contentType == sniffedType) {
        do_throw(
          "Sniffing not enabled but sniffer called for " + chan.URI.spec
        );
      }
    } catch (e) {
      do_throw("Unexpected exception: " + e);
    }

    throw Components.Exception("", Cr.NS_ERROR_ABORT);
  },

  onDataAvailable: function test_ODA() {
    throw Components.Exception("", Cr.NS_ERROR_UNEXPECTED);
  },

  onStopRequest: function test_onStopR(request, status) {
    run_test_iteration(this._iteration);
    do_test_finished();
  },

  _iteration: 1,
};

function makeChan(url) {
  var chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
  if (sniffing_enabled) {
    chan.loadFlags |= Ci.nsIChannel.LOAD_CALL_CONTENT_SNIFFERS;
  }

  return chan;
}

var httpserv = null;
var urls = null;

function run_test() {
  httpserv = new HttpServer();
  httpserv.registerPathHandler("/nosniff", nosniffHandler);
  httpserv.start(-1);

  urls = [
    // NOTE: First URL here runs without our content sniffer
    "data:" + unknownType + ", Some text",
    "data:" + unknownType + ", Text", // Make sure sniffing works even if we
    // used the unknown content sniffer too
    "data:text/plain, Some more text",
    "http://localhost:" + httpserv.identity.primaryPort,
    "http://localhost:" + httpserv.identity.primaryPort + "/nosniff",
  ];

  Components.manager.nsIComponentRegistrar.registerFactory(
    snifferCID,
    "Unit test content sniffer",
    snifferContract,
    sniffer
  );

  run_test_iteration(1);
}

function nosniffHandler(request, response) {
  response.setHeader("X-Content-Type-Options", "nosniff");
}

function run_test_iteration(index) {
  if (index > urls.length) {
    if (sniffing_enabled) {
      sniffing_enabled = false;
      index = listener._iteration = 1;
    } else {
      do_test_pending();
      httpserv.stop(do_test_finished);
      return; // we're done
    }
  }

  if (sniffing_enabled && index == 2) {
    // Register our sniffer only here
    // This also makes sure that dynamic registration is working
    var catMan = Services.catMan;
    catMan.nsICategoryManager.addCategoryEntry(
      categoryName,
      "unit test",
      snifferContract,
      false,
      true
    );
  } else if (sniffing_enabled && index == 5) {
    isNosniff = true;
  }

  var chan = makeChan(urls[index - 1]);

  listener._iteration++;
  chan.asyncOpen(listener);

  do_test_pending();
}