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 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 41 LeakDetector::~LeakDetector() { 42 } 43 44 void LeakDetector::TryLeakDetection(blink::WebLocalFrame* frame) { 45 web_leak_detector_->collectGarbageAndGetDOMCounts(frame); 46 } 47 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