1// Copyright (c) 2006-2008 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/browser/metrics/metrics_response.h"
6
7#include "libxml/parser.h"
8
9// State to pass around during SAX parsing.
10struct SAXState {
11  int collectors;
12  int events;
13  int interval;
14};
15
16// libxml uses xmlChar*, which is unsigned char*
17inline const char* Char(const xmlChar* input) {
18  return reinterpret_cast<const char*>(input);
19}
20
21static void SAXStartElement(void* user_data,
22                            const xmlChar* name,
23                            const xmlChar** attrs) {
24  if (!name || !attrs)
25    return;
26
27  SAXState* state = static_cast<SAXState*>(user_data);
28
29  if (strcmp(Char(name), "upload") == 0) {
30    for (int i = 0; attrs[i] && attrs[i + i]; i += 2) {
31      if (strcmp(Char(attrs[i]), "interval") == 0) {
32        state->interval = atoi(Char(attrs[i + 1]));
33        return;
34      }
35    }
36  } else if (strcmp(Char(name), "limit") == 0) {
37    for (int i = 0; attrs[i] && attrs[i + 1]; i += 2) {
38      if (strcmp(Char(attrs[i]), "events") == 0) {
39        state->events = atoi(Char(attrs[i + 1]));
40        return;
41      }
42    }
43  } else if (strcmp(Char(name), "collector") == 0) {
44    for (int i = 0; attrs[i] && attrs[i + 1]; i += 2) {
45      if (strcmp(Char(attrs[i]), "type") == 0) {
46        const char* type = Char(attrs[i + 1]);
47        if (strcmp(type, "document") == 0) {
48          state->collectors |= MetricsResponse::COLLECTOR_DOCUMENT;
49        } else if (strcmp(type, "profile") == 0) {
50          state->collectors |= MetricsResponse::COLLECTOR_PROFILE;
51        } else if (strcmp(type, "window") == 0) {
52          state->collectors |= MetricsResponse::COLLECTOR_WINDOW;
53        } else if (strcmp(type, "ui") == 0) {
54          state->collectors |= MetricsResponse::COLLECTOR_UI;
55        }
56        return;
57      }
58    }
59  }
60}
61
62MetricsResponse::MetricsResponse(const std::string& response_xml)
63    : valid_(false),
64      collectors_(COLLECTOR_NONE),
65      events_(0),
66      interval_(0) {
67  if (response_xml.empty())
68    return;
69
70  xmlSAXHandler handler = {0};
71  handler.startElement = SAXStartElement;
72  SAXState state = {0};
73
74  valid_ = !xmlSAXUserParseMemory(&handler, &state,
75                                  response_xml.data(),
76                                  static_cast<int>(response_xml.size()));
77
78  collectors_ = state.collectors;
79  events_ = state.events;
80  interval_ = state.interval;
81}
82