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.
4
5#include "chrome/test/chromedriver/chrome/heap_snapshot_taker.h"
6
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"
12
13HeapSnapshotTaker::HeapSnapshotTaker(DevToolsClient* client)
14    : client_(client) {
15  client_->AddListener(this);
16}
17
18HeapSnapshotTaker::~HeapSnapshotTaker() {}
19
20Status HeapSnapshotTaker::TakeSnapshot(scoped_ptr<base::Value>* snapshot) {
21  Status status1 = TakeSnapshotInternal();
22  base::DictionaryValue params;
23  Status status2 = client_->SendCommand("Debugger.disable", params);
24
25  Status status3(kOk);
26  if (status1.IsOk() && status2.IsOk()) {
27    scoped_ptr<base::Value> value(base::JSONReader::Read(snapshot_));
28    if (!value) {
29      status3 = Status(kUnknownError, "heap snapshot not in JSON format");
30    } else {
31      *snapshot = value.Pass();
32    }
33  }
34  snapshot_.clear();
35  if (status1.IsError()) {
36    return status1;
37  } else if (status2.IsError()) {
38    return status2;
39  } else {
40    return status3;
41  }
42}
43
44Status HeapSnapshotTaker::TakeSnapshotInternal() {
45  base::DictionaryValue params;
46  const char* kMethods[] = {
47      "Debugger.enable",
48      "HeapProfiler.collectGarbage",
49      "HeapProfiler.takeHeapSnapshot"
50  };
51  for (size_t i = 0; i < arraysize(kMethods); ++i) {
52    Status status = client_->SendCommand(kMethods[i], params);
53    if (status.IsError())
54      return status;
55  }
56
57  return Status(kOk);
58}
59
60Status HeapSnapshotTaker::OnEvent(DevToolsClient* client,
61                                  const std::string& method,
62                                  const base::DictionaryValue& params) {
63  if (method == "HeapProfiler.addHeapSnapshotChunk") {
64    std::string chunk;
65    if (!params.GetString("chunk", &chunk)) {
66      return Status(kUnknownError,
67                    "HeapProfiler.addHeapSnapshotChunk has no 'chunk'");
68    }
69    snapshot_.append(chunk);
70  }
71  return Status(kOk);
72}
73