OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/log_private/log_private_api.h" | 5 #include "chrome/browser/extensions/api/log_private/log_private_api.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
| 10 #include "base/command_line.h" |
10 #include "base/json/json_writer.h" | 11 #include "base/json/json_writer.h" |
11 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/memory/linked_ptr.h" | 14 #include "base/memory/linked_ptr.h" |
14 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
15 #include "chrome/browser/browser_process.h" | 16 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/download/download_prefs.h" |
| 18 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h" |
16 #include "chrome/browser/extensions/api/log_private/filter_handler.h" | 19 #include "chrome/browser/extensions/api/log_private/filter_handler.h" |
17 #include "chrome/browser/extensions/api/log_private/log_parser.h" | 20 #include "chrome/browser/extensions/api/log_private/log_parser.h" |
18 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" | 21 #include "chrome/browser/extensions/api/log_private/syslog_parser.h" |
19 #include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h" | 22 #include "chrome/browser/feedback/system_logs/scrubbed_system_logs_fetcher.h" |
20 #include "chrome/browser/io_thread.h" | 23 #include "chrome/browser/io_thread.h" |
21 #include "chrome/browser/net/chrome_net_log.h" | 24 #include "chrome/browser/net/chrome_net_log.h" |
22 #include "chrome/browser/profiles/profile.h" | 25 #include "chrome/browser/profiles/profile.h" |
| 26 #include "chrome/browser/profiles/profile_manager.h" |
23 #include "chrome/common/extensions/api/log_private.h" | 27 #include "chrome/common/extensions/api/log_private.h" |
| 28 #include "chrome/common/logging_chrome.h" |
| 29 #include "content/public/browser/render_process_host.h" |
24 #include "extensions/browser/event_router.h" | 30 #include "extensions/browser/event_router.h" |
25 #include "extensions/browser/extension_function.h" | 31 #include "extensions/browser/extension_function.h" |
26 #include "extensions/browser/extension_registry.h" | 32 #include "extensions/browser/extension_registry.h" |
| 33 #include "extensions/browser/granted_file_entry.h" |
| 34 |
| 35 #if defined(OS_CHROMEOS) |
| 36 #include "chrome/browser/chromeos/system_logs/debug_log_writer.h" |
| 37 #endif |
27 | 38 |
28 using content::BrowserThread; | 39 using content::BrowserThread; |
29 | 40 |
30 namespace events { | 41 namespace events { |
31 const char kOnAddNetInternalsEntries[] = "logPrivate.onAddNetInternalsEntries"; | 42 const char kOnCapturedEvents[] = "logPrivate.onCapturedEvents"; |
32 } // namespace events | 43 } // namespace events |
33 | 44 |
34 namespace extensions { | 45 namespace extensions { |
35 namespace { | 46 namespace { |
36 | 47 |
| 48 const char kAppLogsSubdir[] = "apps"; |
| 49 const char kLogDumpsSubdir[] = "log_dumps"; |
| 50 const char kLogFileNameBase[] = "net-internals"; |
37 const int kNetLogEventDelayMilliseconds = 100; | 51 const int kNetLogEventDelayMilliseconds = 100; |
38 | 52 |
| 53 // Gets sequenced task runner for file specific calls within this API. |
| 54 scoped_refptr<base::SequencedTaskRunner> GetSequencedTaskRunner() { |
| 55 base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool(); |
| 56 return pool->GetSequencedTaskRunnerWithShutdownBehavior( |
| 57 pool->GetNamedSequenceToken(FileResource::kSequenceToken), |
| 58 base::SequencedWorkerPool::BLOCK_SHUTDOWN); |
| 59 } |
| 60 |
| 61 // Checks if we are running on sequenced task runner thread. |
| 62 bool IsRunningOnSequenceThread() { |
| 63 base::SequencedWorkerPool* pool = content::BrowserThread::GetBlockingPool(); |
| 64 return pool->IsRunningSequenceOnCurrentThread( |
| 65 pool->GetNamedSequenceToken(FileResource::kSequenceToken)); |
| 66 } |
| 67 |
39 scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { | 68 scoped_ptr<LogParser> CreateLogParser(const std::string& log_type) { |
40 if (log_type == "syslog") | 69 if (log_type == "syslog") |
41 return scoped_ptr<LogParser>(new SyslogParser()); | 70 return scoped_ptr<LogParser>(new SyslogParser()); |
42 // TODO(shinfan): Add more parser here | 71 // TODO(shinfan): Add more parser here |
43 | 72 |
44 NOTREACHED() << "Invalid log type: " << log_type; | 73 NOTREACHED() << "Invalid log type: " << log_type; |
45 return scoped_ptr<LogParser>(); | 74 return scoped_ptr<LogParser>(); |
46 } | 75 } |
47 | 76 |
48 void CollectLogInfo( | 77 void CollectLogInfo( |
49 FilterHandler* filter_handler, | 78 FilterHandler* filter_handler, |
50 system_logs::SystemLogsResponse* logs, | 79 system_logs::SystemLogsResponse* logs, |
51 std::vector<linked_ptr<api::log_private::LogEntry> >* output) { | 80 std::vector<linked_ptr<api::log_private::LogEntry> >* output) { |
52 for (system_logs::SystemLogsResponse::const_iterator | 81 for (system_logs::SystemLogsResponse::const_iterator |
53 request_it = logs->begin(); request_it != logs->end(); ++request_it) { | 82 request_it = logs->begin(); request_it != logs->end(); ++request_it) { |
54 if (!filter_handler->IsValidSource(request_it->first)) { | 83 if (!filter_handler->IsValidSource(request_it->first)) { |
55 continue; | 84 continue; |
56 } | 85 } |
57 scoped_ptr<LogParser> parser(CreateLogParser(request_it->first)); | 86 scoped_ptr<LogParser> parser(CreateLogParser(request_it->first)); |
58 if (parser) { | 87 if (parser) { |
59 parser->Parse(request_it->second, output, filter_handler); | 88 parser->Parse(request_it->second, output, filter_handler); |
60 } | 89 } |
61 } | 90 } |
62 } | 91 } |
63 | 92 |
| 93 // Returns directory location of app-specific logs that are initiated with |
| 94 // logPrivate.startEventRecorder() calls - /home/chronos/user/log/apps |
| 95 base::FilePath GetAppLogDirectory() { |
| 96 return logging::GetSessionLogDir(*CommandLine::ForCurrentProcess()) |
| 97 .Append(kAppLogsSubdir); |
| 98 } |
| 99 |
| 100 // Returns directory location where logs dumps initiated with chrome.dumpLogs |
| 101 // will be stored - /home/chronos/<user_profile_dir>/Downloads/log_dumps |
| 102 base::FilePath GetLogDumpDirectory(content::BrowserContext* context) { |
| 103 const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(context); |
| 104 return prefs->DownloadPath().Append(kLogDumpsSubdir); |
| 105 } |
| 106 |
| 107 // Removes direcotry content of |logs_dumps| and |app_logs_dir| (only for the |
| 108 // primary profile). |
| 109 void CleanUpLeftoverLogs(bool is_primary_profile, |
| 110 const base::FilePath& app_logs_dir, |
| 111 const base::FilePath& logs_dumps) { |
| 112 LOG(WARNING) << "Deleting " << app_logs_dir.value(); |
| 113 LOG(WARNING) << "Deleting " << logs_dumps.value(); |
| 114 |
| 115 DCHECK(IsRunningOnSequenceThread()); |
| 116 base::DeleteFile(logs_dumps, true); |
| 117 |
| 118 // App-specific logs are stored in /home/chronos/user/log/apps directory that |
| 119 // is shared between all profiles in multi-profile case. We should not |
| 120 // nuke it for non-primary profiles. |
| 121 if (!is_primary_profile) |
| 122 return; |
| 123 |
| 124 base::DeleteFile(app_logs_dir, true); |
| 125 } |
| 126 |
64 } // namespace | 127 } // namespace |
65 | 128 |
| 129 const char FileResource::kSequenceToken[] = "log_api_files"; |
| 130 |
| 131 FileResource::FileResource(const std::string& owner_extension_id, |
| 132 const base::FilePath& path) |
| 133 : ApiResource(owner_extension_id), path_(path) { |
| 134 } |
| 135 |
| 136 FileResource::~FileResource() { |
| 137 base::DeleteFile(path_, true); |
| 138 } |
| 139 |
| 140 bool FileResource::IsPersistent() const { |
| 141 return false; |
| 142 } |
| 143 |
66 // static | 144 // static |
67 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { | 145 LogPrivateAPI* LogPrivateAPI::Get(content::BrowserContext* context) { |
68 return GetFactoryInstance()->Get(context); | 146 LogPrivateAPI* api = GetFactoryInstance()->Get(context); |
| 147 api->Initialize(); |
| 148 return api; |
69 } | 149 } |
70 | 150 |
71 LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) | 151 LogPrivateAPI::LogPrivateAPI(content::BrowserContext* context) |
72 : browser_context_(context), | 152 : browser_context_(context), |
73 logging_net_internals_(false), | 153 logging_net_internals_(false), |
74 extension_registry_observer_(this) { | 154 event_sink_(api::log_private::EVENT_SINK_CAPTURE), |
75 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); | 155 extension_registry_observer_(this), |
| 156 log_file_resources_(context), |
| 157 initialized_(false) { |
76 } | 158 } |
77 | 159 |
78 LogPrivateAPI::~LogPrivateAPI() { | 160 LogPrivateAPI::~LogPrivateAPI() { |
79 } | 161 } |
80 | 162 |
81 void LogPrivateAPI::StartNetInternalsWatch(const std::string& extension_id) { | 163 void LogPrivateAPI::StartNetInternalsWatch( |
| 164 const std::string& extension_id, |
| 165 api::log_private::EventSink event_sink, |
| 166 const base::Closure& closure) { |
82 net_internal_watches_.insert(extension_id); | 167 net_internal_watches_.insert(extension_id); |
83 BrowserThread::PostTask( | 168 |
84 BrowserThread::IO, FROM_HERE, | 169 // Nuke any leftover app-specific or dumped log files from previous sessions. |
| 170 BrowserThread::PostTaskAndReply( |
| 171 BrowserThread::IO, |
| 172 FROM_HERE, |
85 base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, | 173 base::Bind(&LogPrivateAPI::MaybeStartNetInternalLogging, |
86 base::Unretained(this))); | 174 base::Unretained(this), |
| 175 extension_id, |
| 176 g_browser_process->io_thread(), |
| 177 event_sink), |
| 178 closure); |
87 } | 179 } |
88 | 180 |
89 void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id) { | 181 void LogPrivateAPI::StopNetInternalsWatch(const std::string& extension_id, |
| 182 const base::Closure& closure) { |
90 net_internal_watches_.erase(extension_id); | 183 net_internal_watches_.erase(extension_id); |
91 MaybeStopNetInternalLogging(); | 184 MaybeStopNetInternalLogging(closure); |
| 185 } |
| 186 |
| 187 void LogPrivateAPI::StopAllWatches(const std::string& extension_id, |
| 188 const base::Closure& closure) { |
| 189 StopNetInternalsWatch(extension_id, closure); |
| 190 } |
| 191 |
| 192 void LogPrivateAPI::RegisterTempFile(const std::string& owner_extension_id, |
| 193 const base::FilePath& file_path) { |
| 194 if (!IsRunningOnSequenceThread()) { |
| 195 GetSequencedTaskRunner()->PostTask( |
| 196 FROM_HERE, |
| 197 base::Bind(&LogPrivateAPI::RegisterTempFile, |
| 198 base::Unretained(this), |
| 199 owner_extension_id, |
| 200 file_path)); |
| 201 return; |
| 202 } |
| 203 |
| 204 log_file_resources_.Add(new FileResource(owner_extension_id, file_path)); |
92 } | 205 } |
93 | 206 |
94 static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > | 207 static base::LazyInstance<BrowserContextKeyedAPIFactory<LogPrivateAPI> > |
95 g_factory = LAZY_INSTANCE_INITIALIZER; | 208 g_factory = LAZY_INSTANCE_INITIALIZER; |
96 | 209 |
97 // static | 210 // static |
98 BrowserContextKeyedAPIFactory<LogPrivateAPI>* | 211 BrowserContextKeyedAPIFactory<LogPrivateAPI>* |
99 LogPrivateAPI::GetFactoryInstance() { | 212 LogPrivateAPI::GetFactoryInstance() { |
100 return g_factory.Pointer(); | 213 return g_factory.Pointer(); |
101 } | 214 } |
102 | 215 |
103 void LogPrivateAPI::OnAddEntry(const net::NetLog::Entry& entry) { | 216 void LogPrivateAPI::OnAddEntry(const net::NetLog::Entry& entry) { |
104 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 217 // We could receive events on whatever thread they happen to be generated, |
| 218 // since we are only interested in network events, we should ignore any |
| 219 // other thread than BrowserThread::IO. |
| 220 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 221 return; |
| 222 } |
| 223 |
105 if (!pending_entries_.get()) { | 224 if (!pending_entries_.get()) { |
106 pending_entries_.reset(new base::ListValue()); | 225 pending_entries_.reset(new base::ListValue()); |
107 BrowserThread::PostDelayedTask( | 226 BrowserThread::PostDelayedTask( |
108 BrowserThread::IO, FROM_HERE, | 227 BrowserThread::IO, FROM_HERE, |
109 base::Bind(&LogPrivateAPI::PostPendingEntries, base::Unretained(this)), | 228 base::Bind(&LogPrivateAPI::PostPendingEntries, base::Unretained(this)), |
110 base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds)); | 229 base::TimeDelta::FromMilliseconds(kNetLogEventDelayMilliseconds)); |
111 } | 230 } |
112 pending_entries_->Append(entry.ToValue()); | 231 pending_entries_->Append(entry.ToValue()); |
113 } | 232 } |
114 | 233 |
115 void LogPrivateAPI::PostPendingEntries() { | 234 void LogPrivateAPI::PostPendingEntries() { |
116 BrowserThread::PostTask( | 235 BrowserThread::PostTask( |
117 BrowserThread::UI, FROM_HERE, | 236 BrowserThread::UI, FROM_HERE, |
118 base::Bind(&LogPrivateAPI:: AddEntriesOnUI, | 237 base::Bind(&LogPrivateAPI:: AddEntriesOnUI, |
119 base::Unretained(this), | 238 base::Unretained(this), |
120 base::Passed(&pending_entries_))); | 239 base::Passed(&pending_entries_))); |
121 } | 240 } |
122 | 241 |
123 void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) { | 242 void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) { |
124 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 243 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
125 | 244 |
126 for (std::set<std::string>::iterator ix = net_internal_watches_.begin(); | 245 for (std::set<std::string>::iterator ix = net_internal_watches_.begin(); |
127 ix != net_internal_watches_.end(); ++ix) { | 246 ix != net_internal_watches_.end(); ++ix) { |
128 // Create the event's arguments value. | 247 // Create the event's arguments value. |
129 scoped_ptr<base::ListValue> event_args(new base::ListValue()); | 248 scoped_ptr<base::ListValue> event_args(new base::ListValue()); |
130 event_args->Append(value->DeepCopy()); | 249 event_args->Append(value->DeepCopy()); |
131 scoped_ptr<Event> event(new Event(events::kOnAddNetInternalsEntries, | 250 scoped_ptr<Event> event( |
132 event_args.Pass())); | 251 new Event(events::kOnCapturedEvents, event_args.Pass())); |
133 EventRouter::Get(browser_context_) | 252 EventRouter::Get(browser_context_) |
134 ->DispatchEventToExtension(*ix, event.Pass()); | 253 ->DispatchEventToExtension(*ix, event.Pass()); |
135 } | 254 } |
136 } | 255 } |
137 | 256 |
138 void LogPrivateAPI::MaybeStartNetInternalLogging() { | 257 void LogPrivateAPI::InitializeNetLogger(const std::string& owner_extension_id, |
| 258 net::NetLogLogger** net_log_logger) { |
| 259 DCHECK(IsRunningOnSequenceThread()); |
| 260 (*net_log_logger) = NULL; |
| 261 |
| 262 // Create app-specific subdirectory in session logs folder. |
| 263 base::FilePath app_log_dir = GetAppLogDirectory().Append(owner_extension_id); |
| 264 if (!base::DirectoryExists(app_log_dir)) { |
| 265 if (!base::CreateDirectory(app_log_dir)) { |
| 266 LOG(ERROR) << "Could not create dir " << app_log_dir.value(); |
| 267 return; |
| 268 } |
| 269 } |
| 270 |
| 271 base::FilePath file_path = app_log_dir.Append(kLogFileNameBase); |
| 272 file_path = logging::GenerateTimestampedName(file_path, base::Time::Now()); |
| 273 FILE* file = NULL; |
| 274 file = fopen(file_path.value().c_str(), "w"); |
| 275 if (file == NULL) { |
| 276 LOG(ERROR) << "Could not open " << file_path.value(); |
| 277 return; |
| 278 } |
| 279 |
| 280 RegisterTempFile(owner_extension_id, file_path); |
| 281 scoped_ptr<base::Value> constants(net::NetLogLogger::GetConstants()); |
| 282 *net_log_logger = new net::NetLogLogger(file, *constants); |
| 283 (*net_log_logger)->set_log_level(net::NetLog::LOG_ALL_BUT_BYTES); |
| 284 } |
| 285 |
| 286 void LogPrivateAPI::StartObservingNetEvents( |
| 287 IOThread* io_thread, |
| 288 net::NetLogLogger** net_log_logger) { |
| 289 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 290 if (!(*net_log_logger)) |
| 291 return; |
| 292 |
| 293 net_log_logger_.reset(*net_log_logger); |
| 294 net_log_logger_->StartObserving(io_thread->net_log()); |
| 295 } |
| 296 |
| 297 void LogPrivateAPI::MaybeStartNetInternalLogging( |
| 298 const std::string& caller_extension_id, |
| 299 IOThread* io_thread, |
| 300 api::log_private::EventSink event_sink) { |
139 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 301 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
140 if (!logging_net_internals_) { | 302 if (!logging_net_internals_) { |
141 g_browser_process->io_thread()->net_log()->AddThreadSafeObserver( | |
142 this, net::NetLog::LOG_ALL_BUT_BYTES); | |
143 logging_net_internals_ = true; | 303 logging_net_internals_ = true; |
| 304 event_sink_ = event_sink; |
| 305 switch (event_sink_) { |
| 306 case api::log_private::EVENT_SINK_CAPTURE: { |
| 307 io_thread->net_log()->AddThreadSafeObserver( |
| 308 this, net::NetLog::LOG_ALL_BUT_BYTES); |
| 309 break; |
| 310 } |
| 311 case api::log_private::EVENT_SINK_FILE: { |
| 312 net::NetLogLogger** net_logger_ptr = new net::NetLogLogger* [1]; |
| 313 // Initialize net logger on the blocking pool and start observing event |
| 314 // with in on IO thread. |
| 315 GetSequencedTaskRunner()->PostTaskAndReply( |
| 316 FROM_HERE, |
| 317 base::Bind(&LogPrivateAPI::InitializeNetLogger, |
| 318 base::Unretained(this), |
| 319 caller_extension_id, |
| 320 net_logger_ptr), |
| 321 base::Bind(&LogPrivateAPI::StartObservingNetEvents, |
| 322 base::Unretained(this), |
| 323 io_thread, |
| 324 base::Owned(net_logger_ptr))); |
| 325 break; |
| 326 } |
| 327 case api::log_private::EVENT_SINK_NONE: { |
| 328 NOTREACHED(); |
| 329 break; |
| 330 } |
| 331 } |
144 } | 332 } |
145 } | 333 } |
146 | 334 |
147 void LogPrivateAPI::MaybeStopNetInternalLogging() { | 335 void LogPrivateAPI::MaybeStopNetInternalLogging(const base::Closure& closure) { |
148 if (net_internal_watches_.empty()) { | 336 if (net_internal_watches_.empty()) { |
149 BrowserThread::PostTask( | 337 if (closure.is_null()) { |
150 BrowserThread::IO, FROM_HERE, | 338 BrowserThread::PostTask( |
151 base::Bind(&LogPrivateAPI:: StopNetInternalLogging, | 339 BrowserThread::IO, |
152 base::Unretained(this))); | 340 FROM_HERE, |
| 341 base::Bind(&LogPrivateAPI::StopNetInternalLogging, |
| 342 base::Unretained(this))); |
| 343 } else { |
| 344 BrowserThread::PostTaskAndReply( |
| 345 BrowserThread::IO, |
| 346 FROM_HERE, |
| 347 base::Bind(&LogPrivateAPI::StopNetInternalLogging, |
| 348 base::Unretained(this)), |
| 349 closure); |
| 350 } |
153 } | 351 } |
154 } | 352 } |
155 | 353 |
156 void LogPrivateAPI::StopNetInternalLogging() { | 354 void LogPrivateAPI::StopNetInternalLogging() { |
157 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 355 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
158 if (net_log() && logging_net_internals_) { | 356 if (net_log() && logging_net_internals_) { |
159 net_log()->RemoveThreadSafeObserver(this); | |
160 logging_net_internals_ = false; | 357 logging_net_internals_ = false; |
| 358 switch (event_sink_) { |
| 359 case api::log_private::EVENT_SINK_CAPTURE: |
| 360 net_log()->RemoveThreadSafeObserver(this); |
| 361 break; |
| 362 case api::log_private::EVENT_SINK_FILE: |
| 363 net_log_logger_->StopObserving(); |
| 364 net_log_logger_.reset(); |
| 365 break; |
| 366 case api::log_private::EVENT_SINK_NONE: |
| 367 NOTREACHED(); |
| 368 break; |
| 369 } |
161 } | 370 } |
162 } | 371 } |
163 | 372 |
| 373 void LogPrivateAPI::Initialize() { |
| 374 if (initialized_) |
| 375 return; |
| 376 |
| 377 // Clean up temp files and folders from the previous sessions. |
| 378 initialized_ = true; |
| 379 extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_)); |
| 380 GetSequencedTaskRunner()->PostTask( |
| 381 FROM_HERE, |
| 382 base::Bind(&CleanUpLeftoverLogs, |
| 383 Profile::FromBrowserContext(browser_context_) == |
| 384 ProfileManager::GetPrimaryUserProfile(), |
| 385 GetAppLogDirectory(), |
| 386 GetLogDumpDirectory(browser_context_))); |
| 387 } |
| 388 |
164 void LogPrivateAPI::OnExtensionUnloaded( | 389 void LogPrivateAPI::OnExtensionUnloaded( |
165 content::BrowserContext* browser_context, | 390 content::BrowserContext* browser_context, |
166 const Extension* extension, | 391 const Extension* extension, |
167 UnloadedExtensionInfo::Reason reason) { | 392 UnloadedExtensionInfo::Reason reason) { |
168 StopNetInternalsWatch(extension->id()); | 393 StopNetInternalsWatch(extension->id(), base::Closure()); |
169 } | 394 } |
170 | 395 |
171 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { | 396 LogPrivateGetHistoricalFunction::LogPrivateGetHistoricalFunction() { |
172 } | 397 } |
173 | 398 |
174 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() { | 399 LogPrivateGetHistoricalFunction::~LogPrivateGetHistoricalFunction() { |
175 } | 400 } |
176 | 401 |
177 bool LogPrivateGetHistoricalFunction::RunAsync() { | 402 bool LogPrivateGetHistoricalFunction::RunAsync() { |
178 // Get parameters | 403 // Get parameters |
(...skipping 22 matching lines...) Expand all Loading... |
201 | 426 |
202 // Prepare result | 427 // Prepare result |
203 api::log_private::Result result; | 428 api::log_private::Result result; |
204 result.data = data; | 429 result.data = data; |
205 api::log_private::Filter::Populate( | 430 api::log_private::Filter::Populate( |
206 *((filter_handler_->GetFilter())->ToValue()), &result.filter); | 431 *((filter_handler_->GetFilter())->ToValue()), &result.filter); |
207 SetResult(result.ToValue().release()); | 432 SetResult(result.ToValue().release()); |
208 SendResponse(true); | 433 SendResponse(true); |
209 } | 434 } |
210 | 435 |
211 LogPrivateStartNetInternalsWatchFunction:: | 436 LogPrivateStartEventRecorderFunction::LogPrivateStartEventRecorderFunction() { |
212 LogPrivateStartNetInternalsWatchFunction() { | |
213 } | 437 } |
214 | 438 |
215 LogPrivateStartNetInternalsWatchFunction:: | 439 LogPrivateStartEventRecorderFunction::~LogPrivateStartEventRecorderFunction() { |
216 ~LogPrivateStartNetInternalsWatchFunction() { | |
217 } | 440 } |
218 | 441 |
219 bool LogPrivateStartNetInternalsWatchFunction::RunSync() { | 442 bool LogPrivateStartEventRecorderFunction::RunAsync() { |
220 LogPrivateAPI::Get(GetProfile())->StartNetInternalsWatch(extension_id()); | 443 scoped_ptr<api::log_private::StartEventRecorder::Params> params( |
| 444 api::log_private::StartEventRecorder::Params::Create(*args_)); |
| 445 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 446 switch (params->event_type) { |
| 447 case api::log_private::EVENT_TYPE_NETWORK: |
| 448 LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context())) |
| 449 ->StartNetInternalsWatch( |
| 450 extension_id(), |
| 451 params->sink, |
| 452 base::Bind( |
| 453 &LogPrivateStartEventRecorderFunction::OnEventRecorderStarted, |
| 454 this)); |
| 455 break; |
| 456 case api::log_private::EVENT_TYPE_NONE: |
| 457 NOTREACHED(); |
| 458 return false; |
| 459 } |
| 460 |
221 return true; | 461 return true; |
222 } | 462 } |
223 | 463 |
224 LogPrivateStopNetInternalsWatchFunction:: | 464 void LogPrivateStartEventRecorderFunction::OnEventRecorderStarted() { |
225 LogPrivateStopNetInternalsWatchFunction() { | 465 SendResponse(true); |
226 } | 466 } |
227 | 467 |
228 LogPrivateStopNetInternalsWatchFunction:: | 468 LogPrivateStopEventRecorderFunction::LogPrivateStopEventRecorderFunction() { |
229 ~LogPrivateStopNetInternalsWatchFunction() { | |
230 } | 469 } |
231 | 470 |
232 bool LogPrivateStopNetInternalsWatchFunction::RunSync() { | 471 LogPrivateStopEventRecorderFunction::~LogPrivateStopEventRecorderFunction() { |
233 LogPrivateAPI::Get(GetProfile())->StopNetInternalsWatch(extension_id()); | 472 } |
| 473 |
| 474 bool LogPrivateStopEventRecorderFunction::RunAsync() { |
| 475 scoped_ptr<api::log_private::StopEventRecorder::Params> params( |
| 476 api::log_private::StopEventRecorder::Params::Create(*args_)); |
| 477 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 478 switch (params->event_type) { |
| 479 case api::log_private::EVENT_TYPE_NETWORK: |
| 480 LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context())) |
| 481 ->StopNetInternalsWatch( |
| 482 extension_id(), |
| 483 base::Bind( |
| 484 &LogPrivateStopEventRecorderFunction::OnEventRecorderStopped, |
| 485 this)); |
| 486 break; |
| 487 case api::log_private::EVENT_TYPE_NONE: |
| 488 NOTREACHED(); |
| 489 return false; |
| 490 } |
234 return true; | 491 return true; |
235 } | 492 } |
236 | 493 |
| 494 void LogPrivateStopEventRecorderFunction::OnEventRecorderStopped() { |
| 495 SendResponse(true); |
| 496 } |
| 497 |
| 498 LogPrivateDumpLogsFunction::LogPrivateDumpLogsFunction() { |
| 499 } |
| 500 |
| 501 LogPrivateDumpLogsFunction::~LogPrivateDumpLogsFunction() { |
| 502 } |
| 503 |
| 504 bool LogPrivateDumpLogsFunction::RunAsync() { |
| 505 LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context())) |
| 506 ->StopAllWatches( |
| 507 extension_id(), |
| 508 base::Bind(&LogPrivateDumpLogsFunction::OnStopAllWatches, this)); |
| 509 return true; |
| 510 } |
| 511 |
| 512 void LogPrivateDumpLogsFunction::OnStopAllWatches() { |
| 513 chromeos::DebugLogWriter::StoreCombinedLogs( |
| 514 GetLogDumpDirectory(browser_context()).Append(extension_id()), |
| 515 FileResource::kSequenceToken, |
| 516 base::Bind(&LogPrivateDumpLogsFunction::OnStoreLogsCompleted, this)); |
| 517 } |
| 518 |
| 519 void LogPrivateDumpLogsFunction::OnStoreLogsCompleted( |
| 520 const base::FilePath& log_path, |
| 521 bool succeeded) { |
| 522 if (succeeded) { |
| 523 LogPrivateAPI::Get(Profile::FromBrowserContext(browser_context())) |
| 524 ->RegisterTempFile(extension_id(), log_path); |
| 525 } |
| 526 |
| 527 scoped_ptr<base::DictionaryValue> response(new base::DictionaryValue()); |
| 528 extensions::GrantedFileEntry file_entry = |
| 529 extensions::app_file_handler_util::CreateFileEntry( |
| 530 Profile::FromBrowserContext(browser_context()), |
| 531 GetExtension(), |
| 532 render_view_host_->GetProcess()->GetID(), |
| 533 log_path, |
| 534 false); |
| 535 |
| 536 base::DictionaryValue* entry = new base::DictionaryValue(); |
| 537 entry->SetString("fileSystemId", file_entry.filesystem_id); |
| 538 entry->SetString("baseName", file_entry.registered_name); |
| 539 entry->SetString("id", file_entry.id); |
| 540 entry->SetBoolean("isDirectory", false); |
| 541 base::ListValue* entry_list = new base::ListValue(); |
| 542 entry_list->Append(entry); |
| 543 response->Set("entries", entry_list); |
| 544 response->SetBoolean("multiple", false); |
| 545 SetResult(response.release()); |
| 546 SendResponse(succeeded); |
| 547 } |
| 548 |
237 } // namespace extensions | 549 } // namespace extensions |
OLD | NEW |