- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / chromedriver / chrome / heap_snapshot_taker.cc
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
13 HeapSnapshotTaker::HeapSnapshotTaker(DevToolsClient* client)
14     : client_(client), snapshot_uid_(-1) {
15   client_->AddListener(this);
16 }
17
18 HeapSnapshotTaker::~HeapSnapshotTaker() {}
19
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);
24   Status status3(kOk);
25   if (snapshot_uid_ != -1) {  // Clear the snapshot cached in chrome.
26     status3 = client_->SendCommand("HeapProfiler.clearProfiles", params);
27   }
28
29   Status status4(kOk);
30   if (status1.IsOk() && status2.IsOk() && status3.IsOk()) {
31     scoped_ptr<base::Value> value(base::JSONReader::Read(snapshot_));
32     if (!value)
33       status4 = Status(kUnknownError, "heap snapshot not in JSON format");
34     else
35       *snapshot = value.Pass();
36   }
37   snapshot_uid_ = -1;
38   snapshot_.clear();
39   if (status1.IsError())
40     return status1;
41   else if (status2.IsError())
42     return status2;
43   else if (status3.IsError())
44     return status3;
45   else
46     return status4;
47 }
48
49 Status HeapSnapshotTaker::TakeSnapshotInternal() {
50   if (snapshot_uid_ != -1)
51     return Status(kUnknownError, "unexpected heap snapshot was triggered");
52
53   base::DictionaryValue params;
54   const char* kMethods[] = {
55       "Debugger.enable",
56       "HeapProfiler.collectGarbage",
57       "HeapProfiler.takeHeapSnapshot"
58   };
59   for (size_t i = 0; i < arraysize(kMethods); ++i) {
60     Status status = client_->SendCommand(kMethods[i], params);
61     if (status.IsError())
62       return status;
63   }
64
65   if (snapshot_uid_ == -1)
66     return Status(kUnknownError, "failed to receive snapshot uid");
67
68   base::DictionaryValue uid_params;
69   uid_params.SetInteger("uid", snapshot_uid_);
70   Status status = client_->SendCommand(
71       "HeapProfiler.getHeapSnapshot", uid_params);
72   if (status.IsError())
73     return status;
74
75   return Status(kOk);
76 }
77
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'");
87     }
88   } else if (method == "HeapProfiler.addHeapSnapshotChunk") {
89     int uid = -1;
90     if (!params.GetInteger("uid", &uid)) {
91       return Status(kUnknownError,
92                     "HeapProfiler.addHeapSnapshotChunk has no 'uid'");
93     } else if (uid == snapshot_uid_) {
94       std::string chunk;
95       if (!params.GetString("chunk", &chunk)) {
96         return Status(kUnknownError,
97                       "HeapProfiler.addHeapSnapshotChunk has no 'chunk'");
98       }
99
100       snapshot_.append(chunk);
101     } else {
102       LOG(WARNING) << "expect chunk event uid " << snapshot_uid_
103                    << ", but got " << uid;
104     }
105   }
106   return Status(kOk);
107 }