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 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 /** 32 * @constructor 33 * @extends {WebInspector.Object} 34 * @param {!WebInspector.NetworkManager} networkManager 35 */ 36 WebInspector.ResourceTreeModel = function(networkManager) 37 { 38 networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this); 39 networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, this); 40 41 WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this); 42 WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this); 43 WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this); 44 45 PageAgent.enable(); 46 47 this._fetchResourceTree(); 48 49 InspectorBackend.registerPageDispatcher(new WebInspector.PageDispatcher(this)); 50 51 this._pendingConsoleMessages = {}; 52 this._securityOriginFrameCount = {}; 53 } 54 55 WebInspector.ResourceTreeModel.EventTypes = { 56 FrameAdded: "FrameAdded", 57 FrameNavigated: "FrameNavigated", 58 FrameDetached: "FrameDetached", 59 FrameResized: "FrameResized", 60 MainFrameNavigated: "MainFrameNavigated", 61 MainFrameCreatedOrNavigated: "MainFrameCreatedOrNavigated", 62 ResourceAdded: "ResourceAdded", 63 WillLoadCachedResources: "WillLoadCachedResources", 64 CachedResourcesLoaded: "CachedResourcesLoaded", 65 DOMContentLoaded: "DOMContentLoaded", 66 Load: "Load", 67 WillReloadPage: "WillReloadPage", 68 InspectedURLChanged: "InspectedURLChanged", 69 SecurityOriginAdded: "SecurityOriginAdded", 70 SecurityOriginRemoved: "SecurityOriginRemoved", 71 ScreencastFrame: "ScreencastFrame", 72 ScreencastVisibilityChanged: "ScreencastVisibilityChanged" 73 } 74 75 WebInspector.ResourceTreeModel.prototype = { 76 _fetchResourceTree: function() 77 { 78 /** @type {!Object.<string, !WebInspector.ResourceTreeFrame>} */ 79 this._frames = {}; 80 delete this._cachedResourcesProcessed; 81 PageAgent.getResourceTree(this._processCachedResources.bind(this)); 82 }, 83 84 _processCachedResources: function(error, mainFramePayload) 85 { 86 if (error) { 87 console.error(JSON.stringify(error)); 88 return; 89 } 90 91 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources); 92 WebInspector.inspectedPageURL = mainFramePayload.frame.url; 93 this._addFramesRecursively(null, mainFramePayload); 94 this._dispatchInspectedURLChanged(); 95 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded); 96 this._cachedResourcesProcessed = true; 97 }, 98 99 cachedResourcesLoaded: function() 100 { 101 return this._cachedResourcesProcessed; 102 }, 103 104 _dispatchInspectedURLChanged: function() 105 { 106 InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL); 107 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL); 108 }, 109 110 /** 111 * @param {!WebInspector.ResourceTreeFrame} frame 112 * @param {boolean=} aboutToNavigate 113 */ 114 _addFrame: function(frame, aboutToNavigate) 115 { 116 this._frames[frame.id] = frame; 117 if (frame.isMainFrame()) 118 this.mainFrame = frame; 119 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame); 120 if (!aboutToNavigate) 121 this._addSecurityOrigin(frame.securityOrigin); 122 if (frame.isMainFrame()) 123 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameCreatedOrNavigated, frame); 124 }, 125 126 /** 127 * @param {string} securityOrigin 128 */ 129 _addSecurityOrigin: function(securityOrigin) 130 { 131 if (!this._securityOriginFrameCount[securityOrigin]) { 132 this._securityOriginFrameCount[securityOrigin] = 1; 133 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, securityOrigin); 134 return; 135 } 136 this._securityOriginFrameCount[securityOrigin] += 1; 137 }, 138 139 /** 140 * @param {string|undefined} securityOrigin 141 */ 142 _removeSecurityOrigin: function(securityOrigin) 143 { 144 if (typeof securityOrigin === "undefined") 145 return; 146 if (this._securityOriginFrameCount[securityOrigin] === 1) { 147 delete this._securityOriginFrameCount[securityOrigin]; 148 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, securityOrigin); 149 return; 150 } 151 this._securityOriginFrameCount[securityOrigin] -= 1; 152 }, 153 154 /** 155 * @return {!Array.<string>} 156 */ 157 securityOrigins: function() 158 { 159 return Object.keys(this._securityOriginFrameCount); 160 }, 161 162 /** 163 * @param {!WebInspector.ResourceTreeFrame} mainFrame 164 */ 165 _handleMainFrameDetached: function(mainFrame) 166 { 167 /** 168 * @param {!WebInspector.ResourceTreeFrame} frame 169 * @this {WebInspector.ResourceTreeModel} 170 */ 171 function removeOriginForFrame(frame) 172 { 173 for (var i = 0; i < frame.childFrames.length; ++i) 174 removeOriginForFrame.call(this, frame.childFrames[i]); 175 if (!frame.isMainFrame()) 176 this._removeSecurityOrigin(frame.securityOrigin); 177 } 178 removeOriginForFrame.call(this, WebInspector.resourceTreeModel.mainFrame); 179 }, 180 181 /** 182 * @param {!PageAgent.FrameId} frameId 183 * @param {?PageAgent.FrameId} parentFrameId 184 * @return {?WebInspector.ResourceTreeFrame} 185 */ 186 _frameAttached: function(frameId, parentFrameId) 187 { 188 // Do nothing unless cached resource tree is processed - it will overwrite everything. 189 if (!this._cachedResourcesProcessed) 190 return null; 191 if (this._frames[frameId]) 192 return null; 193 194 var parentFrame = parentFrameId ? this._frames[parentFrameId] : null; 195 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, frameId); 196 if (frame.isMainFrame() && this.mainFrame) { 197 this._handleMainFrameDetached(this.mainFrame); 198 // Navigation to the new backend process. 199 this._frameDetached(this.mainFrame.id); 200 } 201 this._addFrame(frame, true); 202 return frame; 203 }, 204 205 /** 206 * @param {!PageAgent.Frame} framePayload 207 */ 208 _frameNavigated: function(framePayload) 209 { 210 // Do nothing unless cached resource tree is processed - it will overwrite everything. 211 if (!this._cachedResourcesProcessed) 212 return; 213 var frame = this._frames[framePayload.id]; 214 if (!frame) { 215 // Simulate missed "frameAttached" for a main frame navigation to the new backend process. 216 console.assert(!framePayload.parentId, "Main frame shouldn't have parent frame id."); 217 frame = this._frameAttached(framePayload.id, framePayload.parentId || ""); 218 console.assert(frame); 219 } 220 this._removeSecurityOrigin(frame.securityOrigin); 221 frame._navigate(framePayload); 222 var addedOrigin = frame.securityOrigin; 223 224 if (frame.isMainFrame()) 225 WebInspector.inspectedPageURL = frame.url; 226 227 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame); 228 if (frame.isMainFrame()) { 229 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame); 230 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameCreatedOrNavigated, frame); 231 } 232 if (addedOrigin) 233 this._addSecurityOrigin(addedOrigin); 234 235 // Fill frame with retained resources (the ones loaded using new loader). 236 var resources = frame.resources(); 237 for (var i = 0; i < resources.length; ++i) 238 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]); 239 240 if (frame.isMainFrame()) 241 this._dispatchInspectedURLChanged(); 242 }, 243 244 /** 245 * @param {!PageAgent.FrameId} frameId 246 */ 247 _frameDetached: function(frameId) 248 { 249 // Do nothing unless cached resource tree is processed - it will overwrite everything. 250 if (!this._cachedResourcesProcessed) 251 return; 252 253 var frame = this._frames[frameId]; 254 if (!frame) 255 return; 256 257 this._removeSecurityOrigin(frame.securityOrigin); 258 if (frame.parentFrame) 259 frame.parentFrame._removeChildFrame(frame); 260 else 261 frame._remove(); 262 }, 263 264 /** 265 * @param {!WebInspector.Event} event 266 */ 267 _onRequestFinished: function(event) 268 { 269 if (!this._cachedResourcesProcessed) 270 return; 271 272 var request = /** @type {!WebInspector.NetworkRequest} */ (event.data); 273 if (request.failed || request.type === WebInspector.resourceTypes.XHR) 274 return; 275 276 var frame = this._frames[request.frameId]; 277 if (frame) { 278 var resource = frame._addRequest(request); 279 this._addPendingConsoleMessagesToResource(resource); 280 } 281 }, 282 283 /** 284 * @param {!WebInspector.Event} event 285 */ 286 _onRequestUpdateDropped: function(event) 287 { 288 if (!this._cachedResourcesProcessed) 289 return; 290 291 var frameId = event.data.frameId; 292 var frame = this._frames[frameId]; 293 if (!frame) 294 return; 295 296 var url = event.data.url; 297 if (frame._resourcesMap[url]) 298 return; 299 300 var resource = new WebInspector.Resource(null, url, frame.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType); 301 frame.addResource(resource); 302 }, 303 304 /** 305 * @param {!PageAgent.FrameId} frameId 306 * @return {!WebInspector.ResourceTreeFrame} 307 */ 308 frameForId: function(frameId) 309 { 310 return this._frames[frameId]; 311 }, 312 313 /** 314 * @param {function(!WebInspector.Resource)} callback 315 * @return {boolean} 316 */ 317 forAllResources: function(callback) 318 { 319 if (this.mainFrame) 320 return this.mainFrame._callForFrameResources(callback); 321 return false; 322 }, 323 324 /** 325 * @return {!Array.<!WebInspector.ResourceTreeFrame>} 326 */ 327 frames: function() 328 { 329 return Object.values(this._frames); 330 }, 331 332 /** 333 * @param {!WebInspector.Event} event 334 */ 335 _consoleMessageAdded: function(event) 336 { 337 var msg = /** @type {!WebInspector.ConsoleMessage} */ (event.data); 338 var resource = msg.url ? this.resourceForURL(msg.url) : null; 339 if (resource) 340 this._addConsoleMessageToResource(msg, resource); 341 else 342 this._addPendingConsoleMessage(msg); 343 }, 344 345 /** 346 * @param {!WebInspector.ConsoleMessage} msg 347 */ 348 _addPendingConsoleMessage: function(msg) 349 { 350 if (!msg.url) 351 return; 352 if (!this._pendingConsoleMessages[msg.url]) 353 this._pendingConsoleMessages[msg.url] = []; 354 this._pendingConsoleMessages[msg.url].push(msg); 355 }, 356 357 /** 358 * @param {!WebInspector.Resource} resource 359 */ 360 _addPendingConsoleMessagesToResource: function(resource) 361 { 362 var messages = this._pendingConsoleMessages[resource.url]; 363 if (messages) { 364 for (var i = 0; i < messages.length; i++) 365 this._addConsoleMessageToResource(messages[i], resource); 366 delete this._pendingConsoleMessages[resource.url]; 367 } 368 }, 369 370 /** 371 * @param {!WebInspector.ConsoleMessage} msg 372 * @param {!WebInspector.Resource} resource 373 */ 374 _addConsoleMessageToResource: function(msg, resource) 375 { 376 switch (msg.level) { 377 case WebInspector.ConsoleMessage.MessageLevel.Warning: 378 resource.warnings += msg.repeatDelta; 379 break; 380 case WebInspector.ConsoleMessage.MessageLevel.Error: 381 resource.errors += msg.repeatDelta; 382 break; 383 } 384 resource.addMessage(msg); 385 }, 386 387 _consoleCleared: function() 388 { 389 function callback(resource) 390 { 391 resource.clearErrorsAndWarnings(); 392 } 393 394 this._pendingConsoleMessages = {}; 395 this.forAllResources(callback); 396 }, 397 398 /** 399 * @param {string} url 400 * @return {!WebInspector.Resource} 401 */ 402 resourceForURL: function(url) 403 { 404 // Workers call into this with no frames available. 405 return this.mainFrame ? this.mainFrame.resourceForURL(url) : null; 406 }, 407 408 /** 409 * @param {?WebInspector.ResourceTreeFrame} parentFrame 410 * @param {!PageAgent.FrameResourceTree} frameTreePayload 411 */ 412 _addFramesRecursively: function(parentFrame, frameTreePayload) 413 { 414 var framePayload = frameTreePayload.frame; 415 var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload.id, framePayload); 416 this._addFrame(frame); 417 418 var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url, WebInspector.resourceTypes.Document, framePayload.mimeType); 419 if (frame.isMainFrame()) 420 WebInspector.inspectedPageURL = frameResource.url; 421 frame.addResource(frameResource); 422 423 for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i) 424 this._addFramesRecursively(frame, frameTreePayload.childFrames[i]); 425 426 for (var i = 0; i < frameTreePayload.resources.length; ++i) { 427 var subresource = frameTreePayload.resources[i]; 428 var resource = this._createResourceFromFramePayload(framePayload, subresource.url, WebInspector.resourceTypes[subresource.type], subresource.mimeType); 429 frame.addResource(resource); 430 } 431 }, 432 433 /** 434 * @param {!PageAgent.Frame} frame 435 * @param {string} url 436 * @param {!WebInspector.ResourceType} type 437 * @param {string} mimeType 438 * @return {!WebInspector.Resource} 439 */ 440 _createResourceFromFramePayload: function(frame, url, type, mimeType) 441 { 442 return new WebInspector.Resource(null, url, frame.url, frame.id, frame.loaderId, type, mimeType); 443 }, 444 445 /** 446 * @param {boolean=} ignoreCache 447 * @param {string=} scriptToEvaluateOnLoad 448 * @param {string=} scriptPreprocessor 449 */ 450 reloadPage: function(ignoreCache, scriptToEvaluateOnLoad, scriptPreprocessor) 451 { 452 this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillReloadPage); 453 PageAgent.reload(ignoreCache, scriptToEvaluateOnLoad, scriptPreprocessor); 454 }, 455 456 __proto__: WebInspector.Object.prototype 457 } 458 459 /** 460 * @constructor 461 * @param {!WebInspector.ResourceTreeModel} model 462 * @param {?WebInspector.ResourceTreeFrame} parentFrame 463 * @param {!PageAgent.FrameId} frameId 464 * @param {!PageAgent.Frame=} payload 465 */ 466 WebInspector.ResourceTreeFrame = function(model, parentFrame, frameId, payload) 467 { 468 this._model = model; 469 this._parentFrame = parentFrame; 470 this._id = frameId; 471 this._url = ""; 472 473 if (payload) { 474 this._loaderId = payload.loaderId; 475 this._name = payload.name; 476 this._url = payload.url; 477 this._securityOrigin = payload.securityOrigin; 478 this._mimeType = payload.mimeType; 479 } 480 481 /** 482 * @type {!Array.<!WebInspector.ResourceTreeFrame>} 483 */ 484 this._childFrames = []; 485 486 /** 487 * @type {!Object.<string, !WebInspector.Resource>} 488 */ 489 this._resourcesMap = {}; 490 491 if (this._parentFrame) 492 this._parentFrame._childFrames.push(this); 493 } 494 495 WebInspector.ResourceTreeFrame.prototype = { 496 /** 497 * @return {string} 498 */ 499 get id() 500 { 501 return this._id; 502 }, 503 504 /** 505 * @return {string} 506 */ 507 get name() 508 { 509 return this._name || ""; 510 }, 511 512 /** 513 * @return {string} 514 */ 515 get url() 516 { 517 return this._url; 518 }, 519 520 /** 521 * @return {string} 522 */ 523 get securityOrigin() 524 { 525 return this._securityOrigin; 526 }, 527 528 /** 529 * @return {string} 530 */ 531 get loaderId() 532 { 533 return this._loaderId; 534 }, 535 536 /** 537 * @return {?WebInspector.ResourceTreeFrame} 538 */ 539 get parentFrame() 540 { 541 return this._parentFrame; 542 }, 543 544 /** 545 * @return {!Array.<!WebInspector.ResourceTreeFrame>} 546 */ 547 get childFrames() 548 { 549 return this._childFrames; 550 }, 551 552 /** 553 * @return {boolean} 554 */ 555 isMainFrame: function() 556 { 557 return !this._parentFrame; 558 }, 559 560 /** 561 * @param {!PageAgent.Frame} framePayload 562 */ 563 _navigate: function(framePayload) 564 { 565 this._loaderId = framePayload.loaderId; 566 this._name = framePayload.name; 567 this._url = framePayload.url; 568 this._securityOrigin = framePayload.securityOrigin; 569 this._mimeType = framePayload.mimeType; 570 571 var mainResource = this._resourcesMap[this._url]; 572 this._resourcesMap = {}; 573 this._removeChildFrames(); 574 if (mainResource && mainResource.loaderId === this._loaderId) 575 this.addResource(mainResource); 576 }, 577 578 /** 579 * @return {!WebInspector.Resource} 580 */ 581 get mainResource() 582 { 583 return this._resourcesMap[this._url]; 584 }, 585 586 /** 587 * @param {!WebInspector.ResourceTreeFrame} frame 588 */ 589 _removeChildFrame: function(frame) 590 { 591 this._childFrames.remove(frame); 592 frame._remove(); 593 }, 594 595 _removeChildFrames: function() 596 { 597 var frames = this._childFrames; 598 this._childFrames = []; 599 for (var i = 0; i < frames.length; ++i) 600 frames[i]._remove(); 601 }, 602 603 _remove: function() 604 { 605 this._removeChildFrames(); 606 delete this._model._frames[this.id]; 607 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this); 608 }, 609 610 /** 611 * @param {!WebInspector.Resource} resource 612 */ 613 addResource: function(resource) 614 { 615 if (this._resourcesMap[resource.url] === resource) { 616 // Already in the tree, we just got an extra update. 617 return; 618 } 619 this._resourcesMap[resource.url] = resource; 620 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); 621 }, 622 623 /** 624 * @param {!WebInspector.NetworkRequest} request 625 * @return {!WebInspector.Resource} 626 */ 627 _addRequest: function(request) 628 { 629 var resource = this._resourcesMap[request.url]; 630 if (resource && resource.request === request) { 631 // Already in the tree, we just got an extra update. 632 return resource; 633 } 634 resource = new WebInspector.Resource(request, request.url, request.documentURL, request.frameId, request.loaderId, request.type, request.mimeType); 635 this._resourcesMap[resource.url] = resource; 636 this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource); 637 return resource; 638 }, 639 640 /** 641 * @return {!Array.<!WebInspector.Resource>} 642 */ 643 resources: function() 644 { 645 var result = []; 646 for (var url in this._resourcesMap) 647 result.push(this._resourcesMap[url]); 648 return result; 649 }, 650 651 /** 652 * @param {string} url 653 * @return {?WebInspector.Resource} 654 */ 655 resourceForURL: function(url) 656 { 657 var result; 658 function filter(resource) 659 { 660 if (resource.url === url) { 661 result = resource; 662 return true; 663 } 664 } 665 this._callForFrameResources(filter); 666 return result; 667 }, 668 669 /** 670 * @param {function(!WebInspector.Resource)} callback 671 * @return {boolean} 672 */ 673 _callForFrameResources: function(callback) 674 { 675 for (var url in this._resourcesMap) { 676 if (callback(this._resourcesMap[url])) 677 return true; 678 } 679 680 for (var i = 0; i < this._childFrames.length; ++i) { 681 if (this._childFrames[i]._callForFrameResources(callback)) 682 return true; 683 } 684 return false; 685 } 686 } 687 688 /** 689 * @constructor 690 * @implements {PageAgent.Dispatcher} 691 */ 692 WebInspector.PageDispatcher = function(resourceTreeModel) 693 { 694 this._resourceTreeModel = resourceTreeModel; 695 } 696 697 WebInspector.PageDispatcher.prototype = { 698 domContentEventFired: function(time) 699 { 700 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time); 701 }, 702 703 loadEventFired: function(time) 704 { 705 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.Load, time); 706 }, 707 708 frameAttached: function(frameId, parentFrameId) 709 { 710 this._resourceTreeModel._frameAttached(frameId, parentFrameId); 711 }, 712 713 frameNavigated: function(frame) 714 { 715 this._resourceTreeModel._frameNavigated(frame); 716 }, 717 718 frameDetached: function(frameId) 719 { 720 this._resourceTreeModel._frameDetached(frameId); 721 }, 722 723 frameStartedLoading: function(frameId) 724 { 725 }, 726 727 frameStoppedLoading: function(frameId) 728 { 729 }, 730 731 frameScheduledNavigation: function(frameId, delay) 732 { 733 }, 734 735 frameClearedScheduledNavigation: function(frameId) 736 { 737 }, 738 739 frameResized: function() 740 { 741 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameResized, null); 742 }, 743 744 javascriptDialogOpening: function(message) 745 { 746 }, 747 748 javascriptDialogClosed: function() 749 { 750 }, 751 752 scriptsEnabled: function(isEnabled) 753 { 754 WebInspector.settings.javaScriptDisabled.set(!isEnabled); 755 }, 756 757 /** 758 * @param {string} data 759 * @param {!PageAgent.ScreencastFrameMetadata=} metadata 760 */ 761 screencastFrame: function(data, metadata) 762 { 763 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastFrame, {data:data, metadata:metadata}); 764 }, 765 766 /** 767 * @param {boolean} visible 768 */ 769 screencastVisibilityChanged: function(visible) 770 { 771 this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastVisibilityChanged, {visible:visible}); 772 } 773 } 774 775 /** 776 * @type {!WebInspector.ResourceTreeModel} 777 */ 778 WebInspector.resourceTreeModel; 779