1 // Copyright 2013 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 "chrome/test/chromedriver/chrome/heap_snapshot_taker.h"
7 #include "base/json/json_reader.h"
8 #include "base/logging.h"
9 #include "base/values.h"
10 #include "chrome/test/chromedriver/chrome/devtools_client.h"
11 #include "chrome/test/chromedriver/chrome/status.h"
13 HeapSnapshotTaker::HeapSnapshotTaker(DevToolsClient* client)
14 : client_(client), snapshot_uid_(-1) {
15 client_->AddListener(this);
18 HeapSnapshotTaker::~HeapSnapshotTaker() {}
20 Status HeapSnapshotTaker::TakeSnapshot(scoped_ptr<base::Value>* snapshot) {
21 Status status1 = TakeSnapshotInternal();
22 base::DictionaryValue params;
23 Status status2 = client_->SendCommand("Debugger.disable", params);
25 if (snapshot_uid_ != -1) { // Clear the snapshot cached in chrome.
26 status3 = client_->SendCommand("HeapProfiler.clearProfiles", params);
30 if (status1.IsOk() && status2.IsOk() && status3.IsOk()) {
31 scoped_ptr<base::Value> value(base::JSONReader::Read(snapshot_));
33 status4 = Status(kUnknownError, "heap snapshot not in JSON format");
35 *snapshot = value.Pass();
39 if (status1.IsError())
41 else if (status2.IsError())
43 else if (status3.IsError())
49 Status HeapSnapshotTaker::TakeSnapshotInternal() {
50 if (snapshot_uid_ != -1)
51 return Status(kUnknownError, "unexpected heap snapshot was triggered");
53 base::DictionaryValue params;
54 const char* kMethods[] = {
56 "HeapProfiler.collectGarbage",
57 "HeapProfiler.takeHeapSnapshot"
59 for (size_t i = 0; i < arraysize(kMethods); ++i) {
60 Status status = client_->SendCommand(kMethods[i], params);
65 if (snapshot_uid_ == -1)
66 return Status(kUnknownError, "failed to receive snapshot uid");
68 base::DictionaryValue uid_params;
69 uid_params.SetInteger("uid", snapshot_uid_);
70 Status status = client_->SendCommand(
71 "HeapProfiler.getHeapSnapshot", uid_params);
78 Status HeapSnapshotTaker::OnEvent(DevToolsClient* client,
79 const std::string& method,
80 const base::DictionaryValue& params) {
81 if (method == "HeapProfiler.addProfileHeader") {
82 if (snapshot_uid_ != -1) {
83 LOG(WARNING) << "multiple heap snapshot triggered";
84 } else if (!params.GetInteger("header.uid", &snapshot_uid_)) {
85 return Status(kUnknownError,
86 "HeapProfiler.addProfileHeader has invalid 'header.uid'");
88 } else if (method == "HeapProfiler.addHeapSnapshotChunk") {
90 if (!params.GetInteger("uid", &uid)) {
91 return Status(kUnknownError,
92 "HeapProfiler.addHeapSnapshotChunk has no 'uid'");
93 } else if (uid == snapshot_uid_) {
95 if (!params.GetString("chunk", &chunk)) {
96 return Status(kUnknownError,
97 "HeapProfiler.addHeapSnapshotChunk has no 'chunk'");
100 snapshot_.append(chunk);
102 LOG(WARNING) << "expect chunk event uid " << snapshot_uid_
103 << ", but got " << uid;