test_private_channel.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. var Cc = Components.classes;
  2. var Ci = Components.interfaces;
  3. var Cr = Components.results;
  4. var Cu = Components.utils;
  5. Cu.import("resource://gre/modules/Services.jsm");
  6. Cu.import("resource://gre/modules/NetUtil.jsm");
  7. Cu.import("resource://testing-common/httpd.js");
  8. var server = new HttpServer();
  9. server.registerPathHandler('/image.png', imageHandler);
  10. server.start(-1);
  11. load('image_load_helpers.js');
  12. var gHits = 0;
  13. var gIoService = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
  14. var gPublicLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
  15. var gPrivateLoader = Cc["@mozilla.org/image/loader;1"].createInstance(Ci.imgILoader);
  16. gPrivateLoader.QueryInterface(Ci.imgICache).respectPrivacyNotifications();
  17. function imageHandler(metadata, response) {
  18. gHits++;
  19. response.setHeader("Cache-Control", "max-age=10000", false);
  20. response.setStatusLine(metadata.httpVersion, 200, "OK");
  21. response.setHeader("Content-Type", "image/png", false);
  22. var body = "iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAEUlEQVQImWP4z8AAQTAamQkAhpcI+DeMzFcAAAAASUVORK5CYII=";
  23. response.bodyOutputStream.write(body, body.length);
  24. }
  25. var requests = [];
  26. var listeners = [];
  27. function NotificationCallbacks(isPrivate) {
  28. this.originAttributes.privateBrowsingId = isPrivate ? 1 : 0;
  29. this.usePrivateBrowsing = isPrivate;
  30. }
  31. NotificationCallbacks.prototype = {
  32. QueryInterface: function (iid) {
  33. if (iid.equals(Ci.nsISupports) ||
  34. iid.equals(Ci.nsILoadContext))
  35. return this;
  36. throw Cr.NS_ERROR_NO_INTERFACE;
  37. },
  38. getInterface: function(iid) {
  39. if (iid.equals(Ci.nsILoadContext))
  40. return this;
  41. throw Cr.NS_ERROR_NO_INTERFACE;
  42. },
  43. originAttributes: {
  44. privateBrowsingId: 0
  45. }
  46. };
  47. var gImgPath = 'http://localhost:' + server.identity.primaryPort + '/image.png';
  48. function setup_chan(path, isPrivate, callback) {
  49. var uri = NetUtil.newURI(gImgPath);
  50. var securityFlags = Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL;
  51. var principal = Services.scriptSecurityManager
  52. .createCodebasePrincipal(uri, {privateBrowsingId: isPrivate ? 1 : 0});
  53. var chan = NetUtil.newChannel({uri: uri, loadingPrincipal: principal,
  54. securityFlags: securityFlags,
  55. contentPolicyType: Ci.nsIContentPolicy.TYPE_INTERNAL_IMAGE});
  56. chan.notificationCallbacks = new NotificationCallbacks(isPrivate);
  57. var channelListener = new ChannelListener();
  58. chan.asyncOpen2(channelListener);
  59. var listener = new ImageListener(null, callback);
  60. var outlistener = {};
  61. var loader = isPrivate ? gPrivateLoader : gPublicLoader;
  62. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  63. .createScriptedObserver(listener);
  64. listeners.push(outer);
  65. requests.push(loader.loadImageWithChannelXPCOM(chan, outer, null, outlistener));
  66. channelListener.outputListener = outlistener.value;
  67. listener.synchronous = false;
  68. }
  69. function loadImage(isPrivate, callback) {
  70. var listener = new ImageListener(null, callback);
  71. var outer = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
  72. .createScriptedObserver(listener);
  73. var uri = gIoService.newURI(gImgPath, null, null);
  74. var loadGroup = Cc["@mozilla.org/network/load-group;1"].createInstance(Ci.nsILoadGroup);
  75. loadGroup.notificationCallbacks = new NotificationCallbacks(isPrivate);
  76. var loader = isPrivate ? gPrivateLoader : gPublicLoader;
  77. requests.push(loader.loadImageXPCOM(uri, null, null, "default", null, loadGroup, outer, null, 0, null));
  78. listener.synchronous = false;
  79. }
  80. function run_loadImage_tests() {
  81. function observer() {
  82. Services.obs.removeObserver(observer, "cacheservice:empty-cache");
  83. gHits = 0;
  84. loadImage(false, function() {
  85. loadImage(false, function() {
  86. loadImage(true, function() {
  87. loadImage(true, function() {
  88. do_check_eq(gHits, 2);
  89. server.stop(do_test_finished);
  90. });
  91. });
  92. });
  93. });
  94. }
  95. Services.obs.addObserver(observer, "cacheservice:empty-cache", false);
  96. let cs = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
  97. .getService(Ci.nsICacheStorageService);
  98. cs.clear();
  99. }
  100. function cleanup()
  101. {
  102. for (var i = 0; i < requests.length; ++i) {
  103. requests[i].cancelAndForgetObserver(0);
  104. }
  105. }
  106. function run_test() {
  107. do_register_cleanup(cleanup);
  108. do_test_pending();
  109. // We create a public channel that loads an image, then an identical
  110. // one that should cause a cache read. We then create a private channel
  111. // and load the same image, and do that a second time to ensure a cache
  112. // read. In total, we should cause two separate http responses to occur,
  113. // since the private channels shouldn't be able to use the public cache.
  114. setup_chan('/image.png', false, function() {
  115. setup_chan('/image.png', false, function() {
  116. setup_chan('/image.png', true, function() {
  117. setup_chan('/image.png', true, function() {
  118. do_check_eq(gHits, 2);
  119. run_loadImage_tests();
  120. });
  121. });
  122. });
  123. });
  124. }