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