OLD | NEW |
1 # Copyright 2016 The Chromium Authors. All rights reserved. | 1 # Copyright 2016 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Gathers and infers dependencies between requests. | 5 """Gathers and infers dependencies between requests. |
6 | 6 |
7 When executed as a script, loads a trace and outputs the dependencies. | 7 When executed as a script, loads a trace and outputs the dependencies. |
8 """ | 8 """ |
9 | 9 |
10 import collections | 10 import collections |
(...skipping 12 matching lines...) Expand all Loading... |
23 def __init__(self, trace): | 23 def __init__(self, trace): |
24 """Initializes an instance of RequestDependencyLens. | 24 """Initializes an instance of RequestDependencyLens. |
25 | 25 |
26 Args: | 26 Args: |
27 trace: (LoadingTrace) Loading trace. | 27 trace: (LoadingTrace) Loading trace. |
28 """ | 28 """ |
29 self.loading_trace = trace | 29 self.loading_trace = trace |
30 self._requests = self.loading_trace.request_track.GetEvents() | 30 self._requests = self.loading_trace.request_track.GetEvents() |
31 self._requests_by_id = {r.request_id: r for r in self._requests} | 31 self._requests_by_id = {r.request_id: r for r in self._requests} |
32 self._requests_by_url = collections.defaultdict(list) | 32 self._requests_by_url = collections.defaultdict(list) |
| 33 self._deps = None |
33 for request in self._requests: | 34 for request in self._requests: |
34 self._requests_by_url[request.url].append(request) | 35 self._requests_by_url[request.url].append(request) |
35 self._frame_to_parent = {} | 36 self._frame_to_parent = {} |
36 for event in self.loading_trace.page_track.GetEvents(): | 37 for event in self.loading_trace.page_track.GetEvents(): |
37 if event['method'] == 'Page.frameAttached': | 38 if event['method'] == 'Page.frameAttached': |
38 self._frame_to_parent[event['frame_id']] = event['parent_frame_id'] | 39 self._frame_to_parent[event['frame_id']] = event['parent_frame_id'] |
39 | 40 |
40 def GetRequestDependencies(self): | 41 def GetRequestDependencies(self): |
41 """Returns a list of request dependencies. | 42 """Returns a list of request dependencies. |
42 | 43 |
43 Returns: | 44 Returns: |
44 [(first, second, reason), ...] where first and second are instances of | 45 [(first, second, reason), ...] where first and second are instances of |
45 request_track.Request, and reason is in DEPENDENCIES. The second request | 46 request_track.Request, and reason is in DEPENDENCIES. The second request |
46 depends on the first one, with the listed reason. | 47 depends on the first one, with the listed reason. |
47 """ | 48 """ |
48 deps = [] | 49 self._ComputeRequestDependencies() |
| 50 return copy.copy(self._deps) |
| 51 |
| 52 def GetRedirectChain(self, request): |
| 53 """Returns the whole redirect chain for a given request. |
| 54 |
| 55 Note that this misses some JS-based redirects. |
| 56 |
| 57 Returns: |
| 58 A list of request, containing the request passed as a parameter. |
| 59 """ |
| 60 self._ComputeRequestDependencies() |
| 61 chain = [request] |
| 62 while True: |
| 63 for (first_request, second_request, why) in self._deps: |
| 64 if first_request == request and why == 'redirect': |
| 65 chain.append(second_request) |
| 66 request = second_request |
| 67 break |
| 68 else: |
| 69 return chain |
| 70 |
| 71 def _ComputeRequestDependencies(self): |
| 72 if self._deps is not None: |
| 73 return |
| 74 self._deps = [] |
49 for request in self._requests: | 75 for request in self._requests: |
50 dependency = self._GetDependency(request) | 76 dependency = self._GetDependency(request) |
51 if dependency: | 77 if dependency: |
52 deps.append(dependency) | 78 self._deps.append(dependency) |
53 return deps | |
54 | 79 |
55 def _GetDependency(self, request): | 80 def _GetDependency(self, request): |
56 """Returns (first, second, reason), or None. | 81 """Returns (first, second, reason), or None. |
57 | 82 |
58 |second| depends on |first|. | 83 |second| depends on |first|. |
59 | 84 |
60 Args: | 85 Args: |
61 request: (Request) the request we wish to get the initiator of. | 86 request: (Request) the request we wish to get the initiator of. |
62 | 87 |
63 Returns: | 88 Returns: |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 if __name__ == '__main__': | 240 if __name__ == '__main__': |
216 import json | 241 import json |
217 import sys | 242 import sys |
218 trace_filename = sys.argv[1] | 243 trace_filename = sys.argv[1] |
219 json_dict = json.load(open(trace_filename, 'r')) | 244 json_dict = json.load(open(trace_filename, 'r')) |
220 lens = RequestDependencyLens( | 245 lens = RequestDependencyLens( |
221 loading_trace.LoadingTrace.FromJsonDict(json_dict)) | 246 loading_trace.LoadingTrace.FromJsonDict(json_dict)) |
222 depedencies = lens.GetRequestDependencies() | 247 depedencies = lens.GetRequestDependencies() |
223 for (first, second, dep_reason) in depedencies: | 248 for (first, second, dep_reason) in depedencies: |
224 print '%s -> %s\t(%s)' % (first.request_id, second.request_id, dep_reason) | 249 print '%s -> %s\t(%s)' % (first.request_id, second.request_id, dep_reason) |
OLD | NEW |