1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. 20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** 30 * @constructor 31 * @extends {WebInspector.Object} 32 */ 33 WebInspector.ApplicationCacheModel = function() 34 { 35 ApplicationCacheAgent.enable(); 36 InspectorBackend.registerApplicationCacheDispatcher(new WebInspector.ApplicationCacheDispatcher(this)); 37 38 WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this); 39 WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this); 40 41 this._statuses = {}; 42 this._manifestURLsByFrame = {}; 43 44 this._mainFrameNavigated(); 45 46 this._onLine = true; 47 } 48 49 WebInspector.ApplicationCacheModel.EventTypes = { 50 FrameManifestStatusUpdated: "FrameManifestStatusUpdated", 51 FrameManifestAdded: "FrameManifestAdded", 52 FrameManifestRemoved: "FrameManifestRemoved", 53 NetworkStateChanged: "NetworkStateChanged" 54 } 55 56 WebInspector.ApplicationCacheModel.prototype = { 57 _frameNavigated: function(event) 58 { 59 var frame = /** @type {WebInspector.ResourceTreeFrame} */ (event.data); 60 if (frame.isMainFrame()) { 61 this._mainFrameNavigated(); 62 return; 63 } 64 65 ApplicationCacheAgent.getManifestForFrame(frame.id, this._manifestForFrameLoaded.bind(this, frame.id)); 66 }, 67 68 /** 69 * @param {WebInspector.Event} event 70 */ 71 _frameDetached: function(event) 72 { 73 var frame = /** @type {WebInspector.ResourceTreeFrame} */ (event.data); 74 this._frameManifestRemoved(frame.id); 75 }, 76 77 _mainFrameNavigated: function() 78 { 79 ApplicationCacheAgent.getFramesWithManifests(this._framesWithManifestsLoaded.bind(this)); 80 }, 81 82 /** 83 * @param {string} frameId 84 * @param {?Protocol.Error} error 85 * @param {string} manifestURL 86 */ 87 _manifestForFrameLoaded: function(frameId, error, manifestURL) 88 { 89 if (error) { 90 console.error(error); 91 return; 92 } 93 94 if (!manifestURL) 95 this._frameManifestRemoved(frameId); 96 }, 97 98 /** 99 * @param {?Protocol.Error} error 100 * @param {Array.<ApplicationCacheAgent.FrameWithManifest>} framesWithManifests 101 */ 102 _framesWithManifestsLoaded: function(error, framesWithManifests) 103 { 104 if (error) { 105 console.error(error); 106 return; 107 } 108 109 for (var i = 0; i < framesWithManifests.length; ++i) 110 this._frameManifestUpdated(framesWithManifests[i].frameId, framesWithManifests[i].manifestURL, framesWithManifests[i].status); 111 }, 112 113 /** 114 * @param {string} frameId 115 * @param {string} manifestURL 116 * @param {number} status 117 */ 118 _frameManifestUpdated: function(frameId, manifestURL, status) 119 { 120 if (status === applicationCache.UNCACHED) { 121 this._frameManifestRemoved(frameId); 122 return; 123 } 124 125 if (!manifestURL) 126 return; 127 128 if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId]) 129 this._frameManifestRemoved(frameId); 130 131 var statusChanged = this._statuses[frameId] !== status; 132 this._statuses[frameId] = status; 133 134 if (!this._manifestURLsByFrame[frameId]) { 135 this._manifestURLsByFrame[frameId] = manifestURL; 136 this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, frameId); 137 } 138 139 if (statusChanged) 140 this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, frameId); 141 }, 142 143 /** 144 * @param {string} frameId 145 */ 146 _frameManifestRemoved: function(frameId) 147 { 148 if (!this._manifestURLsByFrame[frameId]) 149 return; 150 151 var manifestURL = this._manifestURLsByFrame[frameId]; 152 delete this._manifestURLsByFrame[frameId]; 153 delete this._statuses[frameId]; 154 155 this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, frameId); 156 }, 157 158 /** 159 * @param {string} frameId 160 * @return {string} 161 */ 162 frameManifestURL: function(frameId) 163 { 164 return this._manifestURLsByFrame[frameId] || ""; 165 }, 166 167 /** 168 * @param {string} frameId 169 * @return {number} 170 */ 171 frameManifestStatus: function(frameId) 172 { 173 return this._statuses[frameId] || applicationCache.UNCACHED; 174 }, 175 176 /** 177 * @return {boolean} 178 */ 179 get onLine() 180 { 181 return this._onLine; 182 }, 183 184 /** 185 * @param {string} frameId 186 * @param {string} manifestURL 187 * @param {number} status 188 */ 189 _statusUpdated: function(frameId, manifestURL, status) 190 { 191 this._frameManifestUpdated(frameId, manifestURL, status); 192 }, 193 194 /** 195 * @param {string} frameId 196 * @param {function(Object)} callback 197 */ 198 requestApplicationCache: function(frameId, callback) 199 { 200 function callbackWrapper(error, applicationCache) 201 { 202 if (error) { 203 console.error(error); 204 callback(null); 205 return; 206 } 207 208 callback(applicationCache); 209 } 210 211 ApplicationCacheAgent.getApplicationCacheForFrame(frameId, callbackWrapper.bind(this)); 212 }, 213 214 /** 215 * @param {boolean} isNowOnline 216 */ 217 _networkStateUpdated: function(isNowOnline) 218 { 219 this._onLine = isNowOnline; 220 this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, isNowOnline); 221 }, 222 223 __proto__: WebInspector.Object.prototype 224 } 225 226 /** 227 * @constructor 228 * @implements {ApplicationCacheAgent.Dispatcher} 229 */ 230 WebInspector.ApplicationCacheDispatcher = function(applicationCacheModel) 231 { 232 this._applicationCacheModel = applicationCacheModel; 233 } 234 235 WebInspector.ApplicationCacheDispatcher.prototype = { 236 /** 237 * @param {string} frameId 238 * @param {string} manifestURL 239 * @param {number} status 240 */ 241 applicationCacheStatusUpdated: function(frameId, manifestURL, status) 242 { 243 this._applicationCacheModel._statusUpdated(frameId, manifestURL, status); 244 }, 245 246 /** 247 * @param {boolean} isNowOnline 248 */ 249 networkStateUpdated: function(isNowOnline) 250 { 251 this._applicationCacheModel._networkStateUpdated(isNowOnline); 252 } 253 } 254