1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// A simple, incomplete implementation of the Cache API, intended to facilitate 6// end to end serviceworker testing. 7 8// See https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html#cache-objects 9 10// FIXME: Support AbstractResponse/OpaqueResponse correctly. 11// FIXME: Serialize the cache. 12// FIXME: Bind all function references. 13(function(global) { 14 var _castToRequest = function(item) { 15 if (typeof item === 'string') { 16 item = new Request({ 17 url: item, 18 }); 19 } 20 return item; 21 }; 22 23 var Cache = function() { 24 // An object containing a property for each HTTP fetch method. Those 25 // referenced objects contain a property for each URL, which is the 26 // Response. 27 this.entriesByMethod = {}; 28 }; 29 30 // FIXME: Should this be in the spec? 31 Cache.prototype.keys = function() { 32 var that = this; 33 34 var flatten = Array.prototype.concat.apply.bind(Array.prototype.concat, []); 35 36 return Promise.resolve(flatten( 37 Object.keys(this.entriesByMethod).map(function(method) { 38 return Object.keys(that.entriesByMethod[method]).map(function(url) { 39 return new Request({method: method, url: url}); 40 }); 41 }))); 42 }; 43 44 // FIXME: Implement this. 45 // FIXME: Should spec rename each --> forEach? 46 Cache.prototype.forEach = Promise.reject.bind(Promise, 'Cache.prototype.forEach() not implemented.'); 47 Cache.prototype.each = Promise.reject.bind(Promise, 'Cache.prototype.each() not implemented.'); 48 49 Cache.prototype.put = function(request, response) { 50 var that = this; 51 52 return new Promise(function(resolve, reject) { 53 request = _castToRequest(request); 54 55 if (!that.entriesByMethod.hasOwnProperty(request.method)) { 56 that.entriesByMethod[request.method] = {}; 57 } 58 59 var entriesByUrl = that.entriesByMethod[request.method]; 60 entriesByUrl[request.url] = response; 61 62 resolve(); 63 }); 64 }; 65 66 Cache.prototype.add = function(request) { 67 var that = this; 68 request = _castToRequest(request); 69 return new Promise(function (resolve, reject) { 70 fetch(request).then( 71 function(response) { 72 that.put(request, response).then(resolve); 73 }, 74 reject); 75 }); 76 }; 77 78 // FIXME: Add QueryParams argument. 79 Cache.prototype.delete = function(request) { 80 request = _castToRequest(request); 81 82 var that = this; 83 return new Promise(function(resolve, reject) { 84 if (that.entriesByMethod.hasOwnProperty(request.method)) { 85 var entriesByUrl = that.entriesByMethod[request.method]; 86 delete entriesByUrl[request.url]; 87 } 88 resolve(); 89 }); 90 }; 91 92 // FIXME: Add QueryParams argument. 93 Cache.prototype.match = function(request) { 94 var that = this; 95 96 return new Promise(function(resolve, reject) { 97 request = _castToRequest(request); 98 99 if (!that.entriesByMethod.hasOwnProperty(request.method)) { 100 reject('not found'); 101 return; 102 } 103 104 var entriesByUrl = that.entriesByMethod[request.method]; 105 106 if (!entriesByUrl.hasOwnProperty(request.url)) { 107 reject('not found'); 108 return; 109 } 110 111 var entry = entriesByUrl[request.url]; 112 resolve(entry); 113 }); 114 }; 115 116 // FIXME: Implement this. 117 Cache.prototype.matchAll = Promise.reject.bind(Promise, 'Cache.prototype.matchAll not implemented.'); 118 119 global.Cache = global.Cache || Cache; 120}(self)); // window or worker global scope. 121