ResourceTreeModel.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. export default class ResourceTreeModel extends SDK.SDKModel{constructor(target){super(target);const networkManager=target.model(SDK.NetworkManager);if(networkManager){networkManager.addEventListener(SDK.NetworkManager.Events.RequestFinished,this._onRequestFinished,this);networkManager.addEventListener(SDK.NetworkManager.Events.RequestUpdateDropped,this._onRequestUpdateDropped,this);}
  2. this._agent=target.pageAgent();this._agent.enable();this._securityOriginManager=target.model(SDK.SecurityOriginManager);target.registerPageDispatcher(new SDK.PageDispatcher(this));this._frames=new Map();this._cachedResourcesProcessed=false;this._pendingReloadOptions=null;this._reloadSuspensionCount=0;this._isInterstitialShowing=false;this.mainFrame=null;this._agent.getResourceTree().then(this._processCachedResources.bind(this));}
  3. static frameForRequest(request){const networkManager=SDK.NetworkManager.forRequest(request);const resourceTreeModel=networkManager?networkManager.target().model(ResourceTreeModel):null;if(!resourceTreeModel){return null;}
  4. return resourceTreeModel.frameForId(request.frameId);}
  5. static frames(){let result=[];for(const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)){result=result.concat(resourceTreeModel._frames.valuesArray());}
  6. return result;}
  7. static resourceForURL(url){for(const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)){const mainFrame=resourceTreeModel.mainFrame;const result=mainFrame?mainFrame.resourceForURL(url):null;if(result){return result;}}
  8. return null;}
  9. static reloadAllPages(bypassCache,scriptToEvaluateOnLoad){for(const resourceTreeModel of SDK.targetManager.models(ResourceTreeModel)){if(!resourceTreeModel.target().parentTarget()){resourceTreeModel.reloadPage(bypassCache,scriptToEvaluateOnLoad);}}}
  10. domModel(){return(this.target().model(SDK.DOMModel));}
  11. _processCachedResources(mainFramePayload){if(mainFramePayload){this.dispatchEventToListeners(Events.WillLoadCachedResources);this._addFramesRecursively(null,mainFramePayload);this.target().setInspectedURL(mainFramePayload.frame.url);}
  12. this._cachedResourcesProcessed=true;const runtimeModel=this.target().model(SDK.RuntimeModel);if(runtimeModel){runtimeModel.setExecutionContextComparator(this._executionContextComparator.bind(this));runtimeModel.fireExecutionContextOrderChanged();}
  13. this.dispatchEventToListeners(Events.CachedResourcesLoaded,this);}
  14. cachedResourcesLoaded(){return this._cachedResourcesProcessed;}
  15. isInterstitialShowing(){return this._isInterstitialShowing;}
  16. _addFrame(frame,aboutToNavigate){this._frames.set(frame.id,frame);if(frame.isMainFrame()){this.mainFrame=frame;}
  17. this.dispatchEventToListeners(Events.FrameAdded,frame);this._updateSecurityOrigins();}
  18. _frameAttached(frameId,parentFrameId,stackTrace){const parentFrame=parentFrameId?(this._frames.get(parentFrameId)||null):null;if(!this._cachedResourcesProcessed&&parentFrame){return null;}
  19. if(this._frames.has(frameId)){return null;}
  20. const frame=new ResourceTreeFrame(this,parentFrame,frameId,null,stackTrace||null);if(parentFrameId&&!parentFrame){frame._crossTargetParentFrameId=parentFrameId;}
  21. if(frame.isMainFrame()&&this.mainFrame){this._frameDetached(this.mainFrame.id);}
  22. this._addFrame(frame,true);return frame;}
  23. _frameNavigated(framePayload){const parentFrame=framePayload.parentId?(this._frames.get(framePayload.parentId)||null):null;if(!this._cachedResourcesProcessed&&parentFrame){return;}
  24. let frame=this._frames.get(framePayload.id);if(!frame){frame=this._frameAttached(framePayload.id,framePayload.parentId||'');console.assert(frame);}
  25. this.dispatchEventToListeners(Events.FrameWillNavigate,frame);frame._navigate(framePayload);this.dispatchEventToListeners(Events.FrameNavigated,frame);if(frame.isMainFrame()){this.dispatchEventToListeners(Events.MainFrameNavigated,frame);}
  26. const resources=frame.resources();for(let i=0;i<resources.length;++i){this.dispatchEventToListeners(Events.ResourceAdded,resources[i]);}
  27. if(frame.isMainFrame()){this.target().setInspectedURL(frame.url);}
  28. this._updateSecurityOrigins();}
  29. _frameDetached(frameId){if(!this._cachedResourcesProcessed){return;}
  30. const frame=this._frames.get(frameId);if(!frame){return;}
  31. if(frame.parentFrame){frame.parentFrame._removeChildFrame(frame);}else{frame._remove();}
  32. this._updateSecurityOrigins();}
  33. _onRequestFinished(event){if(!this._cachedResourcesProcessed){return;}
  34. const request=(event.data);if(request.failed||request.resourceType()===Common.resourceTypes.XHR){return;}
  35. const frame=this._frames.get(request.frameId);if(frame){frame._addRequest(request);}}
  36. _onRequestUpdateDropped(event){if(!this._cachedResourcesProcessed){return;}
  37. const frameId=event.data.frameId;const frame=this._frames.get(frameId);if(!frame){return;}
  38. const url=event.data.url;if(frame._resourcesMap[url]){return;}
  39. const resource=new SDK.Resource(this,null,url,frame.url,frameId,event.data.loaderId,Common.resourceTypes[event.data.resourceType],event.data.mimeType,event.data.lastModified,null);frame.addResource(resource);}
  40. frameForId(frameId){return this._frames.get(frameId);}
  41. forAllResources(callback){if(this.mainFrame){return this.mainFrame._callForFrameResources(callback);}
  42. return false;}
  43. frames(){return this._frames.valuesArray();}
  44. resourceForURL(url){return this.mainFrame?this.mainFrame.resourceForURL(url):null;}
  45. _addFramesRecursively(parentFrame,frameTreePayload){const framePayload=frameTreePayload.frame;const frame=new ResourceTreeFrame(this,parentFrame,framePayload.id,framePayload,null);if(!parentFrame&&framePayload.parentId){frame._crossTargetParentFrameId=framePayload.parentId;}
  46. this._addFrame(frame);for(let i=0;frameTreePayload.childFrames&&i<frameTreePayload.childFrames.length;++i){this._addFramesRecursively(frame,frameTreePayload.childFrames[i]);}
  47. for(let i=0;i<frameTreePayload.resources.length;++i){const subresource=frameTreePayload.resources[i];const resource=this._createResourceFromFramePayload(framePayload,subresource.url,Common.resourceTypes[subresource.type],subresource.mimeType,subresource.lastModified||null,subresource.contentSize||null);frame.addResource(resource);}
  48. if(!frame._resourcesMap[framePayload.url]){const frameResource=this._createResourceFromFramePayload(framePayload,framePayload.url,Common.resourceTypes.Document,framePayload.mimeType,null,null);frame.addResource(frameResource);}}
  49. _createResourceFromFramePayload(frame,url,type,mimeType,lastModifiedTime,contentSize){const lastModified=typeof lastModifiedTime==='number'?new Date(lastModifiedTime*1000):null;return new SDK.Resource(this,null,url,frame.url,frame.id,frame.loaderId,type,mimeType,lastModified,contentSize);}
  50. suspendReload(){this._reloadSuspensionCount++;}
  51. resumeReload(){this._reloadSuspensionCount--;console.assert(this._reloadSuspensionCount>=0,'Unbalanced call to ResourceTreeModel.resumeReload()');if(!this._reloadSuspensionCount&&this._pendingReloadOptions){this.reloadPage.apply(this,this._pendingReloadOptions);}}
  52. reloadPage(bypassCache,scriptToEvaluateOnLoad){if(!this._pendingReloadOptions){this.dispatchEventToListeners(Events.PageReloadRequested,this);}
  53. if(this._reloadSuspensionCount){this._pendingReloadOptions=[bypassCache,scriptToEvaluateOnLoad];return;}
  54. this._pendingReloadOptions=null;this.dispatchEventToListeners(Events.WillReloadPage);this._agent.reload(bypassCache,scriptToEvaluateOnLoad);}
  55. navigate(url){return this._agent.navigate(url);}
  56. async navigationHistory(){const response=await this._agent.invoke_getNavigationHistory({});if(response[Protocol.Error]){return null;}
  57. return{currentIndex:response.currentIndex,entries:response.entries};}
  58. navigateToHistoryEntry(entry){this._agent.navigateToHistoryEntry(entry.id);}
  59. async fetchAppManifest(){const response=await this._agent.invoke_getAppManifest({});if(response[Protocol.Error]){return{url:response.url,data:null,errors:[]};}
  60. return{url:response.url,data:response.data||null,errors:response.errors};}
  61. async getInstallabilityErrors(){const response=await this._agent.invoke_getInstallabilityErrors({});return response.errors||[];}
  62. _executionContextComparator(a,b){function framePath(frame){let currentFrame=frame;const parents=[];while(currentFrame){parents.push(currentFrame);currentFrame=currentFrame.parentFrame;}
  63. return parents.reverse();}
  64. if(a.target()!==b.target()){return SDK.ExecutionContext.comparator(a,b);}
  65. const framesA=a.frameId?framePath(this.frameForId(a.frameId)):[];const framesB=b.frameId?framePath(this.frameForId(b.frameId)):[];let frameA;let frameB;for(let i=0;;i++){if(!framesA[i]||!framesB[i]||(framesA[i]!==framesB[i])){frameA=framesA[i];frameB=framesB[i];break;}}
  66. if(!frameA&&frameB){return-1;}
  67. if(!frameB&&frameA){return 1;}
  68. if(frameA&&frameB){return frameA.id.localeCompare(frameB.id);}
  69. return SDK.ExecutionContext.comparator(a,b);}
  70. _getSecurityOriginData(){const securityOrigins=new Set();let mainSecurityOrigin=null;let unreachableMainSecurityOrigin=null;for(const frame of this._frames.values()){const origin=frame.securityOrigin;if(!origin){continue;}
  71. securityOrigins.add(origin);if(frame.isMainFrame()){mainSecurityOrigin=origin;if(frame.unreachableUrl()){const unreachableParsed=new Common.ParsedURL(frame.unreachableUrl());unreachableMainSecurityOrigin=unreachableParsed.securityOrigin();}}}
  72. return{securityOrigins:securityOrigins,mainSecurityOrigin:mainSecurityOrigin,unreachableMainSecurityOrigin:unreachableMainSecurityOrigin};}
  73. _updateSecurityOrigins(){const data=this._getSecurityOriginData();this._securityOriginManager.setMainSecurityOrigin(data.mainSecurityOrigin||'',data.unreachableMainSecurityOrigin||'');this._securityOriginManager.updateSecurityOrigins(data.securityOrigins);}
  74. getMainSecurityOrigin(){const data=this._getSecurityOriginData();return data.mainSecurityOrigin||data.unreachableMainSecurityOrigin;}}
  75. export const Events={FrameAdded:Symbol('FrameAdded'),FrameNavigated:Symbol('FrameNavigated'),FrameDetached:Symbol('FrameDetached'),FrameResized:Symbol('FrameResized'),FrameWillNavigate:Symbol('FrameWillNavigate'),MainFrameNavigated:Symbol('MainFrameNavigated'),ResourceAdded:Symbol('ResourceAdded'),WillLoadCachedResources:Symbol('WillLoadCachedResources'),CachedResourcesLoaded:Symbol('CachedResourcesLoaded'),DOMContentLoaded:Symbol('DOMContentLoaded'),LifecycleEvent:Symbol('LifecycleEvent'),Load:Symbol('Load'),PageReloadRequested:Symbol('PageReloadRequested'),WillReloadPage:Symbol('WillReloadPage'),InterstitialShown:Symbol('InterstitialShown'),InterstitialHidden:Symbol('InterstitialHidden')};export class ResourceTreeFrame{constructor(model,parentFrame,frameId,payload,creationStackTrace){this._model=model;this._parentFrame=parentFrame;this._id=frameId;this._url='';this._crossTargetParentFrameId=null;if(payload){this._loaderId=payload.loaderId;this._name=payload.name;this._url=payload.url;this._securityOrigin=payload.securityOrigin;this._mimeType=payload.mimeType;this._unreachableUrl=payload.unreachableUrl||'';}
  76. this._creationStackTrace=creationStackTrace;this._childFrames=[];this._resourcesMap={};if(this._parentFrame){this._parentFrame._childFrames.push(this);}}
  77. _navigate(framePayload){this._loaderId=framePayload.loaderId;this._name=framePayload.name;this._url=framePayload.url;this._securityOrigin=framePayload.securityOrigin;this._mimeType=framePayload.mimeType;this._unreachableUrl=framePayload.unreachableUrl||'';const mainResource=this._resourcesMap[this._url];this._resourcesMap={};this._removeChildFrames();if(mainResource&&mainResource.loaderId===this._loaderId){this.addResource(mainResource);}}
  78. resourceTreeModel(){return this._model;}
  79. get id(){return this._id;}
  80. get name(){return this._name||'';}
  81. get url(){return this._url;}
  82. get securityOrigin(){return this._securityOrigin;}
  83. unreachableUrl(){return this._unreachableUrl;}
  84. get loaderId(){return this._loaderId;}
  85. get parentFrame(){return this._parentFrame;}
  86. get childFrames(){return this._childFrames;}
  87. crossTargetParentFrame(){if(!this._crossTargetParentFrameId){return null;}
  88. if(!this._model.target().parentTarget()){return null;}
  89. const parentModel=this._model.target().parentTarget().model(ResourceTreeModel);if(!parentModel){return null;}
  90. return parentModel._frames.get(this._crossTargetParentFrameId)||null;}
  91. findCreationCallFrame(searchFn){let stackTrace=this._creationStackTrace;while(stackTrace){const foundEntry=stackTrace.callFrames.find(searchFn);if(foundEntry){return foundEntry;}
  92. stackTrace=this.parent;}
  93. return null;}
  94. isMainFrame(){return!this._parentFrame;}
  95. isTopFrame(){return!this._parentFrame&&!this._crossTargetParentFrameId;}
  96. get mainResource(){return this._resourcesMap[this._url];}
  97. _removeChildFrame(frame){this._childFrames.remove(frame);frame._remove();}
  98. _removeChildFrames(){const frames=this._childFrames;this._childFrames=[];for(let i=0;i<frames.length;++i){frames[i]._remove();}}
  99. _remove(){this._removeChildFrames();this._model._frames.delete(this.id);this._model.dispatchEventToListeners(Events.FrameDetached,this);}
  100. addResource(resource){if(this._resourcesMap[resource.url]===resource){return;}
  101. this._resourcesMap[resource.url]=resource;this._model.dispatchEventToListeners(Events.ResourceAdded,resource);}
  102. _addRequest(request){let resource=this._resourcesMap[request.url()];if(resource&&resource.request===request){return;}
  103. resource=new SDK.Resource(this._model,request,request.url(),request.documentURL,request.frameId,request.loaderId,request.resourceType(),request.mimeType,null,null);this._resourcesMap[resource.url]=resource;this._model.dispatchEventToListeners(Events.ResourceAdded,resource);}
  104. resources(){const result=[];for(const url in this._resourcesMap){result.push(this._resourcesMap[url]);}
  105. return result;}
  106. resourceForURL(url){let resource=this._resourcesMap[url]||null;if(resource){return resource;}
  107. for(let i=0;!resource&&i<this._childFrames.length;++i){resource=this._childFrames[i].resourceForURL(url);}
  108. return resource;}
  109. _callForFrameResources(callback){for(const url in this._resourcesMap){if(callback(this._resourcesMap[url])){return true;}}
  110. for(let i=0;i<this._childFrames.length;++i){if(this._childFrames[i]._callForFrameResources(callback)){return true;}}
  111. return false;}
  112. displayName(){if(this.isTopFrame()){return Common.UIString('top');}
  113. const subtitle=new Common.ParsedURL(this._url).displayName;if(subtitle){if(!this._name){return subtitle;}
  114. return this._name+' ('+subtitle+')';}
  115. return Common.UIString('<iframe>');}}
  116. export class PageDispatcher{constructor(resourceTreeModel){this._resourceTreeModel=resourceTreeModel;}
  117. domContentEventFired(time){this._resourceTreeModel.dispatchEventToListeners(Events.DOMContentLoaded,time);}
  118. loadEventFired(time){this._resourceTreeModel.dispatchEventToListeners(Events.Load,{resourceTreeModel:this._resourceTreeModel,loadTime:time});}
  119. lifecycleEvent(frameId,loaderId,name,time){this._resourceTreeModel.dispatchEventToListeners(Events.LifecycleEvent,{frameId,name});}
  120. frameAttached(frameId,parentFrameId,stackTrace){this._resourceTreeModel._frameAttached(frameId,parentFrameId,stackTrace);}
  121. frameNavigated(frame){this._resourceTreeModel._frameNavigated(frame);}
  122. frameDetached(frameId){this._resourceTreeModel._frameDetached(frameId);}
  123. frameStartedLoading(frameId){}
  124. frameStoppedLoading(frameId){}
  125. frameRequestedNavigation(frameId){}
  126. frameScheduledNavigation(frameId,delay){}
  127. frameClearedScheduledNavigation(frameId){}
  128. navigatedWithinDocument(frameId,url){}
  129. frameResized(){this._resourceTreeModel.dispatchEventToListeners(Events.FrameResized,null);}
  130. javascriptDialogOpening(url,message,dialogType,hasBrowserHandler,prompt){if(!hasBrowserHandler){this._resourceTreeModel._agent.handleJavaScriptDialog(false);}}
  131. javascriptDialogClosed(result,userInput){}
  132. screencastFrame(data,metadata,sessionId){}
  133. screencastVisibilityChanged(visible){}
  134. interstitialShown(){this._resourceTreeModel._isInterstitialShowing=true;this._resourceTreeModel.dispatchEventToListeners(Events.InterstitialShown);}
  135. interstitialHidden(){this._resourceTreeModel._isInterstitialShowing=false;this._resourceTreeModel.dispatchEventToListeners(Events.InterstitialHidden);}
  136. windowOpen(url,windowName,windowFeatures,userGesture){}
  137. compilationCacheProduced(url,data){}
  138. fileChooserOpened(mode){}
  139. downloadWillBegin(frameId,url){}}
  140. self.SDK=self.SDK||{};SDK=SDK||{};SDK.ResourceTreeModel=ResourceTreeModel;SDK.ResourceTreeModel.Events=Events;SDK.ResourceTreeFrame=ResourceTreeFrame;SDK.PageDispatcher=PageDispatcher;SDK.ResourceTreeModel.SecurityOriginData;SDK.SDKModel.register(ResourceTreeModel,SDK.Target.Capability.DOM,true);