Commit dc5cefc1 authored by tengs's avatar tengs Committed by Commit bot

Hook up PA_LOG() logs to chrome://proximity-auth WebUI.

BUG=409158
TEST=manual

Review URL: https://codereview.chromium.org/1135293002

Cr-Commit-Position: refs/heads/master@{#329877}
parent 2b496b6d
...@@ -37,16 +37,26 @@ LogBuffer* LogBuffer::GetInstance() { ...@@ -37,16 +37,26 @@ LogBuffer* LogBuffer::GetInstance() {
return &g_log_buffer.Get(); return &g_log_buffer.Get();
} }
void LogBuffer::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void LogBuffer::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void LogBuffer::AddLogMessage(const LogMessage& log_message) { void LogBuffer::AddLogMessage(const LogMessage& log_message) {
// Note: We may want to sort the messages by timestamp if there are cases // Note: We may want to sort the messages by timestamp if there are cases
// where logs are not added chronologically. // where logs are not added chronologically.
log_messages_.push_back(log_message); log_messages_.push_back(log_message);
if (log_messages_.size() > MaxBufferSize()) if (log_messages_.size() > MaxBufferSize())
log_messages_.pop_front(); log_messages_.pop_front();
FOR_EACH_OBSERVER(Observer, observers_, OnLogMessageAdded(log_message));
} }
void LogBuffer::Clear() { void LogBuffer::Clear() {
log_messages_.clear(); log_messages_.clear();
FOR_EACH_OBSERVER(Observer, observers_, OnLogBufferCleared());
} }
size_t LogBuffer::MaxBufferSize() const { size_t LogBuffer::MaxBufferSize() const {
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/observer_list.h"
#include "base/time/time.h" #include "base/time/time.h"
namespace proximity_auth { namespace proximity_auth {
...@@ -33,12 +34,25 @@ class LogBuffer { ...@@ -33,12 +34,25 @@ class LogBuffer {
logging::LogSeverity severity); logging::LogSeverity severity);
}; };
class Observer {
public:
// Called when a new message is added to the log buffer.
virtual void OnLogMessageAdded(const LogMessage& log_message) = 0;
// Called when all messages in the log buffer are cleared.
virtual void OnLogBufferCleared() = 0;
};
LogBuffer(); LogBuffer();
~LogBuffer(); ~LogBuffer();
// Returns the global instance. // Returns the global instance.
static LogBuffer* GetInstance(); static LogBuffer* GetInstance();
// Adds and removes log buffer observers.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Adds a new log message to the buffer. If the number of log messages exceeds // Adds a new log message to the buffer. If the number of log messages exceeds
// the maximum, then the earliest added log will be removed. // the maximum, then the earliest added log will be removed.
void AddLogMessage(const LogMessage& log_message); void AddLogMessage(const LogMessage& log_message);
...@@ -56,6 +70,9 @@ class LogBuffer { ...@@ -56,6 +70,9 @@ class LogBuffer {
// The messages currently in the buffer. // The messages currently in the buffer.
std::list<LogMessage> log_messages_; std::list<LogMessage> log_messages_;
// List of observers.
ObserverList<Observer> observers_;
DISALLOW_COPY_AND_ASSIGN(LogBuffer); DISALLOW_COPY_AND_ASSIGN(LogBuffer);
}; };
......
...@@ -33,6 +33,9 @@ ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui) ...@@ -33,6 +33,9 @@ ProximityAuthUI::ProximityAuthUI(content::WebUI* web_ui)
source->AddResourcePath("device-list.html", source->AddResourcePath("device-list.html",
IDR_PROXIMITY_AUTH_DEVICE_LIST_HTML); IDR_PROXIMITY_AUTH_DEVICE_LIST_HTML);
source->AddResourcePath("device-list.js", IDR_PROXIMITY_AUTH_DEVICE_LIST_JS); source->AddResourcePath("device-list.js", IDR_PROXIMITY_AUTH_DEVICE_LIST_JS);
source->AddResourcePath("log-buffer.html",
IDR_PROXIMITY_AUTH_LOG_BUFFER_HTML);
source->AddResourcePath("log-buffer.js", IDR_PROXIMITY_AUTH_LOG_BUFFER_JS);
content::BrowserContext* browser_context = content::BrowserContext* browser_context =
web_ui->GetWebContents()->GetBrowserContext(); web_ui->GetWebContents()->GetBrowserContext();
......
...@@ -4,15 +4,85 @@ ...@@ -4,15 +4,85 @@
#include "components/proximity_auth/webui/proximity_auth_webui_handler.h" #include "components/proximity_auth/webui/proximity_auth_webui_handler.h"
#include "base/bind.h"
#include "base/i18n/time_formatting.h"
#include "base/values.h"
#include "content/public/browser/web_ui.h"
namespace proximity_auth { namespace proximity_auth {
namespace {
// Keys in the JSON representation of a log message.
const char kLogMessageTextKey[] = "text";
const char kLogMessageTimeKey[] = "time";
const char kLogMessageFileKey[] = "file";
const char kLogMessageLineKey[] = "line";
const char kLogMessageSeverityKey[] = "severity";
// Converts |log_message| to a raw dictionary value used as a JSON argument to
// JavaScript functions.
scoped_ptr<base::DictionaryValue> LogMessageToDictionary(
const LogBuffer::LogMessage& log_message) {
scoped_ptr<base::DictionaryValue> dictionary(new base::DictionaryValue());
dictionary->SetString(kLogMessageTextKey, log_message.text);
dictionary->SetString(kLogMessageTimeKey,
base::TimeFormatTimeOfDay(log_message.time));
dictionary->SetString(kLogMessageFileKey, log_message.file);
dictionary->SetInteger(kLogMessageLineKey, log_message.line);
dictionary->SetInteger(kLogMessageSeverityKey,
static_cast<int>(log_message.severity));
return dictionary.Pass();
}
} // namespace
ProximityAuthWebUIHandler::ProximityAuthWebUIHandler() { ProximityAuthWebUIHandler::ProximityAuthWebUIHandler() {
LogBuffer::GetInstance()->AddObserver(this);
} }
ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() { ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() {
LogBuffer::GetInstance()->RemoveObserver(this);
} }
void ProximityAuthWebUIHandler::RegisterMessages() { void ProximityAuthWebUIHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"clearLogBuffer", base::Bind(&ProximityAuthWebUIHandler::ClearLogBuffer,
base::Unretained(this)));
web_ui()->RegisterMessageCallback(
"getLogMessages", base::Bind(&ProximityAuthWebUIHandler::GetLogMessages,
base::Unretained(this)));
}
void ProximityAuthWebUIHandler::OnLogMessageAdded(
const LogBuffer::LogMessage& log_message) {
scoped_ptr<base::DictionaryValue> dictionary =
LogMessageToDictionary(log_message);
web_ui()->CallJavascriptFunction("LogBufferInterface.onLogMessageAdded",
*dictionary);
}
void ProximityAuthWebUIHandler::OnLogBufferCleared() {
web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared");
}
void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue* args) {
base::ListValue json_logs;
auto logs = LogBuffer::GetInstance()->logs();
std::transform(logs->begin(), logs->end(), json_logs.begin(),
[](const LogBuffer::LogMessage& log) {
return LogMessageToDictionary(log).release();
});
web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages",
json_logs);
}
void ProximityAuthWebUIHandler::ClearLogBuffer(const base::ListValue* args) {
// The OnLogBufferCleared() observer function will be called after the buffer
// is cleared.
LogBuffer::GetInstance()->Clear();
} }
} // namespace proximity_auth } // namespace proximity_auth
...@@ -5,22 +5,36 @@ ...@@ -5,22 +5,36 @@
#ifndef COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_ #ifndef COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_
#define COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_ #define COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_
#include "components/proximity_auth/logging/log_buffer.h"
#include "content/public/browser/web_ui_message_handler.h" #include "content/public/browser/web_ui_message_handler.h"
namespace base {
class ListValue;
}
namespace proximity_auth { namespace proximity_auth {
class ProximityAuthService; class ProximityAuthService;
// Handles messages from the chrome://proximity-auth page. // Handles messages from the chrome://proximity-auth page.
class ProximityAuthWebUIHandler : public content::WebUIMessageHandler { class ProximityAuthWebUIHandler : public content::WebUIMessageHandler,
public LogBuffer::Observer {
public: public:
ProximityAuthWebUIHandler(); ProximityAuthWebUIHandler();
~ProximityAuthWebUIHandler() override; ~ProximityAuthWebUIHandler() override;
// content::WebUIMessageHandler implementation. // content::WebUIMessageHandler:
void RegisterMessages() override; void RegisterMessages() override;
private: private:
// LogBuffer::Observer:
void OnLogMessageAdded(const LogBuffer::LogMessage& log_message) override;
void OnLogBufferCleared() override;
// Message handler callbacks.
void GetLogMessages(const base::ListValue* args);
void ClearLogBuffer(const base::ListValue* args);
DISALLOW_COPY_AND_ASSIGN(ProximityAuthWebUIHandler); DISALLOW_COPY_AND_ASSIGN(ProximityAuthWebUIHandler);
}; };
......
<link href="chrome://resources/polymer/polymer/polymer.html" rel="import">
<polymer-element name="log-buffer">
<template></template>
<script src="log-buffer.js"></script>
</polymer-element>
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Polymer('log-buffer', {
publish: {
/**
* List of displayed logs.
* @type {?Array.<{{
* text: string,
* time: string,
* file: string,
* line: number,
* severity: number,
* }}>} LogMessage
*/
logs: null,
},
/**
* Called when an instance is created.
*/
created: function() {
this.logs = [];
// We assume that only one instance of log-buffer is ever created.
LogBufferInterface = this;
chrome.send('getLogMessages');
},
// Clears the native LogBuffer.
clearLogs: function() {
chrome.send('clearLogBuffer');
},
// Handles when a new log message is added.
onLogMessageAdded: function(log) {
this.logs.push(log);
},
// Handles when the logs are cleared.
onLogBufferCleared: function() {
this.logs = [];
},
// Handles when the logs are returned in response to the 'getLogMessages'
// request.
onGotLogMessages: function(logs) {
this.logs = logs;
}
});
// Interface with the native WebUI component for LogBuffer events. The functions
// contained in this object will be invoked by the browser for each operation
// performed on the native LogBuffer.
LogBufferInterface = {
/**
* Called when a new log message is added.
* @type {function(LogMessage)}
*/
onLogMessageAdded: function(log) {},
/**
* Called when the log buffer is cleared.
* @type {function()}
*/
onLogBufferCleared: function() {},
/**
* Called in response to chrome.send('getLogMessages') with the log messages
* currently in the buffer.
* @type {function(Array.<LogMessage>)}
*/
onGotLogMessages: function(messages) {},
};
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
<link href="chrome://resources/polymer/core-toolbar/core-toolbar.html" rel="import"> <link href="chrome://resources/polymer/core-toolbar/core-toolbar.html" rel="import">
<link href="chrome://resources/polymer/paper-icon-button/paper-icon-button.html" rel="import"> <link href="chrome://resources/polymer/paper-icon-button/paper-icon-button.html" rel="import">
<link href="chrome://resources/polymer/core-icons/communication-icons.html" rel="import"> <link href="chrome://resources/polymer/core-icons/communication-icons.html" rel="import">
<link href="log-buffer.html" rel="import">
<polymer-element name="log-panel" layout vertical> <polymer-element name="log-panel" layout vertical>
<template> <template>
...@@ -28,8 +29,18 @@ ...@@ -28,8 +29,18 @@
padding: 15px 30px; padding: 15px 30px;
} }
.list-item[severity="1"] {
background-color: #fffcef;
color: #312200;
}
.list-item[severity="2"] {
background-color: #fff1f1;
color: #ef0000;
}
.item-metadata { .item-metadata {
color: rgb(153, 153, 153); color: #888888;
font-size: 10px; font-size: 10px;
} }
...@@ -45,18 +56,19 @@ ...@@ -45,18 +56,19 @@
</style> </style>
<core-toolbar layout horizontal end-justified center <core-toolbar layout horizontal end-justified center
on-click="{{clearLogs}}"> on-click="{{clearLogs_}}">
<paper-icon-button icon="communication:clear-all"></paper-icon-button> <paper-icon-button icon="communication:clear-all"></paper-icon-button>
</core-toolbar> </core-toolbar>
<log-buffer id='logBuffer' logs="{{logs}}"></log-buffer>
<div id="list" flex> <div id="list" flex>
<template repeat="{{log in logs}}"> <template repeat="{{log in logs}}">
<div class="list-item {{ {selected: log.selected} | tokenList }}" <div class="list-item {{ {selected: log.selected} | tokenList }}"
on-click={{itemClick}}> on-click={{itemClick}} severity="{{log.severity}}">
<div class="item-metadata" layout horizontal> <div class="item-metadata" layout horizontal>
<div>14:23:50</div> <div>{{log.time}}</div>
<div flex></div> <div flex></div>
<div>proximity_auth_class.cc:123</div> <div>{{stripPath_(log.file)}}:{{log.line}}</div>
</div> </div>
<pre class="item-log" flex>{{log.text}}</pre> <pre class="item-log" flex>{{log.text}}</pre>
</div> </div>
......
...@@ -18,4 +18,8 @@ ...@@ -18,4 +18,8 @@
file="../proximity_auth/webui/resources/device-list.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> file="../proximity_auth/webui/resources/device-list.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PROXIMITY_AUTH_DEVICE_LIST_JS" <include name="IDR_PROXIMITY_AUTH_DEVICE_LIST_JS"
file="../proximity_auth/webui/resources/device-list.js" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> file="../proximity_auth/webui/resources/device-list.js" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PROXIMITY_AUTH_LOG_BUFFER_HTML"
file="../proximity_auth/webui/resources/log-buffer.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_PROXIMITY_AUTH_LOG_BUFFER_JS"
file="../proximity_auth/webui/resources/log-buffer.js" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
</grit-part> </grit-part>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment