blob: 7d602e6ed7796061f4f2e3a62a98d5a9e6943c47 [file] [log] [blame]
[email protected]85ed9d42010-06-08 22:37:441// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]cd1adc22009-01-16 01:29:225#include "chrome/browser/metrics/metrics_log.h"
initial.commit09911bf2008-07-26 23:55:296
[email protected]1eeb5e02010-07-20 23:02:117#include <string>
8#include <vector>
9
[email protected]d1be67b2008-11-19 20:28:3810#include "base/basictypes.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/file_util.h"
[email protected]85ed9d42010-06-08 22:37:4412#include "base/perftimer.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/scoped_ptr.h"
14#include "base/string_util.h"
[email protected]fadf97f2008-09-18 12:18:1415#include "base/sys_info.h"
[email protected]37f39e42010-01-06 17:35:1716#include "base/third_party/nspr/prtime.h"
[email protected]1eeb5e02010-07-20 23:02:1117#include "base/time.h"
18#include "base/utf_string_conversions.h"
initial.commit09911bf2008-07-26 23:55:2919#include "chrome/browser/autocomplete/autocomplete.h"
20#include "chrome/browser/browser_process.h"
[email protected]e8c287c872010-07-20 00:49:4221#include "chrome/browser/gpu_process_host.h"
[email protected]37858e52010-08-26 00:22:0222#include "chrome/browser/prefs/pref_service.h"
[email protected]1eeb5e02010-07-20 23:02:1123#include "chrome/common/chrome_version_info.h"
initial.commit09911bf2008-07-26 23:55:2924#include "chrome/common/logging_chrome.h"
25#include "chrome/common/pref_names.h"
[email protected]46072d42008-07-28 14:49:3526#include "googleurl/src/gurl.h"
initial.commit09911bf2008-07-26 23:55:2927
28#define OPEN_ELEMENT_FOR_SCOPE(name) ScopedElement scoped_element(this, name)
29
[email protected]d1be67b2008-11-19 20:28:3830// http://blogs.msdn.com/oldnewthing/archive/2004/10/25/247180.aspx
31#if defined(OS_WIN)
32extern "C" IMAGE_DOS_HEADER __ImageBase;
33#endif
34
[email protected]1226abb2010-06-10 18:01:2835MetricsLog::MetricsLog(const std::string& client_id, int session_id)
36 : MetricsLogBase(client_id, session_id, MetricsLog::GetVersionString()) {}
[email protected]5ed7d4572009-12-23 17:42:4137
[email protected]1226abb2010-06-10 18:01:2838MetricsLog::~MetricsLog() {}
initial.commit09911bf2008-07-26 23:55:2939
40// static
41void MetricsLog::RegisterPrefs(PrefService* local_state) {
42 local_state->RegisterListPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:2943}
44
[email protected]9165f742010-03-10 22:55:0145int64 MetricsLog::GetIncrementalUptime(PrefService* pref) {
46 base::TimeTicks now = base::TimeTicks::Now();
47 static base::TimeTicks last_updated_time(now);
48 int64 incremental_time = (now - last_updated_time).InSeconds();
49 last_updated_time = now;
50
51 if (incremental_time > 0) {
52 int64 metrics_uptime = pref->GetInt64(prefs::kUninstallMetricsUptimeSec);
53 metrics_uptime += incremental_time;
54 pref->SetInt64(prefs::kUninstallMetricsUptimeSec, metrics_uptime);
55 }
56
57 return incremental_time;
58}
59
initial.commit09911bf2008-07-26 23:55:2960std::string MetricsLog::GetInstallDate() const {
61 PrefService* pref = g_browser_process->local_state();
62 if (pref) {
[email protected]ddd231e2010-06-29 20:35:1963 return pref->GetString(prefs::kMetricsClientIDTimestamp);
initial.commit09911bf2008-07-26 23:55:2964 } else {
65 NOTREACHED();
66 return "0";
67 }
68}
69
[email protected]1226abb2010-06-10 18:01:2870// static
71std::string MetricsLog::GetVersionString() {
[email protected]0211f57e2010-08-27 20:28:4272 chrome::VersionInfo version_info;
73 if (!version_info.is_valid()) {
74 NOTREACHED() << "Unable to retrieve version info.";
75 return std::string();
[email protected]1226abb2010-06-10 18:01:2876 }
77
[email protected]0211f57e2010-08-27 20:28:4278 std::string version = version_info.Version();
79 if (!version_extension_.empty())
80 version += version_extension_;
81 if (!version_info.IsOfficialBuild())
82 version.append("-devel");
83 return version;
[email protected]1226abb2010-06-10 18:01:2884}
85
[email protected]dec76e802010-09-23 22:43:5386MetricsLog* MetricsLog::AsMetricsLog() {
87 return this;
88}
89
[email protected]0b33f80b2008-12-17 21:34:3690void MetricsLog::RecordIncrementalStabilityElements() {
91 DCHECK(!locked_);
92
93 PrefService* pref = g_browser_process->local_state();
94 DCHECK(pref);
95
[email protected]147bbc0b2009-01-06 19:37:4096 OPEN_ELEMENT_FOR_SCOPE("profile");
97 WriteCommonEventAttributes();
98
99 WriteInstallElement(); // Supply appversion.
100
101 {
102 OPEN_ELEMENT_FOR_SCOPE("stability"); // Minimal set of stability elements.
103 WriteRequiredStabilityAttributes(pref);
104 WriteRealtimeStabilityAttributes(pref);
105
106 WritePluginStabilityElements(pref);
107 }
[email protected]0b33f80b2008-12-17 21:34:36108}
109
initial.commit09911bf2008-07-26 23:55:29110void MetricsLog::WriteStabilityElement() {
111 DCHECK(!locked_);
112
113 PrefService* pref = g_browser_process->local_state();
114 DCHECK(pref);
115
116 // Get stability attributes out of Local State, zeroing out stored values.
117 // NOTE: This could lead to some data loss if this report isn't successfully
118 // sent, but that's true for all the metrics.
119
[email protected]ffaf78a2008-11-12 17:38:33120 OPEN_ELEMENT_FOR_SCOPE("stability");
[email protected]147bbc0b2009-01-06 19:37:40121 WriteRequiredStabilityAttributes(pref);
122 WriteRealtimeStabilityAttributes(pref);
initial.commit09911bf2008-07-26 23:55:29123
[email protected]0b33f80b2008-12-17 21:34:36124 // TODO(jar): The following are all optional, so we *could* optimize them for
125 // values of zero (and not include them).
[email protected]8e674e42008-07-30 16:05:48126 WriteIntAttribute("incompleteshutdowncount",
127 pref->GetInteger(
128 prefs::kStabilityIncompleteSessionEndCount));
129 pref->SetInteger(prefs::kStabilityIncompleteSessionEndCount, 0);
[email protected]0b33f80b2008-12-17 21:34:36130
131
[email protected]e73c01972008-08-13 00:18:24132 WriteIntAttribute("breakpadregistrationok",
133 pref->GetInteger(prefs::kStabilityBreakpadRegistrationSuccess));
134 pref->SetInteger(prefs::kStabilityBreakpadRegistrationSuccess, 0);
135 WriteIntAttribute("breakpadregistrationfail",
136 pref->GetInteger(prefs::kStabilityBreakpadRegistrationFail));
137 pref->SetInteger(prefs::kStabilityBreakpadRegistrationFail, 0);
138 WriteIntAttribute("debuggerpresent",
139 pref->GetInteger(prefs::kStabilityDebuggerPresent));
140 pref->SetInteger(prefs::kStabilityDebuggerPresent, 0);
141 WriteIntAttribute("debuggernotpresent",
142 pref->GetInteger(prefs::kStabilityDebuggerNotPresent));
143 pref->SetInteger(prefs::kStabilityDebuggerNotPresent, 0);
initial.commit09911bf2008-07-26 23:55:29144
[email protected]147bbc0b2009-01-06 19:37:40145 WritePluginStabilityElements(pref);
146}
147
148void MetricsLog::WritePluginStabilityElements(PrefService* pref) {
149 // Now log plugin stability info.
initial.commit09911bf2008-07-26 23:55:29150 const ListValue* plugin_stats_list = pref->GetList(
151 prefs::kStabilityPluginStats);
152 if (plugin_stats_list) {
[email protected]ffaf78a2008-11-12 17:38:33153 OPEN_ELEMENT_FOR_SCOPE("plugins");
initial.commit09911bf2008-07-26 23:55:29154 for (ListValue::const_iterator iter = plugin_stats_list->begin();
155 iter != plugin_stats_list->end(); ++iter) {
156 if (!(*iter)->IsType(Value::TYPE_DICTIONARY)) {
157 NOTREACHED();
158 continue;
159 }
160 DictionaryValue* plugin_dict = static_cast<DictionaryValue*>(*iter);
161
[email protected]57ecc4b2010-08-11 03:02:51162 std::string plugin_name;
[email protected]8e50b602009-03-03 22:59:43163 plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name);
initial.commit09911bf2008-07-26 23:55:29164
[email protected]ffaf78a2008-11-12 17:38:33165 OPEN_ELEMENT_FOR_SCOPE("pluginstability");
[email protected]a27a9382009-02-11 23:55:10166 // Use "filename" instead of "name", otherwise we need to update the
167 // UMA servers.
[email protected]57ecc4b2010-08-11 03:02:51168 WriteAttribute("filename", CreateBase64Hash(plugin_name));
initial.commit09911bf2008-07-26 23:55:29169
170 int launches = 0;
[email protected]8e50b602009-03-03 22:59:43171 plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches);
initial.commit09911bf2008-07-26 23:55:29172 WriteIntAttribute("launchcount", launches);
173
174 int instances = 0;
[email protected]8e50b602009-03-03 22:59:43175 plugin_dict->GetInteger(prefs::kStabilityPluginInstances, &instances);
initial.commit09911bf2008-07-26 23:55:29176 WriteIntAttribute("instancecount", instances);
177
178 int crashes = 0;
[email protected]8e50b602009-03-03 22:59:43179 plugin_dict->GetInteger(prefs::kStabilityPluginCrashes, &crashes);
initial.commit09911bf2008-07-26 23:55:29180 WriteIntAttribute("crashcount", crashes);
initial.commit09911bf2008-07-26 23:55:29181 }
182
183 pref->ClearPref(prefs::kStabilityPluginStats);
initial.commit09911bf2008-07-26 23:55:29184 }
initial.commit09911bf2008-07-26 23:55:29185}
186
[email protected]147bbc0b2009-01-06 19:37:40187void MetricsLog::WriteRequiredStabilityAttributes(PrefService* pref) {
[email protected]0b33f80b2008-12-17 21:34:36188 // The server refuses data that doesn't have certain values. crashcount and
189 // launchcount are currently "required" in the "stability" group.
190 WriteIntAttribute("launchcount",
191 pref->GetInteger(prefs::kStabilityLaunchCount));
192 pref->SetInteger(prefs::kStabilityLaunchCount, 0);
193 WriteIntAttribute("crashcount",
194 pref->GetInteger(prefs::kStabilityCrashCount));
195 pref->SetInteger(prefs::kStabilityCrashCount, 0);
196}
197
[email protected]147bbc0b2009-01-06 19:37:40198void MetricsLog::WriteRealtimeStabilityAttributes(PrefService* pref) {
[email protected]0b33f80b2008-12-17 21:34:36199 // Update the stats which are critical for real-time stability monitoring.
200 // Since these are "optional," only list ones that are non-zero, as the counts
201 // are aggergated (summed) server side.
202
203 int count = pref->GetInteger(prefs::kStabilityPageLoadCount);
204 if (count) {
205 WriteIntAttribute("pageloadcount", count);
206 pref->SetInteger(prefs::kStabilityPageLoadCount, 0);
207 }
208
209 count = pref->GetInteger(prefs::kStabilityRendererCrashCount);
210 if (count) {
211 WriteIntAttribute("renderercrashcount", count);
212 pref->SetInteger(prefs::kStabilityRendererCrashCount, 0);
213 }
214
[email protected]1f085622009-12-04 05:33:45215 count = pref->GetInteger(prefs::kStabilityExtensionRendererCrashCount);
216 if (count) {
217 WriteIntAttribute("extensionrenderercrashcount", count);
218 pref->SetInteger(prefs::kStabilityExtensionRendererCrashCount, 0);
219 }
220
[email protected]0b33f80b2008-12-17 21:34:36221 count = pref->GetInteger(prefs::kStabilityRendererHangCount);
222 if (count) {
223 WriteIntAttribute("rendererhangcount", count);
224 pref->SetInteger(prefs::kStabilityRendererHangCount, 0);
225 }
[email protected]1f085622009-12-04 05:33:45226
227 count = pref->GetInteger(prefs::kStabilityChildProcessCrashCount);
228 if (count) {
229 WriteIntAttribute("childprocesscrashcount", count);
230 pref->SetInteger(prefs::kStabilityChildProcessCrashCount, 0);
231 }
[email protected]9165f742010-03-10 22:55:01232
233 int64 recent_duration = GetIncrementalUptime(pref);
234 if (recent_duration)
235 WriteInt64Attribute("uptimesec", recent_duration);
[email protected]0b33f80b2008-12-17 21:34:36236}
237
initial.commit09911bf2008-07-26 23:55:29238void MetricsLog::WritePluginList(
239 const std::vector<WebPluginInfo>& plugin_list) {
240 DCHECK(!locked_);
241
[email protected]ffaf78a2008-11-12 17:38:33242 OPEN_ELEMENT_FOR_SCOPE("plugins");
initial.commit09911bf2008-07-26 23:55:29243
244 for (std::vector<WebPluginInfo>::const_iterator iter = plugin_list.begin();
245 iter != plugin_list.end(); ++iter) {
[email protected]ffaf78a2008-11-12 17:38:33246 OPEN_ELEMENT_FOR_SCOPE("plugin");
initial.commit09911bf2008-07-26 23:55:29247
248 // Plugin name and filename are hashed for the privacy of those
249 // testing unreleased new extensions.
[email protected]c9d811372010-06-23 21:44:57250 WriteAttribute("name", CreateBase64Hash(UTF16ToUTF8(iter->name)));
[email protected]046344c2009-01-13 00:54:21251 WriteAttribute("filename",
252 CreateBase64Hash(WideToUTF8(iter->path.BaseName().ToWStringHack())));
[email protected]c9d811372010-06-23 21:44:57253 WriteAttribute("version", UTF16ToUTF8(iter->version));
initial.commit09911bf2008-07-26 23:55:29254 }
initial.commit09911bf2008-07-26 23:55:29255}
256
[email protected]147bbc0b2009-01-06 19:37:40257void MetricsLog::WriteInstallElement() {
258 OPEN_ELEMENT_FOR_SCOPE("install");
259 WriteAttribute("installdate", GetInstallDate());
260 WriteIntAttribute("buildid", 0); // We're using appversion instead.
[email protected]147bbc0b2009-01-06 19:37:40261}
262
initial.commit09911bf2008-07-26 23:55:29263void MetricsLog::RecordEnvironment(
264 const std::vector<WebPluginInfo>& plugin_list,
265 const DictionaryValue* profile_metrics) {
266 DCHECK(!locked_);
267
268 PrefService* pref = g_browser_process->local_state();
269
[email protected]ffaf78a2008-11-12 17:38:33270 OPEN_ELEMENT_FOR_SCOPE("profile");
initial.commit09911bf2008-07-26 23:55:29271 WriteCommonEventAttributes();
272
[email protected]147bbc0b2009-01-06 19:37:40273 WriteInstallElement();
initial.commit09911bf2008-07-26 23:55:29274
275 WritePluginList(plugin_list);
276
277 WriteStabilityElement();
278
279 {
280 OPEN_ELEMENT_FOR_SCOPE("cpu");
[email protected]05f9b682008-09-29 22:18:01281 WriteAttribute("arch", base::SysInfo::CPUArchitecture());
initial.commit09911bf2008-07-26 23:55:29282 }
283
284 {
initial.commit09911bf2008-07-26 23:55:29285 OPEN_ELEMENT_FOR_SCOPE("memory");
[email protected]ed6fc352008-09-18 12:44:40286 WriteIntAttribute("mb", base::SysInfo::AmountOfPhysicalMemoryMB());
[email protected]d1be67b2008-11-19 20:28:38287#if defined(OS_WIN)
288 WriteIntAttribute("dllbase", reinterpret_cast<int>(&__ImageBase));
289#endif
initial.commit09911bf2008-07-26 23:55:29290 }
291
292 {
293 OPEN_ELEMENT_FOR_SCOPE("os");
294 WriteAttribute("name",
[email protected]05f9b682008-09-29 22:18:01295 base::SysInfo::OperatingSystemName());
initial.commit09911bf2008-07-26 23:55:29296 WriteAttribute("version",
[email protected]05f9b682008-09-29 22:18:01297 base::SysInfo::OperatingSystemVersion());
initial.commit09911bf2008-07-26 23:55:29298 }
299
300 {
[email protected]e8c287c872010-07-20 00:49:42301 OPEN_ELEMENT_FOR_SCOPE("gpu");
302 WriteIntAttribute("vendorid",
303 GpuProcessHost::Get()->gpu_info().vendor_id());
304 WriteIntAttribute("deviceid",
305 GpuProcessHost::Get()->gpu_info().device_id());
306 }
307
308 {
initial.commit09911bf2008-07-26 23:55:29309 OPEN_ELEMENT_FOR_SCOPE("display");
310 int width = 0;
311 int height = 0;
[email protected]05f9b682008-09-29 22:18:01312 base::SysInfo::GetPrimaryDisplayDimensions(&width, &height);
initial.commit09911bf2008-07-26 23:55:29313 WriteIntAttribute("xsize", width);
314 WriteIntAttribute("ysize", height);
[email protected]05f9b682008-09-29 22:18:01315 WriteIntAttribute("screens", base::SysInfo::DisplayCount());
initial.commit09911bf2008-07-26 23:55:29316 }
317
318 {
319 OPEN_ELEMENT_FOR_SCOPE("bookmarks");
320 int num_bookmarks_on_bookmark_bar =
321 pref->GetInteger(prefs::kNumBookmarksOnBookmarkBar);
322 int num_folders_on_bookmark_bar =
323 pref->GetInteger(prefs::kNumFoldersOnBookmarkBar);
324 int num_bookmarks_in_other_bookmarks_folder =
325 pref->GetInteger(prefs::kNumBookmarksInOtherBookmarkFolder);
326 int num_folders_in_other_bookmarks_folder =
327 pref->GetInteger(prefs::kNumFoldersInOtherBookmarkFolder);
328 {
329 OPEN_ELEMENT_FOR_SCOPE("bookmarklocation");
330 WriteAttribute("name", "full-tree");
331 WriteIntAttribute("foldercount",
332 num_folders_on_bookmark_bar + num_folders_in_other_bookmarks_folder);
333 WriteIntAttribute("itemcount",
334 num_bookmarks_on_bookmark_bar +
335 num_bookmarks_in_other_bookmarks_folder);
336 }
337 {
338 OPEN_ELEMENT_FOR_SCOPE("bookmarklocation");
339 WriteAttribute("name", "toolbar");
340 WriteIntAttribute("foldercount", num_folders_on_bookmark_bar);
341 WriteIntAttribute("itemcount", num_bookmarks_on_bookmark_bar);
342 }
343 }
344
345 {
346 OPEN_ELEMENT_FOR_SCOPE("keywords");
347 WriteIntAttribute("count", pref->GetInteger(prefs::kNumKeywords));
348 }
349
350 if (profile_metrics)
351 WriteAllProfilesMetrics(*profile_metrics);
initial.commit09911bf2008-07-26 23:55:29352}
353
354void MetricsLog::WriteAllProfilesMetrics(
355 const DictionaryValue& all_profiles_metrics) {
[email protected]57ecc4b2010-08-11 03:02:51356 const std::string profile_prefix(prefs::kProfilePrefix);
initial.commit09911bf2008-07-26 23:55:29357 for (DictionaryValue::key_iterator i = all_profiles_metrics.begin_keys();
358 i != all_profiles_metrics.end_keys(); ++i) {
[email protected]e7b418b2010-07-30 19:47:47359 const std::string& key_name = *i;
initial.commit09911bf2008-07-26 23:55:29360 if (key_name.compare(0, profile_prefix.size(), profile_prefix) == 0) {
361 DictionaryValue* profile;
[email protected]4dad9ad82009-11-25 20:47:52362 if (all_profiles_metrics.GetDictionaryWithoutPathExpansion(key_name,
363 &profile))
initial.commit09911bf2008-07-26 23:55:29364 WriteProfileMetrics(key_name.substr(profile_prefix.size()), *profile);
365 }
366 }
367}
368
[email protected]e7b418b2010-07-30 19:47:47369void MetricsLog::WriteProfileMetrics(const std::string& profileidhash,
initial.commit09911bf2008-07-26 23:55:29370 const DictionaryValue& profile_metrics) {
371 OPEN_ELEMENT_FOR_SCOPE("userprofile");
[email protected]e7b418b2010-07-30 19:47:47372 WriteAttribute("profileidhash", profileidhash);
initial.commit09911bf2008-07-26 23:55:29373 for (DictionaryValue::key_iterator i = profile_metrics.begin_keys();
374 i != profile_metrics.end_keys(); ++i) {
375 Value* value;
[email protected]4dad9ad82009-11-25 20:47:52376 if (profile_metrics.GetWithoutPathExpansion(*i, &value)) {
[email protected]e7b418b2010-07-30 19:47:47377 DCHECK(*i != "id");
initial.commit09911bf2008-07-26 23:55:29378 switch (value->GetType()) {
379 case Value::TYPE_STRING: {
[email protected]5e324b72008-12-18 00:07:59380 std::string string_value;
initial.commit09911bf2008-07-26 23:55:29381 if (value->GetAsString(&string_value)) {
382 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]e7b418b2010-07-30 19:47:47383 WriteAttribute("name", *i);
[email protected]5e324b72008-12-18 00:07:59384 WriteAttribute("value", string_value);
initial.commit09911bf2008-07-26 23:55:29385 }
386 break;
387 }
388
389 case Value::TYPE_BOOLEAN: {
390 bool bool_value;
391 if (value->GetAsBoolean(&bool_value)) {
392 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]e7b418b2010-07-30 19:47:47393 WriteAttribute("name", *i);
initial.commit09911bf2008-07-26 23:55:29394 WriteIntAttribute("value", bool_value ? 1 : 0);
395 }
396 break;
397 }
398
399 case Value::TYPE_INTEGER: {
400 int int_value;
401 if (value->GetAsInteger(&int_value)) {
402 OPEN_ELEMENT_FOR_SCOPE("profileparam");
[email protected]e7b418b2010-07-30 19:47:47403 WriteAttribute("name", *i);
initial.commit09911bf2008-07-26 23:55:29404 WriteIntAttribute("value", int_value);
405 }
406 break;
407 }
408
409 default:
410 NOTREACHED();
411 break;
412 }
413 }
414 }
415}
416
417void MetricsLog::RecordOmniboxOpenedURL(const AutocompleteLog& log) {
418 DCHECK(!locked_);
419
[email protected]ffaf78a2008-11-12 17:38:33420 OPEN_ELEMENT_FOR_SCOPE("uielement");
initial.commit09911bf2008-07-26 23:55:29421 WriteAttribute("action", "autocomplete");
422 WriteAttribute("targetidhash", "");
423 // TODO(kochi): Properly track windows.
424 WriteIntAttribute("window", 0);
425 WriteCommonEventAttributes();
426
[email protected]ffaf78a2008-11-12 17:38:33427 {
428 OPEN_ELEMENT_FOR_SCOPE("autocomplete");
initial.commit09911bf2008-07-26 23:55:29429
[email protected]ffaf78a2008-11-12 17:38:33430 WriteIntAttribute("typedlength", static_cast<int>(log.text.length()));
431 WriteIntAttribute("selectedindex", static_cast<int>(log.selected_index));
432 WriteIntAttribute("completedlength",
433 static_cast<int>(log.inline_autocompleted_length));
[email protected]381e2992008-12-16 01:41:00434 const std::string input_type(
435 AutocompleteInput::TypeToString(log.input_type));
436 if (!input_type.empty())
437 WriteAttribute("inputtype", input_type);
initial.commit09911bf2008-07-26 23:55:29438
[email protected]ffaf78a2008-11-12 17:38:33439 for (AutocompleteResult::const_iterator i(log.result.begin());
440 i != log.result.end(); ++i) {
441 OPEN_ELEMENT_FOR_SCOPE("autocompleteitem");
442 if (i->provider)
443 WriteAttribute("provider", i->provider->name());
[email protected]381e2992008-12-16 01:41:00444 const std::string result_type(AutocompleteMatch::TypeToString(i->type));
445 if (!result_type.empty())
446 WriteAttribute("resulttype", result_type);
[email protected]ffaf78a2008-11-12 17:38:33447 WriteIntAttribute("relevance", i->relevance);
448 WriteIntAttribute("isstarred", i->starred ? 1 : 0);
449 }
initial.commit09911bf2008-07-26 23:55:29450 }
initial.commit09911bf2008-07-26 23:55:29451
452 ++num_events_;
453}