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.
4
5 #include "content/shell/renderer/leak_detector.h"
6
7 #include "base/json/json_writer.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 #include "content/shell/renderer/webkit_test_runner.h"
11 #include "third_party/WebKit/public/web/WebLeakDetector.h"
12
13 using blink::WebLeakDetector;
14
15 namespace content {
16
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.
19 //
20 // TODO(hajimehoshi): Now these are hard-corded. If we add target to count like
21 // RefCoutned objects whose initial state is diffcult to estimate, we stop using
22 // hard-coded values. Instead, we need to load about:blank ahead of the layout
23 // 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
LeakDetector(WebKitTestRunner * test_runner)30 LeakDetector::LeakDetector(WebKitTestRunner* test_runner)
31 : test_runner_(test_runner),
32 web_leak_detector_(blink::WebLeakDetector::create(this)) {
33 previous_result_.numberOfLiveAudioNodes = kInitialNumberOfLiveAudioNodes;
34 previous_result_.numberOfLiveDocuments = kInitialNumberOfLiveDocuments;
35 previous_result_.numberOfLiveNodes = kInitialNumberOfLiveNodes;
36 previous_result_.numberOfLiveRenderObjects =
37 kInitialNumberOfLiveRenderObjects;
38 previous_result_.numberOfLiveResources = kInitialNumberOfLiveResources;
39 }
40
~LeakDetector()41 LeakDetector::~LeakDetector() {
42 }
43
TryLeakDetection(blink::WebLocalFrame * frame)44 void LeakDetector::TryLeakDetection(blink::WebLocalFrame* frame) {
45 web_leak_detector_->collectGarbageAndGetDOMCounts(frame);
46 }
47
onLeakDetectionComplete(const WebLeakDetectorClient::Result & result)48 void LeakDetector::onLeakDetectionComplete(
49 const WebLeakDetectorClient::Result& result) {
50 LeakDetectionResult report;
51 report.leaked = false;
52 base::DictionaryValue detail;
53
54 if (previous_result_.numberOfLiveAudioNodes < result.numberOfLiveAudioNodes) {
55 base::ListValue* list = new base::ListValue();
56 list->AppendInteger(previous_result_.numberOfLiveAudioNodes);
57 list->AppendInteger(result.numberOfLiveAudioNodes);
58 detail.Set("numberOfLiveAudioNodes", list);
59 }
60 if (previous_result_.numberOfLiveDocuments < result.numberOfLiveDocuments) {
61 base::ListValue* list = new base::ListValue();
62 list->AppendInteger(previous_result_.numberOfLiveDocuments);
63 list->AppendInteger(result.numberOfLiveDocuments);
64 detail.Set("numberOfLiveDocuments", list);
65 }
66 if (previous_result_.numberOfLiveNodes < result.numberOfLiveNodes) {
67 base::ListValue* list = new base::ListValue();
68 list->AppendInteger(previous_result_.numberOfLiveNodes);
69 list->AppendInteger(result.numberOfLiveNodes);
70 detail.Set("numberOfLiveNodes", list);
71 }
72 if (previous_result_.numberOfLiveRenderObjects <
73 result.numberOfLiveRenderObjects) {
74 base::ListValue* list = new base::ListValue();
75 list->AppendInteger(previous_result_.numberOfLiveRenderObjects);
76 list->AppendInteger(result.numberOfLiveRenderObjects);
77 detail.Set("numberOfLiveRenderObjects", list);
78 }
79 if (previous_result_.numberOfLiveResources < result.numberOfLiveResources) {
80 base::ListValue* list = new base::ListValue();
81 list->AppendInteger(previous_result_.numberOfLiveResources);
82 list->AppendInteger(result.numberOfLiveResources);
83 detail.Set("numberOfLiveResources", list);
84 }
85
86 if (!detail.empty()) {
87 std::string detail_str;
88 base::JSONWriter::Write(&detail, &detail_str);
89 report.detail = detail_str;
90 report.leaked = true;
91 }
92
93 previous_result_ = result;
94 test_runner_->ReportLeakDetectionResult(report);
95 }
96
97 } // namespace content
98