Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / ResourceTreeModel.js
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     /**
100      * @return {boolean}
101      */
102     cachedResourcesLoaded: function()
103     {
104         return this._cachedResourcesProcessed;
105     },
106
107     _dispatchInspectedURLChanged: function()
108     {
109         InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL);
110         this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL);
111     },
112
113     /**
114      * @param {!WebInspector.ResourceTreeFrame} frame
115      * @param {boolean=} aboutToNavigate
116      */
117     _addFrame: function(frame, aboutToNavigate)
118     {
119         this._frames[frame.id] = frame;
120         if (frame.isMainFrame())
121             this.mainFrame = frame;
122         this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame);
123         if (!aboutToNavigate)
124             this._addSecurityOrigin(frame.securityOrigin);
125         if (frame.isMainFrame())
126             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameCreatedOrNavigated, frame);
127     },
128
129     /**
130      * @param {string} securityOrigin
131      */
132     _addSecurityOrigin: function(securityOrigin)
133     {
134         if (!this._securityOriginFrameCount[securityOrigin]) {
135             this._securityOriginFrameCount[securityOrigin] = 1;
136             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginAdded, securityOrigin);
137             return;
138         }
139         this._securityOriginFrameCount[securityOrigin] += 1;
140     },
141
142     /**
143      * @param {string|undefined} securityOrigin
144      */
145     _removeSecurityOrigin: function(securityOrigin)
146     {
147         if (typeof securityOrigin === "undefined")
148             return;
149         if (this._securityOriginFrameCount[securityOrigin] === 1) {
150             delete this._securityOriginFrameCount[securityOrigin];
151             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.SecurityOriginRemoved, securityOrigin);
152             return;
153         }
154         this._securityOriginFrameCount[securityOrigin] -= 1;
155     },
156
157     /**
158      * @return {!Array.<string>}
159      */
160     securityOrigins: function()
161     {
162         return Object.keys(this._securityOriginFrameCount);
163     },
164
165     /**
166      * @param {!WebInspector.ResourceTreeFrame} mainFrame
167      */
168     _handleMainFrameDetached: function(mainFrame)
169     {
170         /**
171          * @param {!WebInspector.ResourceTreeFrame} frame
172          * @this {WebInspector.ResourceTreeModel}
173          */
174         function removeOriginForFrame(frame)
175         {
176             for (var i = 0; i < frame.childFrames.length; ++i)
177                 removeOriginForFrame.call(this, frame.childFrames[i]);
178             if (!frame.isMainFrame())
179                 this._removeSecurityOrigin(frame.securityOrigin);
180         }
181         removeOriginForFrame.call(this, WebInspector.resourceTreeModel.mainFrame);
182     },
183
184     /**
185      * @param {!PageAgent.FrameId} frameId
186      * @param {?PageAgent.FrameId} parentFrameId
187      * @return {?WebInspector.ResourceTreeFrame}
188      */
189     _frameAttached: function(frameId, parentFrameId)
190     {
191         // Do nothing unless cached resource tree is processed - it will overwrite everything.
192         if (!this._cachedResourcesProcessed)
193             return null;
194         if (this._frames[frameId])
195             return null;
196
197         var parentFrame = parentFrameId ? this._frames[parentFrameId] : null;
198         var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, frameId);
199         if (frame.isMainFrame() && this.mainFrame) {
200             this._handleMainFrameDetached(this.mainFrame);
201             // Navigation to the new backend process.
202             this._frameDetached(this.mainFrame.id);
203         }
204         this._addFrame(frame, true);
205         return frame;
206     },
207
208     /**
209      * @param {!PageAgent.Frame} framePayload
210      */
211     _frameNavigated: function(framePayload)
212     {
213         // Do nothing unless cached resource tree is processed - it will overwrite everything.
214         if (!this._cachedResourcesProcessed)
215             return;
216         var frame = this._frames[framePayload.id];
217         if (!frame) {
218             // Simulate missed "frameAttached" for a main frame navigation to the new backend process.
219             console.assert(!framePayload.parentId, "Main frame shouldn't have parent frame id.");
220             frame = this._frameAttached(framePayload.id, framePayload.parentId || "");
221             console.assert(frame);
222         }
223         this._removeSecurityOrigin(frame.securityOrigin);
224         frame._navigate(framePayload);
225         var addedOrigin = frame.securityOrigin;
226
227         if (frame.isMainFrame())
228             WebInspector.inspectedPageURL = frame.url;
229
230         this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame);
231         if (frame.isMainFrame()) {
232             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame);
233             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameCreatedOrNavigated, frame);
234         }
235         if (addedOrigin)
236             this._addSecurityOrigin(addedOrigin);
237
238         // Fill frame with retained resources (the ones loaded using new loader).
239         var resources = frame.resources();
240         for (var i = 0; i < resources.length; ++i)
241             this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]);
242
243         if (frame.isMainFrame())
244             this._dispatchInspectedURLChanged();
245     },
246
247     /**
248      * @param {!PageAgent.FrameId} frameId
249      */
250     _frameDetached: function(frameId)
251     {
252         // Do nothing unless cached resource tree is processed - it will overwrite everything.
253         if (!this._cachedResourcesProcessed)
254             return;
255
256         var frame = this._frames[frameId];
257         if (!frame)
258             return;
259
260         this._removeSecurityOrigin(frame.securityOrigin);
261         if (frame.parentFrame)
262             frame.parentFrame._removeChildFrame(frame);
263         else
264             frame._remove();
265     },
266
267     /**
268      * @param {!WebInspector.Event} event
269      */
270     _onRequestFinished: function(event)
271     {
272         if (!this._cachedResourcesProcessed)
273             return;
274
275         var request = /** @type {!WebInspector.NetworkRequest} */ (event.data);
276         if (request.failed || request.type === WebInspector.resourceTypes.XHR)
277             return;
278
279         var frame = this._frames[request.frameId];
280         if (frame) {
281             var resource = frame._addRequest(request);
282             this._addPendingConsoleMessagesToResource(resource);
283         }
284     },
285
286     /**
287      * @param {!WebInspector.Event} event
288      */
289     _onRequestUpdateDropped: function(event)
290     {
291         if (!this._cachedResourcesProcessed)
292             return;
293
294         var frameId = event.data.frameId;
295         var frame = this._frames[frameId];
296         if (!frame)
297             return;
298
299         var url = event.data.url;
300         if (frame._resourcesMap[url])
301             return;
302
303         var resource = new WebInspector.Resource(null, url, frame.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType);
304         frame.addResource(resource);
305     },
306
307     /**
308      * @param {!PageAgent.FrameId} frameId
309      * @return {!WebInspector.ResourceTreeFrame}
310      */
311     frameForId: function(frameId)
312     {
313         return this._frames[frameId];
314     },
315
316     /**
317      * @param {function(!WebInspector.Resource)} callback
318      * @return {boolean}
319      */
320     forAllResources: function(callback)
321     {
322         if (this.mainFrame)
323             return this.mainFrame._callForFrameResources(callback);
324         return false;
325     },
326
327     /**
328      * @return {!Array.<!WebInspector.ResourceTreeFrame>}
329      */
330     frames: function()
331     {
332         return Object.values(this._frames);
333     },
334
335     /**
336      * @param {!WebInspector.Event} event
337      */
338     _consoleMessageAdded: function(event)
339     {
340         var msg = /** @type {!WebInspector.ConsoleMessage} */ (event.data);
341         var resource = msg.url ? this.resourceForURL(msg.url) : null;
342         if (resource)
343             this._addConsoleMessageToResource(msg, resource);
344         else
345             this._addPendingConsoleMessage(msg);
346     },
347
348     /**
349      * @param {!WebInspector.ConsoleMessage} msg
350      */
351     _addPendingConsoleMessage: function(msg)
352     {
353         if (!msg.url)
354             return;
355         if (!this._pendingConsoleMessages[msg.url])
356             this._pendingConsoleMessages[msg.url] = [];
357         this._pendingConsoleMessages[msg.url].push(msg);
358     },
359
360     /**
361      * @param {!WebInspector.Resource} resource
362      */
363     _addPendingConsoleMessagesToResource: function(resource)
364     {
365         var messages = this._pendingConsoleMessages[resource.url];
366         if (messages) {
367             for (var i = 0; i < messages.length; i++)
368                 this._addConsoleMessageToResource(messages[i], resource);
369             delete this._pendingConsoleMessages[resource.url];
370         }
371     },
372
373     /**
374      * @param {!WebInspector.ConsoleMessage} msg
375      * @param {!WebInspector.Resource} resource
376      */
377     _addConsoleMessageToResource: function(msg, resource)
378     {
379         switch (msg.level) {
380         case WebInspector.ConsoleMessage.MessageLevel.Warning:
381             resource.warnings += msg.repeatDelta;
382             break;
383         case WebInspector.ConsoleMessage.MessageLevel.Error:
384             resource.errors += msg.repeatDelta;
385             break;
386         }
387         resource.addMessage(msg);
388     },
389
390     _consoleCleared: function()
391     {
392         function callback(resource)
393         {
394             resource.clearErrorsAndWarnings();
395         }
396
397         this._pendingConsoleMessages = {};
398         this.forAllResources(callback);
399     },
400
401     /**
402      * @param {string} url
403      * @return {?WebInspector.Resource}
404      */
405     resourceForURL: function(url)
406     {
407         // Workers call into this with no frames available.
408         return this.mainFrame ? this.mainFrame.resourceForURL(url) : null;
409     },
410
411     /**
412      * @param {?WebInspector.ResourceTreeFrame} parentFrame
413      * @param {!PageAgent.FrameResourceTree} frameTreePayload
414      */
415     _addFramesRecursively: function(parentFrame, frameTreePayload)
416     {
417         var framePayload = frameTreePayload.frame;
418         var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload.id, framePayload);
419         this._addFrame(frame);
420
421         var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url, WebInspector.resourceTypes.Document, framePayload.mimeType);
422         if (frame.isMainFrame())
423             WebInspector.inspectedPageURL = frameResource.url;
424         frame.addResource(frameResource);
425
426         for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
427             this._addFramesRecursively(frame, frameTreePayload.childFrames[i]);
428
429         for (var i = 0; i < frameTreePayload.resources.length; ++i) {
430             var subresource = frameTreePayload.resources[i];
431             var resource = this._createResourceFromFramePayload(framePayload, subresource.url, WebInspector.resourceTypes[subresource.type], subresource.mimeType);
432             frame.addResource(resource);
433         }
434     },
435
436     /**
437      * @param {!PageAgent.Frame} frame
438      * @param {string} url
439      * @param {!WebInspector.ResourceType} type
440      * @param {string} mimeType
441      * @return {!WebInspector.Resource}
442      */
443     _createResourceFromFramePayload: function(frame, url, type, mimeType)
444     {
445         return new WebInspector.Resource(null, url, frame.url, frame.id, frame.loaderId, type, mimeType);
446     },
447
448     /**
449      * @param {boolean=} ignoreCache
450      * @param {string=} scriptToEvaluateOnLoad
451      * @param {string=} scriptPreprocessor
452      */
453     reloadPage: function(ignoreCache, scriptToEvaluateOnLoad, scriptPreprocessor)
454     {
455         this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillReloadPage);
456         PageAgent.reload(ignoreCache, scriptToEvaluateOnLoad, scriptPreprocessor);
457     },
458
459     __proto__: WebInspector.Object.prototype
460 }
461
462 /**
463  * @constructor
464  * @param {!WebInspector.ResourceTreeModel} model
465  * @param {?WebInspector.ResourceTreeFrame} parentFrame
466  * @param {!PageAgent.FrameId} frameId
467  * @param {!PageAgent.Frame=} payload
468  */
469 WebInspector.ResourceTreeFrame = function(model, parentFrame, frameId, payload)
470 {
471     this._model = model;
472     this._parentFrame = parentFrame;
473     this._id = frameId;
474     this._url = "";
475
476     if (payload) {
477         this._loaderId = payload.loaderId;
478         this._name = payload.name;
479         this._url = payload.url;
480         this._securityOrigin = payload.securityOrigin;
481         this._mimeType = payload.mimeType;
482     }
483
484     /**
485      * @type {!Array.<!WebInspector.ResourceTreeFrame>}
486      */
487     this._childFrames = [];
488
489     /**
490      * @type {!Object.<string, !WebInspector.Resource>}
491      */
492     this._resourcesMap = {};
493
494     if (this._parentFrame)
495         this._parentFrame._childFrames.push(this);
496 }
497
498 WebInspector.ResourceTreeFrame.prototype = {
499     /**
500      * @return {string}
501      */
502     get id()
503     {
504         return this._id;
505     },
506
507     /**
508      * @return {string}
509      */
510     get name()
511     {
512         return this._name || "";
513     },
514
515     /**
516      * @return {string}
517      */
518     get url()
519     {
520         return this._url;
521     },
522
523     /**
524      * @return {string}
525      */
526     get securityOrigin()
527     {
528         return this._securityOrigin;
529     },
530
531     /**
532      * @return {string}
533      */
534     get loaderId()
535     {
536         return this._loaderId;
537     },
538
539     /**
540      * @return {?WebInspector.ResourceTreeFrame}
541      */
542     get parentFrame()
543     {
544         return this._parentFrame;
545     },
546
547     /**
548      * @return {!Array.<!WebInspector.ResourceTreeFrame>}
549      */
550     get childFrames()
551     {
552         return this._childFrames;
553     },
554
555     /**
556      * @return {boolean}
557      */
558     isMainFrame: function()
559     {
560         return !this._parentFrame;
561     },
562
563     /**
564      * @param {!PageAgent.Frame} framePayload
565      */
566     _navigate: function(framePayload)
567     {
568         this._loaderId = framePayload.loaderId;
569         this._name = framePayload.name;
570         this._url = framePayload.url;
571         this._securityOrigin = framePayload.securityOrigin;
572         this._mimeType = framePayload.mimeType;
573
574         var mainResource = this._resourcesMap[this._url];
575         this._resourcesMap = {};
576         this._removeChildFrames();
577         if (mainResource && mainResource.loaderId === this._loaderId)
578             this.addResource(mainResource);
579     },
580
581     /**
582      * @return {!WebInspector.Resource}
583      */
584     get mainResource()
585     {
586         return this._resourcesMap[this._url];
587     },
588
589     /**
590      * @param {!WebInspector.ResourceTreeFrame} frame
591      */
592     _removeChildFrame: function(frame)
593     {
594         this._childFrames.remove(frame);
595         frame._remove();
596     },
597
598     _removeChildFrames: function()
599     {
600         var frames = this._childFrames;
601         this._childFrames = [];
602         for (var i = 0; i < frames.length; ++i)
603             frames[i]._remove();
604     },
605
606     _remove: function()
607     {
608         this._removeChildFrames();
609         delete this._model._frames[this.id];
610         this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this);
611     },
612
613     /**
614      * @param {!WebInspector.Resource} resource
615      */
616     addResource: function(resource)
617     {
618         if (this._resourcesMap[resource.url] === resource) {
619             // Already in the tree, we just got an extra update.
620             return;
621         }
622         this._resourcesMap[resource.url] = resource;
623         this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
624     },
625
626     /**
627      * @param {!WebInspector.NetworkRequest} request
628      * @return {!WebInspector.Resource}
629      */
630     _addRequest: function(request)
631     {
632         var resource = this._resourcesMap[request.url];
633         if (resource && resource.request === request) {
634             // Already in the tree, we just got an extra update.
635             return resource;
636         }
637         resource = new WebInspector.Resource(request, request.url, request.documentURL, request.frameId, request.loaderId, request.type, request.mimeType);
638         this._resourcesMap[resource.url] = resource;
639         this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
640         return resource;
641     },
642
643     /**
644      * @return {!Array.<!WebInspector.Resource>}
645      */
646     resources: function()
647     {
648         var result = [];
649         for (var url in this._resourcesMap)
650             result.push(this._resourcesMap[url]);
651         return result;
652     },
653
654     /**
655      * @param {string} url
656      * @return {?WebInspector.Resource}
657      */
658     resourceForURL: function(url)
659     {
660         var result;
661         function filter(resource)
662         {
663             if (resource.url === url) {
664                 result = resource;
665                 return true;
666             }
667         }
668         this._callForFrameResources(filter);
669         return result || null;
670     },
671
672     /**
673      * @param {function(!WebInspector.Resource)} callback
674      * @return {boolean}
675      */
676     _callForFrameResources: function(callback)
677     {
678         for (var url in this._resourcesMap) {
679             if (callback(this._resourcesMap[url]))
680                 return true;
681         }
682
683         for (var i = 0; i < this._childFrames.length; ++i) {
684             if (this._childFrames[i]._callForFrameResources(callback))
685                 return true;
686         }
687         return false;
688     },
689
690     /**
691      * @return {string}
692      */
693     displayName: function()
694     {
695         if (!this._parentFrame)
696             return WebInspector.UIString("<top frame>");
697         var subtitle = new WebInspector.ParsedURL(this._url).displayName;
698         if (subtitle) {
699             if (!this._name)
700                 return subtitle;
701             return this._name + "( " + subtitle + " )";
702         }
703         return WebInspector.UIString("<iframe>");
704     }
705 }
706
707 /**
708  * @constructor
709  * @implements {PageAgent.Dispatcher}
710  */
711 WebInspector.PageDispatcher = function(resourceTreeModel)
712 {
713     this._resourceTreeModel = resourceTreeModel;
714 }
715
716 WebInspector.PageDispatcher.prototype = {
717     domContentEventFired: function(time)
718     {
719         this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time);
720     },
721
722     loadEventFired: function(time)
723     {
724         this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.Load, time);
725     },
726
727     frameAttached: function(frameId, parentFrameId)
728     {
729         this._resourceTreeModel._frameAttached(frameId, parentFrameId);
730     },
731
732     frameNavigated: function(frame)
733     {
734         this._resourceTreeModel._frameNavigated(frame);
735     },
736
737     frameDetached: function(frameId)
738     {
739         this._resourceTreeModel._frameDetached(frameId);
740     },
741
742     frameStartedLoading: function(frameId)
743     {
744     },
745
746     frameStoppedLoading: function(frameId)
747     {
748     },
749
750     frameScheduledNavigation: function(frameId, delay)
751     {
752     },
753
754     frameClearedScheduledNavigation: function(frameId)
755     {
756     },
757
758     frameResized: function()
759     {
760         this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameResized, null);
761     },
762
763     javascriptDialogOpening: function(message)
764     {
765     },
766
767     javascriptDialogClosed: function()
768     {
769     },
770
771     scriptsEnabled: function(isEnabled)
772     {
773         WebInspector.settings.javaScriptDisabled.set(!isEnabled);
774     },
775
776     /**
777      * @param {string} data
778      * @param {!PageAgent.ScreencastFrameMetadata=} metadata
779      */
780     screencastFrame: function(data, metadata)
781     {
782         this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastFrame, {data:data, metadata:metadata});
783     },
784
785     /**
786      * @param {boolean} visible
787      */
788     screencastVisibilityChanged: function(visible)
789     {
790         this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ScreencastVisibilityChanged, {visible:visible});
791     }
792 }
793
794 /**
795  * @type {!WebInspector.ResourceTreeModel}
796  */
797 WebInspector.resourceTreeModel;