1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// found in the LICENSE file.
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/net_log_logger.h"
6eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
7eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include <stdio.h>
8eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/json/json_writer.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/logging.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/memory/scoped_ptr.h"
12eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/strings/string_number_conversions.h"
13eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/values.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/address_family.h"
15eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/load_states.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/quic/quic_protocol.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/quic/quic_utils.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
19eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace net {
20eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// This should be incremented when significant changes are made that will
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// invalidate the old loading code.
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const int kLogFormatVersion = 1;
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochNetLogLogger::NetLogLogger(FILE* file, const base::Value& constants)
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    : file_(file), added_events_(false) {
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DCHECK(file);
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Write constants to the output file.  This allows loading files that have
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // different source and event types, as they may be added and removed
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // between Chrome versions.
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string json;
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::JSONWriter::Write(&constants, &json);
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  fprintf(file_.get(), "{\"constants\": %s,\n", json.c_str());
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  fprintf(file_.get(), "\"events\": [\n");
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochNetLogLogger::~NetLogLogger() {
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (file_.get())
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    fprintf(file_.get(), "]}");
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NetLogLogger::StartObserving(net::NetLog* net_log) {
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NetLogLogger::StopObserving() {
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  net_log()->RemoveThreadSafeObserver(this);
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid NetLogLogger::OnAddEntry(const net::NetLog::Entry& entry) {
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add a comma and newline for every event but the first.  Newlines are needed
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // so can load partial log files by just ignoring the last line.  For this to
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // work, lines cannot be pretty printed.
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  scoped_ptr<Value> value(entry.ToValue());
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  std::string json;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::JSONWriter::Write(value.get(), &json);
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  fprintf(file_.get(), "%s%s",
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          (added_events_ ? ",\n" : ""),
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch          json.c_str());
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  added_events_ = true;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::DictionaryValue* NetLogLogger::GetConstants() {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DictionaryValue* constants_dict = new DictionaryValue();
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Version of the file format.
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  constants_dict->SetInteger("logFormatVersion", kLogFormatVersion);
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add a dictionary with information on the relationship between event type
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // enums and their symbolic names.
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  constants_dict->Set("logEventTypes", net::NetLog::GetEventTypesAsValue());
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add a dictionary with information about the relationship between load flag
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // enums and their symbolic names.
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define LOAD_FLAG(label, value) \
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger(# label, static_cast<int>(value));
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/load_flags_list.h"
82eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#undef LOAD_FLAG
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
84eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("loadFlag", dict);
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add a dictionary with information about the relationship between load state
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // enums and their symbolic names.
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define LOAD_STATE(label) \
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger(# label, net::LOAD_STATE_ ## label);
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/load_states_list.h"
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#undef LOAD_STATE
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("loadState", dict);
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add information on the relationship between net error codes and their
101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // symbolic names.
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
105eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#define NET_ERROR(label, value) \
106eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger(# label, static_cast<int>(value));
107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/base/net_error_list.h"
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#undef NET_ERROR
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("netError", dict);
111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add information on the relationship between QUIC error codes and their
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // symbolic names.
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (net::QuicErrorCode error = net::QUIC_NO_ERROR;
119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         error < net::QUIC_LAST_ERROR;
120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         error = static_cast<net::QuicErrorCode>(error + 1)) {
121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dict->SetInteger(net::QuicUtils::ErrorToString(error),
122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       static_cast<int>(error));
123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("quicError", dict);
126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Add information on the relationship between QUIC RST_STREAM error codes
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // and their symbolic names.
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
133eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    for (net::QuicRstStreamErrorCode error = net::QUIC_STREAM_NO_ERROR;
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         error < net::QUIC_STREAM_LAST_ERROR;
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch         error = static_cast<net::QuicRstStreamErrorCode>(error + 1)) {
136eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      dict->SetInteger(net::QuicUtils::StreamErrorToString(error),
137eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                       static_cast<int>(error));
138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("quicRstStreamError", dict);
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Information about the relationship between event phase enums and their
144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // symbolic names.
145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("PHASE_BEGIN", net::NetLog::PHASE_BEGIN);
149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("PHASE_END", net::NetLog::PHASE_END);
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("PHASE_NONE", net::NetLog::PHASE_NONE);
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("logEventPhase", dict);
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Information about the relationship between source type enums and
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // their symbolic names.
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  constants_dict->Set("logSourceType", net::NetLog::GetSourceTypesAsValue());
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Information about the relationship between LogLevel enums and their
160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // symbolic names.
161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
164eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("LOG_ALL", net::NetLog::LOG_ALL);
165eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("LOG_ALL_BUT_BYTES", net::NetLog::LOG_ALL_BUT_BYTES);
166eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("LOG_BASIC", net::NetLog::LOG_BASIC);
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("logLevelType", dict);
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Information about the relationship between address family enums and
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // their symbolic names.
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    DictionaryValue* dict = new DictionaryValue();
175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("ADDRESS_FAMILY_UNSPECIFIED",
177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     net::ADDRESS_FAMILY_UNSPECIFIED);
178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("ADDRESS_FAMILY_IPV4",
179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     net::ADDRESS_FAMILY_IPV4);
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    dict->SetInteger("ADDRESS_FAMILY_IPV6",
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                     net::ADDRESS_FAMILY_IPV6);
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->Set("addressFamily", dict);
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Information about how the "time ticks" values we have given it relate to
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // actual system times. (We used time ticks throughout since they are stable
188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // across system clock changes).
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  {
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 cur_time_ms = (base::Time::Now() - base::Time()).InMilliseconds();
191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 cur_time_ticks_ms =
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds();
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // If we add this number to a time tick value, it gives the timestamp.
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 tick_to_time_ms = cur_time_ms - cur_time_ticks_ms;
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Chrome on all platforms stores times using the Windows epoch
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // (Jan 1 1601), but the javascript wants a unix epoch.
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // TODO(eroman): Getting the timestamp relative to the unix epoch should
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    //               be part of the time library.
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    const int64 kUnixEpochMs = 11644473600000LL;
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    int64 tick_to_unix_time_ms = tick_to_time_ms - kUnixEpochMs;
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Pass it as a string, since it may be too large to fit in an integer.
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    constants_dict->SetString("timeTickOffset",
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                              base::Int64ToString(tick_to_unix_time_ms));
208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // "clientInfo" key is required for some NetLogLogger log readers.
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // Provide a default empty value for compatibility.
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  constants_dict->Set("clientInfo", new DictionaryValue());
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return constants_dict;
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace net
218