OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 /** |
| 6 * @implements {SDK.SDKModelObserver<!SDK.ResourceTreeModel>} |
| 7 */ |
| 8 Bindings.ResourceMapping = class { |
| 9 /** |
| 10 * @param {!SDK.TargetManager} targetManager |
| 11 * @param {!Workspace.Workspace} workspace |
| 12 */ |
| 13 constructor(targetManager, workspace) { |
| 14 this._workspace = workspace; |
| 15 /** @type {!Map<!SDK.ResourceTreeModel, !Bindings.ResourceMapping.ModelInfo>
} */ |
| 16 this._modelToInfo = new Map(); |
| 17 targetManager.observeModels(SDK.ResourceTreeModel, this); |
| 18 } |
| 19 |
| 20 /** |
| 21 * @override |
| 22 * @param {!SDK.ResourceTreeModel} resourceTreeModel |
| 23 */ |
| 24 modelAdded(resourceTreeModel) { |
| 25 var info = new Bindings.ResourceMapping.ModelInfo(this._workspace, resourceT
reeModel); |
| 26 this._modelToInfo.set(resourceTreeModel, info); |
| 27 } |
| 28 |
| 29 /** |
| 30 * @override |
| 31 * @param {!SDK.ResourceTreeModel} resourceTreeModel |
| 32 */ |
| 33 modelRemoved(resourceTreeModel) { |
| 34 var info = this._modelToInfo.get(resourceTreeModel); |
| 35 info.dispose(); |
| 36 this._modelToInfo.delete(resourceTreeModel); |
| 37 } |
| 38 |
| 39 /** |
| 40 * @param {!SDK.Target} target |
| 41 * @return {?Bindings.ResourceMapping.ModelInfo} |
| 42 */ |
| 43 _infoForTarget(target) { |
| 44 var resourceTreeModel = target.model(SDK.ResourceTreeModel); |
| 45 return resourceTreeModel ? this._modelToInfo.get(resourceTreeModel) : null; |
| 46 } |
| 47 |
| 48 /** |
| 49 * @param {!SDK.CSSLocation} cssLocation |
| 50 * @return {?Workspace.UILocation} |
| 51 */ |
| 52 cssLocationToUILocation(cssLocation) { |
| 53 var info = this._infoForTarget(cssLocation.cssModel().target()); |
| 54 if (!info) |
| 55 return null; |
| 56 var uiSourceCode = info._project.uiSourceCodeForURL(cssLocation.url); |
| 57 return uiSourceCode ? uiSourceCode.uiLocation(cssLocation.lineNumber, cssLoc
ation.columnNumber) : null; |
| 58 } |
| 59 |
| 60 /** |
| 61 * @param {!SDK.DebuggerModel.Location} jsLocation |
| 62 * @return {?Workspace.UILocation} |
| 63 */ |
| 64 jsLocationToUILocation(jsLocation) { |
| 65 var script = jsLocation.script(); |
| 66 if (!script) |
| 67 return null; |
| 68 var info = this._infoForTarget(jsLocation.debuggerModel.target()); |
| 69 if (!info) |
| 70 return null; |
| 71 var uiSourceCode = info._project.uiSourceCodeForURL(script.sourceURL); |
| 72 return uiSourceCode ? uiSourceCode.uiLocation(jsLocation.lineNumber, jsLocat
ion.columnNumber) : null; |
| 73 } |
| 74 |
| 75 /** |
| 76 * @param {!Workspace.UISourceCode} uiSourceCode |
| 77 * @param {number} lineNumber |
| 78 * @param {number} columnNumber |
| 79 * @return {?SDK.DebuggerModel.Location} |
| 80 */ |
| 81 uiLocationToJSLocation(uiSourceCode, lineNumber, columnNumber) { |
| 82 if (!uiSourceCode[Bindings.ResourceMapping._symbol]) |
| 83 return null; |
| 84 var target = Bindings.NetworkProject.targetForUISourceCode(uiSourceCode); |
| 85 if (!target) |
| 86 return null; |
| 87 var debuggerModel = target.model(SDK.DebuggerModel); |
| 88 if (!debuggerModel) |
| 89 return null; |
| 90 return debuggerModel.createRawLocationByURL(uiSourceCode.url(), lineNumber,
columnNumber); |
| 91 } |
| 92 |
| 93 /** |
| 94 * @param {!SDK.Target} target |
| 95 */ |
| 96 _resetForTest(target) { |
| 97 var resourceTreeModel = target.model(SDK.ResourceTreeModel); |
| 98 var info = resourceTreeModel ? this._modelToInfo.get(resourceTreeModel) : nu
ll; |
| 99 if (info) |
| 100 info._resetForTest(); |
| 101 } |
| 102 }; |
| 103 |
| 104 Bindings.ResourceMapping.ModelInfo = class { |
| 105 /** |
| 106 * @param {!Workspace.Workspace} workspace |
| 107 * @param {!SDK.ResourceTreeModel} resourceTreeModel |
| 108 */ |
| 109 constructor(workspace, resourceTreeModel) { |
| 110 var target = resourceTreeModel.target(); |
| 111 this._project = new Bindings.ContentProviderBasedProject( |
| 112 workspace, 'resources:' + target.id(), Workspace.projectTypes.Network, '
', false /* isServiceProject */); |
| 113 Bindings.NetworkProject.setTargetForProject(this._project, target); |
| 114 |
| 115 /** @type {!Map<string, !Bindings.ResourceMapping.Binding>} */ |
| 116 this._bindings = new Map(); |
| 117 |
| 118 this._eventListeners = [ |
| 119 resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.ResourceAd
ded, this._resourceAdded, this), |
| 120 resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameWillN
avigate, this._frameWillNavigate, this), |
| 121 resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameDetac
hed, this._frameDetached, this) |
| 122 ]; |
| 123 } |
| 124 |
| 125 /** |
| 126 * @param {!SDK.Resource} resource |
| 127 */ |
| 128 _acceptsResource(resource) { |
| 129 var resourceType = resource.resourceType(); |
| 130 // Only load selected resource types from resources. |
| 131 if (resourceType !== Common.resourceTypes.Image && resourceType !== Common.r
esourceTypes.Font && |
| 132 resourceType !== Common.resourceTypes.Document && resourceType !== Commo
n.resourceTypes.Manifest) |
| 133 return false; |
| 134 |
| 135 // Ignore non-images and non-fonts. |
| 136 if (resourceType === Common.resourceTypes.Image && resource.mimeType && !res
ource.mimeType.startsWith('image')) |
| 137 return false; |
| 138 if (resourceType === Common.resourceTypes.Font && resource.mimeType && !reso
urce.mimeType.includes('font')) |
| 139 return false; |
| 140 if ((resourceType === Common.resourceTypes.Image || resourceType === Common.
resourceTypes.Font) && |
| 141 resource.contentURL().startsWith('data:')) |
| 142 return false; |
| 143 return true; |
| 144 } |
| 145 |
| 146 /** |
| 147 * @param {!Common.Event} event |
| 148 */ |
| 149 _resourceAdded(event) { |
| 150 var resource = /** @type {!SDK.Resource} */ (event.data); |
| 151 if (!this._acceptsResource(resource)) |
| 152 return; |
| 153 |
| 154 var binding = this._bindings.get(resource.url); |
| 155 if (!binding) { |
| 156 binding = new Bindings.ResourceMapping.Binding(this._project, resource); |
| 157 this._bindings.set(resource.url, binding); |
| 158 } else { |
| 159 binding.addResource(resource); |
| 160 } |
| 161 } |
| 162 |
| 163 /** |
| 164 * @param {!SDK.ResourceTreeFrame} frame |
| 165 */ |
| 166 _removeFrameResources(frame) { |
| 167 for (var resource of frame.resources()) { |
| 168 if (!this._acceptsResource(resource)) |
| 169 continue; |
| 170 var binding = this._bindings.get(resource.url); |
| 171 if (binding._resources.size === 1) { |
| 172 binding.dispose(); |
| 173 this._bindings.delete(resource.url); |
| 174 } else { |
| 175 binding.removeResource(resource); |
| 176 } |
| 177 } |
| 178 } |
| 179 |
| 180 /** |
| 181 * @param {!Common.Event} event |
| 182 */ |
| 183 _frameWillNavigate(event) { |
| 184 var frame = /** @type {!SDK.ResourceTreeFrame} */ (event.data); |
| 185 this._removeFrameResources(frame); |
| 186 } |
| 187 |
| 188 /** |
| 189 * @param {!Common.Event} event |
| 190 */ |
| 191 _frameDetached(event) { |
| 192 var frame = /** @type {!SDK.ResourceTreeFrame} */ (event.data); |
| 193 this._removeFrameResources(frame); |
| 194 } |
| 195 |
| 196 _resetForTest() { |
| 197 for (var binding of this._bindings.valuesArray()) |
| 198 binding.dispose(); |
| 199 this._bindings.clear(); |
| 200 } |
| 201 |
| 202 dispose() { |
| 203 Common.EventTarget.removeEventListeners(this._eventListeners); |
| 204 for (var binding of this._bindings.valuesArray()) |
| 205 binding.dispose(); |
| 206 this._bindings.clear(); |
| 207 this._project.removeProject(); |
| 208 } |
| 209 }; |
| 210 |
| 211 /** |
| 212 * @implements {Common.ContentProvider} |
| 213 */ |
| 214 Bindings.ResourceMapping.Binding = class { |
| 215 /** |
| 216 * @param {!Bindings.ContentProviderBasedProject} project |
| 217 * @param {!SDK.Resource} resource |
| 218 */ |
| 219 constructor(project, resource) { |
| 220 this._resources = new Set([resource]); |
| 221 this._project = project; |
| 222 this._uiSourceCode = this._project.createUISourceCode(resource.url, resource
.contentType()); |
| 223 this._uiSourceCode[Bindings.ResourceMapping._symbol] = true; |
| 224 Bindings.NetworkProject.setInitialFrameAttribution(this._uiSourceCode, resou
rce.frameId); |
| 225 this._project.addUISourceCodeWithProvider( |
| 226 this._uiSourceCode, this, Bindings.resourceMetadata(resource), resource.
mimeType); |
| 227 } |
| 228 |
| 229 /** |
| 230 * @param {!SDK.Resource} resource |
| 231 */ |
| 232 addResource(resource) { |
| 233 this._resources.add(resource); |
| 234 Bindings.NetworkProject.addFrameAttribution(this._uiSourceCode, resource.fra
meId); |
| 235 } |
| 236 |
| 237 /** |
| 238 * @param {!SDK.Resource} resource |
| 239 */ |
| 240 removeResource(resource) { |
| 241 this._resources.delete(resource); |
| 242 Bindings.NetworkProject.removeFrameAttribution(this._uiSourceCode, resource.
frameId); |
| 243 } |
| 244 |
| 245 dispose() { |
| 246 this._project.removeFile(this._uiSourceCode.url()); |
| 247 } |
| 248 |
| 249 /** |
| 250 * @override |
| 251 * @return {string} |
| 252 */ |
| 253 contentURL() { |
| 254 return this._resources.firstValue().contentURL(); |
| 255 } |
| 256 |
| 257 /** |
| 258 * @override |
| 259 * @return {!Common.ResourceType} |
| 260 */ |
| 261 contentType() { |
| 262 return this._resources.firstValue().contentType(); |
| 263 } |
| 264 |
| 265 /** |
| 266 * @override |
| 267 * @return {!Promise<?string>} |
| 268 */ |
| 269 requestContent() { |
| 270 return this._resources.firstValue().requestContent(); |
| 271 } |
| 272 |
| 273 /** |
| 274 * @override |
| 275 * @param {string} query |
| 276 * @param {boolean} caseSensitive |
| 277 * @param {boolean} isRegex |
| 278 * @return {!Promise<!Array<!Common.ContentProvider.SearchMatch>>} |
| 279 */ |
| 280 searchInContent(query, caseSensitive, isRegex) { |
| 281 return this._resources.firstValue().searchInContent(query, caseSensitive, is
Regex); |
| 282 } |
| 283 }; |
| 284 |
| 285 Bindings.ResourceMapping._symbol = Symbol('Bindings.ResourceMapping._symbol'); |
OLD | NEW |