// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "content/shell/renderer/leak_detector.h" #include "base/json/json_writer.h" #include "base/logging.h" #include "base/values.h" #include "content/shell/renderer/webkit_test_runner.h" #include "third_party/WebKit/public/web/WebLeakDetector.h" using blink::WebLeakDetector; namespace content { // The initial states of the DOM objects at about:blank. The four nodes are a // Document, a HTML, a HEAD and a BODY. // // TODO(hajimehoshi): Now these are hard-corded. If we add target to count like // RefCoutned objects whose initial state is diffcult to estimate, we stop using // hard-coded values. Instead, we need to load about:blank ahead of the layout // tests actually and initialize LeakDetector by the got values. const int kInitialNumberOfLiveAudioNodes = 0; const int kInitialNumberOfLiveDocuments = 1; const int kInitialNumberOfLiveNodes = 4; const int kInitialNumberOfLiveRenderObjects = 3; const int kInitialNumberOfLiveResources = 0; LeakDetector::LeakDetector(WebKitTestRunner* test_runner) : test_runner_(test_runner), web_leak_detector_(blink::WebLeakDetector::create(this)) { previous_result_.numberOfLiveAudioNodes = kInitialNumberOfLiveAudioNodes; previous_result_.numberOfLiveDocuments = kInitialNumberOfLiveDocuments; previous_result_.numberOfLiveNodes = kInitialNumberOfLiveNodes; previous_result_.numberOfLiveRenderObjects = kInitialNumberOfLiveRenderObjects; previous_result_.numberOfLiveResources = kInitialNumberOfLiveResources; } LeakDetector::~LeakDetector() { } void LeakDetector::TryLeakDetection(blink::WebLocalFrame* frame) { web_leak_detector_->collectGarbageAndGetDOMCounts(frame); } void LeakDetector::onLeakDetectionComplete( const WebLeakDetectorClient::Result& result) { LeakDetectionResult report; report.leaked = false; base::DictionaryValue detail; if (previous_result_.numberOfLiveAudioNodes < result.numberOfLiveAudioNodes) { base::ListValue* list = new base::ListValue(); list->AppendInteger(previous_result_.numberOfLiveAudioNodes); list->AppendInteger(result.numberOfLiveAudioNodes); detail.Set("numberOfLiveAudioNodes", list); } if (previous_result_.numberOfLiveDocuments < result.numberOfLiveDocuments) { base::ListValue* list = new base::ListValue(); list->AppendInteger(previous_result_.numberOfLiveDocuments); list->AppendInteger(result.numberOfLiveDocuments); detail.Set("numberOfLiveDocuments", list); } if (previous_result_.numberOfLiveNodes < result.numberOfLiveNodes) { base::ListValue* list = new base::ListValue(); list->AppendInteger(previous_result_.numberOfLiveNodes); list->AppendInteger(result.numberOfLiveNodes); detail.Set("numberOfLiveNodes", list); } if (previous_result_.numberOfLiveRenderObjects < result.numberOfLiveRenderObjects) { base::ListValue* list = new base::ListValue(); list->AppendInteger(previous_result_.numberOfLiveRenderObjects); list->AppendInteger(result.numberOfLiveRenderObjects); detail.Set("numberOfLiveRenderObjects", list); } if (previous_result_.numberOfLiveResources < result.numberOfLiveResources) { base::ListValue* list = new base::ListValue(); list->AppendInteger(previous_result_.numberOfLiveResources); list->AppendInteger(result.numberOfLiveResources); detail.Set("numberOfLiveResources", list); } if (!detail.empty()) { std::string detail_str; base::JSONWriter::Write(&detail, &detail_str); report.detail = detail_str; report.leaked = true; } previous_result_ = result; test_runner_->ReportLeakDetectionResult(report); } } // namespace content