1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/shell/renderer/layout_test/leak_detector.h"
7 #include "base/json/json_writer.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 #include "content/shell/renderer/layout_test/blink_test_runner.h"
11 #include "third_party/WebKit/public/web/WebLeakDetector.h"
13 using blink::WebLeakDetector
;
17 // The initial states of the DOM objects at about:blank. The four nodes are a
18 // Document, a HTML, a HEAD and a BODY.
20 // TODO(hajimehoshi): Now these are hard-corded. If we add a target to count
21 // objects like RefCounted whose initial state is diffcult to estimate, we stop
22 // using hard-coded values. Instead, we need to load about:blank ahead of the
23 // layout tests actually and initialize LeakDetector by the got values.
24 const int kInitialNumberOfLiveAudioNodes
= 0;
25 const int kInitialNumberOfLiveDocuments
= 1;
26 const int kInitialNumberOfLiveNodes
= 4;
27 const int kInitialNumberOfLiveRenderObjects
= 3;
28 const int kInitialNumberOfLiveResources
= 0;
29 const int kInitialNumberOfScriptPromises
= 0;
30 const int kInitialNumberOfLiveFrames
= 1;
32 // In the initial state, there are two ActiveDOMObjects (FontFaceSet created by
33 // HTMLDocument and SuspendableTimer created by DocumentLoader).
34 const int kInitialNumberOfLiveActiveDOMObject
= 2;
36 // This includes not only about:blank's context but also ScriptRegexp (e.g.
37 // created by isValidEmailAddress in EmailInputType.cpp). The leak detector
38 // always creates the latter to stabilize the number of V8PerContextData
40 const int kInitialNumberOfV8PerContextData
= 2;
42 LeakDetector::LeakDetector(BlinkTestRunner
* test_runner
)
43 : test_runner_(test_runner
),
44 web_leak_detector_(blink::WebLeakDetector::create(this)) {
45 previous_result_
.numberOfLiveAudioNodes
= kInitialNumberOfLiveAudioNodes
;
46 previous_result_
.numberOfLiveDocuments
= kInitialNumberOfLiveDocuments
;
47 previous_result_
.numberOfLiveNodes
= kInitialNumberOfLiveNodes
;
48 previous_result_
.numberOfLiveRenderObjects
=
49 kInitialNumberOfLiveRenderObjects
;
50 previous_result_
.numberOfLiveResources
= kInitialNumberOfLiveResources
;
51 previous_result_
.numberOfLiveActiveDOMObjects
=
52 kInitialNumberOfLiveActiveDOMObject
;
53 previous_result_
.numberOfLiveScriptPromises
= kInitialNumberOfScriptPromises
;
54 previous_result_
.numberOfLiveFrames
= kInitialNumberOfLiveFrames
;
55 previous_result_
.numberOfLiveV8PerContextData
=
56 kInitialNumberOfV8PerContextData
;
59 LeakDetector::~LeakDetector() {
62 void LeakDetector::TryLeakDetection(blink::WebLocalFrame
* frame
) {
63 web_leak_detector_
->collectGarbageAndGetDOMCounts(frame
);
66 void LeakDetector::onLeakDetectionComplete(
67 const WebLeakDetectorClient::Result
& result
) {
68 LeakDetectionResult report
;
69 report
.leaked
= false;
70 base::DictionaryValue detail
;
72 if (previous_result_
.numberOfLiveAudioNodes
< result
.numberOfLiveAudioNodes
) {
73 base::ListValue
* list
= new base::ListValue();
74 list
->AppendInteger(previous_result_
.numberOfLiveAudioNodes
);
75 list
->AppendInteger(result
.numberOfLiveAudioNodes
);
76 detail
.Set("numberOfLiveAudioNodes", list
);
78 if (previous_result_
.numberOfLiveDocuments
< result
.numberOfLiveDocuments
) {
79 base::ListValue
* list
= new base::ListValue();
80 list
->AppendInteger(previous_result_
.numberOfLiveDocuments
);
81 list
->AppendInteger(result
.numberOfLiveDocuments
);
82 detail
.Set("numberOfLiveDocuments", list
);
84 if (previous_result_
.numberOfLiveNodes
< result
.numberOfLiveNodes
) {
85 base::ListValue
* list
= new base::ListValue();
86 list
->AppendInteger(previous_result_
.numberOfLiveNodes
);
87 list
->AppendInteger(result
.numberOfLiveNodes
);
88 detail
.Set("numberOfLiveNodes", list
);
90 if (previous_result_
.numberOfLiveRenderObjects
<
91 result
.numberOfLiveRenderObjects
) {
92 base::ListValue
* list
= new base::ListValue();
93 list
->AppendInteger(previous_result_
.numberOfLiveRenderObjects
);
94 list
->AppendInteger(result
.numberOfLiveRenderObjects
);
95 detail
.Set("numberOfLiveRenderObjects", list
);
97 if (previous_result_
.numberOfLiveResources
< result
.numberOfLiveResources
) {
98 base::ListValue
* list
= new base::ListValue();
99 list
->AppendInteger(previous_result_
.numberOfLiveResources
);
100 list
->AppendInteger(result
.numberOfLiveResources
);
101 detail
.Set("numberOfLiveResources", list
);
103 if (previous_result_
.numberOfLiveActiveDOMObjects
<
104 result
.numberOfLiveActiveDOMObjects
) {
105 base::ListValue
* list
= new base::ListValue();
106 list
->AppendInteger(previous_result_
.numberOfLiveActiveDOMObjects
);
107 list
->AppendInteger(result
.numberOfLiveActiveDOMObjects
);
108 detail
.Set("numberOfLiveActiveDOMObjects", list
);
110 if (previous_result_
.numberOfLiveScriptPromises
<
111 result
.numberOfLiveScriptPromises
) {
112 base::ListValue
* list
= new base::ListValue();
113 list
->AppendInteger(previous_result_
.numberOfLiveScriptPromises
);
114 list
->AppendInteger(result
.numberOfLiveScriptPromises
);
115 detail
.Set("numberOfLiveScriptPromises", list
);
117 if (previous_result_
.numberOfLiveFrames
< result
.numberOfLiveFrames
) {
118 base::ListValue
* list
= new base::ListValue();
119 list
->AppendInteger(previous_result_
.numberOfLiveFrames
);
120 list
->AppendInteger(result
.numberOfLiveFrames
);
121 detail
.Set("numberOfLiveFrames", list
);
123 if (previous_result_
.numberOfLiveV8PerContextData
<
124 result
.numberOfLiveV8PerContextData
) {
125 base::ListValue
* list
= new base::ListValue();
126 list
->AppendInteger(previous_result_
.numberOfLiveV8PerContextData
);
127 list
->AppendInteger(result
.numberOfLiveV8PerContextData
);
128 detail
.Set("numberOfLiveV8PerContextData", list
);
131 if (!detail
.empty()) {
132 std::string detail_str
;
133 base::JSONWriter::Write(detail
, &detail_str
);
134 report
.detail
= detail_str
;
135 report
.leaked
= true;
138 previous_result_
= result
;
139 test_runner_
->ReportLeakDetectionResult(report
);
142 } // namespace content