summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/resources/gcm_internals.css22
-rw-r--r--chrome/browser/resources/gcm_internals.html82
-rw-r--r--chrome/browser/resources/gcm_internals.js82
-rw-r--r--chrome/browser/services/gcm/gcm_client_mock.cc6
-rw-r--r--chrome/browser/services/gcm/gcm_client_mock.h2
-rw-r--r--chrome/browser/services/gcm/gcm_profile_service.cc53
-rw-r--r--chrome/browser/services/gcm/gcm_profile_service.h19
-rw-r--r--chrome/browser/ui/webui/gcm_internals_ui.cc91
8 files changed, 312 insertions, 45 deletions
diff --git a/chrome/browser/resources/gcm_internals.css b/chrome/browser/resources/gcm_internals.css
index 98b3544..f3f3c5e 100644
--- a/chrome/browser/resources/gcm_internals.css
+++ b/chrome/browser/resources/gcm_internals.css
@@ -12,12 +12,28 @@ td {
padding: 4px;
}
-.row-caption {
+tr:nth-child(odd) {
+ background-color: rgb(245, 245, 200);
+}
+
+th {
+ background-color: rgb(160, 160, 125);
+ color: rgb(255, 255, 255);
+ font-weight: bold;
+}
+
+.flexbar {
+ display: flex;
+ flex-direction: row;
+ margin: 5px;
+}
+
+#device-info tr :first-child {
font-weight: bold;
padding-right: 10px;
text-align: end;
}
-.odd-number-row {
- background-color: rgb(245, 245, 200);
+.log-table {
+ padding: 4px;
}
diff --git a/chrome/browser/resources/gcm_internals.html b/chrome/browser/resources/gcm_internals.html
index 775a922..50a508f 100644
--- a/chrome/browser/resources/gcm_internals.html
+++ b/chrome/browser/resources/gcm_internals.html
@@ -13,74 +13,118 @@
</head>
<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
<h1>GCM Internals</h1>
-<div>
- <h2>Device Info</h2>
- <table>
- <tr class="odd-number-row">
- <td class="row-caption">
+<div class="flexbar">
+ <button id="refresh">Refresh</button>
+ <button id="recording">Start Recording</button>
+ <button id="clear-logs">Clear All Logs</button>
+</div>
+
+<h2>Device Info</h2>
+<table id="device-info">
+ <tbody>
+ <tr>
+ <td>
Android Id
</td>
<td id="android-id">
</td>
</tr>
<tr>
- <td class="row-caption">
+ <td>
User Profile Service Created
</td>
<td id="profile-service-created">
</td>
</tr>
- <tr class="odd-number-row">
- <td class="row-caption">
+ <tr>
+ <td>
GCM Enabled State
</td>
<td id="gcm-enabled-state">
</td>
</tr>
<tr>
- <td class="row-caption">
+ <td>
Signed In Username
</td>
<td id="signed-in-username">
</td>
</tr>
- <tr class="odd-number-row">
- <td class="row-caption">
+ <tr>
+ <td>
GCM Client Created
</td>
<td id="gcm-client-created">
</td>
</tr>
<tr>
- <td class="row-caption">
+ <td>
GCM Client State
</td>
<td id="gcm-client-state">
</td>
</tr>
- <tr class="odd-number-row">
- <td class="row-caption">
+ <tr>
+ <td>
GCM Client Is Ready
</td>
<td id="gcm-client-ready">
</td>
</tr>
<tr>
- <td class="row-caption">
+ <td>
Connection Client Created
</td>
<td id="connection-client-created">
</td>
</tr>
- <tr class="odd-number-row">
- <td class="row-caption">
+ <tr>
+ <td>
Connection State
</td>
<td id="connection-state">
</td>
</tr>
- </table>
-</div>
+ <tr>
+ <td>
+ Registered App Ids
+ </td>
+ <td id="registered-app-ids">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Send Message Queue Size
+ </td>
+ <td id="send-queue-size">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ Resend Message Queue Size
+ </td>
+ <td id="resend-queue-size">
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+<h2>Send Message Log</h2>
+<table class="log-table">
+ <thead>
+ <tr>
+ <th>Time</th>
+ <th>App Id</th>
+ <th>Receiver Id</th>
+ <th>Msg Id</th>
+ <th>Event</th>
+ <th>Details</th>
+ </tr>
+ </thead>
+ <tbody id="send-info">
+ </tbody>
+</table>
+
<script src="chrome://resources/js/i18n_template2.js"></script>
</body>
</html> \ No newline at end of file
diff --git a/chrome/browser/resources/gcm_internals.js b/chrome/browser/resources/gcm_internals.js
index f309479..35100b3 100644
--- a/chrome/browser/resources/gcm_internals.js
+++ b/chrome/browser/resources/gcm_internals.js
@@ -5,9 +5,11 @@
cr.define('gcmInternals', function() {
'use strict';
+ var isRecording = false;
+
/**
* If the info dictionary has property prop, then set the text content of
- * element to the value of this property.
+ * element to the value of this property. Otherwise clear the content.
* @param {!Object} info A dictionary of device infos to be displayed.
* @param {string} prop Name of the property.
* @param {string} element The id of a HTML element.
@@ -15,6 +17,8 @@ cr.define('gcmInternals', function() {
function setIfExists(info, prop, element) {
if (info[prop] !== undefined) {
$(element).textContent = info[prop];
+ } else {
+ $(element).textContent = '';
}
}
@@ -32,10 +36,73 @@ cr.define('gcmInternals', function() {
setIfExists(info, 'gcmClientReady', 'gcm-client-ready');
setIfExists(info, 'connectionClientCreated', 'connection-client-created');
setIfExists(info, 'connectionState', 'connection-state');
+ setIfExists(info, 'registeredAppIds', 'registered-app-ids');
+ setIfExists(info, 'sendQueueSize', 'send-queue-size');
+ setIfExists(info, 'resendQueueSize', 'resend-queue-size');
+ }
+
+ /**
+ * Remove all the child nodes of the element.
+ * @param {HTMLElement} element A HTML element.
+ */
+ function removeAllChildNodes(element) {
+ element.textContent = '';
+ }
+
+ /**
+ * For each item in line, add a row to the table. Each item is actually a list
+ * of sub-items; each of which will have a corresponding cell created in that
+ * row, and the sub-item will be displayed in the cell.
+ * @param {HTMLElement} table A HTML tbody element.
+ * @param {!Object} list A list of list of item.
+ */
+ function addRows(table, list) {
+ for (var i = 0; i < list.length; ++i) {
+ var row = document.createElement('tr');
+
+ // The first element is always a timestamp.
+ var cell = document.createElement('td');
+ var d = new Date(list[i][0]);
+ cell.textContent = d;
+ row.appendChild(cell);
+
+ for (var j = 1; j < list[i].length; ++j) {
+ var cell = document.createElement('td');
+ cell.textContent = list[i][j];
+ row.appendChild(cell);
+ }
+ table.appendChild(row);
+ }
+ }
+
+ /**
+ * Refresh all displayed information.
+ */
+ function refreshAll() {
+ chrome.send('getGcmInternalsInfo', [false]);
+ }
+
+ /**
+ * Toggle the isRecording variable and send it to browser.
+ */
+ function setRecording() {
+ isRecording = !isRecording;
+ chrome.send('setGcmInternalsRecording', [isRecording]);
+ }
+
+ /**
+ * Clear all the activity logs.
+ */
+ function clearLogs() {
+ chrome.send('getGcmInternalsInfo', [true]);
}
function initialize() {
- chrome.send('getGcmInternalsInfo');
+ $('recording').disabled = true;
+ $('refresh').onclick = refreshAll;
+ $('recording').onclick = setRecording;
+ $('clear-logs').onclick = clearLogs;
+ chrome.send('getGcmInternalsInfo', [false]);
}
/**
@@ -43,9 +110,20 @@ cr.define('gcmInternals', function() {
* @param {!Object} infos A dictionary of info items to be displayed.
*/
function setGcmInternalsInfo(infos) {
+ isRecording = infos.isRecording;
+ if (isRecording)
+ $('recording').textContent = 'Stop Recording';
+ else
+ $('recording').textContent = 'Start Recording';
+ $('recording').disabled = false;
if (infos.deviceInfo !== undefined) {
displayDeviceInfo(infos.deviceInfo);
}
+
+ removeAllChildNodes($('send-info'));
+ if (infos.sendInfo !== undefined) {
+ addRows($('send-info'), infos.sendInfo);
+ }
}
// Return an object with all of the exports.
diff --git a/chrome/browser/services/gcm/gcm_client_mock.cc b/chrome/browser/services/gcm/gcm_client_mock.cc
index 3b58cda..d924238 100644
--- a/chrome/browser/services/gcm/gcm_client_mock.cc
+++ b/chrome/browser/services/gcm/gcm_client_mock.cc
@@ -97,6 +97,12 @@ void GCMClientMock::Send(const std::string& app_id,
message));
}
+void GCMClientMock::SetRecording(bool recording) {
+}
+
+void GCMClientMock::ClearActivityLogs() {
+}
+
GCMClient::GCMStatistics GCMClientMock::GetStatistics() const {
return GCMClient::GCMStatistics();
}
diff --git a/chrome/browser/services/gcm/gcm_client_mock.h b/chrome/browser/services/gcm/gcm_client_mock.h
index 2cdc104..ce080ce 100644
--- a/chrome/browser/services/gcm/gcm_client_mock.h
+++ b/chrome/browser/services/gcm/gcm_client_mock.h
@@ -48,6 +48,8 @@ class GCMClientMock : public GCMClient {
virtual void Send(const std::string& app_id,
const std::string& receiver_id,
const OutgoingMessage& message) OVERRIDE;
+ virtual void SetRecording(bool recording) OVERRIDE;
+ virtual void ClearActivityLogs() OVERRIDE;
virtual GCMStatistics GetStatistics() const OVERRIDE;
// Initiate the loading that has been delayed.
diff --git a/chrome/browser/services/gcm/gcm_profile_service.cc b/chrome/browser/services/gcm/gcm_profile_service.cc
index cf7e1b5..f93b427 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.cc
+++ b/chrome/browser/services/gcm/gcm_profile_service.cc
@@ -176,7 +176,8 @@ class GCMProfileService::IOWorker
void Send(const std::string& app_id,
const std::string& receiver_id,
const GCMClient::OutgoingMessage& message);
- void RequestGCMStatistics();
+ void GetGCMStatistics(bool clear_logs);
+ void SetGCMRecording(bool recording);
// For testing purpose. Can be called from UI thread. Use with care.
GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
@@ -372,19 +373,38 @@ void GCMProfileService::IOWorker::Send(
gcm_client_->Send(app_id, receiver_id, message);
}
-void GCMProfileService::IOWorker::RequestGCMStatistics() {
+void GCMProfileService::IOWorker::GetGCMStatistics(bool clear_logs) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
gcm::GCMClient::GCMStatistics stats;
if (gcm_client_.get()) {
- stats.gcm_client_created = true;
+ if (clear_logs)
+ gcm_client_->ClearActivityLogs();
stats = gcm_client_->GetStatistics();
}
content::BrowserThread::PostTask(
content::BrowserThread::UI,
FROM_HERE,
- base::Bind(&GCMProfileService::RequestGCMStatisticsFinished,
+ base::Bind(&GCMProfileService::GetGCMStatisticsFinished,
+ service_,
+ stats));
+}
+
+void GCMProfileService::IOWorker::SetGCMRecording(bool recording) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+ gcm::GCMClient::GCMStatistics stats;
+
+ if (gcm_client_.get()) {
+ gcm_client_->SetRecording(recording);
+ stats = gcm_client_->GetStatistics();
+ stats.gcm_client_created = true;
+ }
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&GCMProfileService::GetGCMStatisticsFinished,
service_,
stats));
}
@@ -688,8 +708,8 @@ bool GCMProfileService::IsGCMClientReady() const {
return gcm_client_ready_;
}
-void GCMProfileService::RequestGCMStatistics(
- RequestGCMStatisticsCallback callback) {
+void GCMProfileService::GetGCMStatistics(
+ GetGCMStatisticsCallback callback, bool clear_logs) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(!callback.is_null());
@@ -697,8 +717,22 @@ void GCMProfileService::RequestGCMStatistics(
content::BrowserThread::PostTask(
content::BrowserThread::IO,
FROM_HERE,
- base::Bind(&GCMProfileService::IOWorker::RequestGCMStatistics,
- io_worker_));
+ base::Bind(&GCMProfileService::IOWorker::GetGCMStatistics,
+ io_worker_,
+ clear_logs));
+}
+
+void GCMProfileService::SetGCMRecording(
+ GetGCMStatisticsCallback callback, bool recording) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ request_gcm_statistics_callback_ = callback;
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&GCMProfileService::IOWorker::SetGCMRecording,
+ io_worker_,
+ recording));
}
void GCMProfileService::Observe(int type,
@@ -904,10 +938,9 @@ GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) {
return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
}
-void GCMProfileService::RequestGCMStatisticsFinished(
+void GCMProfileService::GetGCMStatisticsFinished(
GCMClient::GCMStatistics stats) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
request_gcm_statistics_callback_.Run(stats);
}
diff --git a/chrome/browser/services/gcm/gcm_profile_service.h b/chrome/browser/services/gcm/gcm_profile_service.h
index 3817b0e..b93bfa2 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.h
+++ b/chrome/browser/services/gcm/gcm_profile_service.h
@@ -52,7 +52,7 @@ class GCMProfileService : public KeyedService,
GCMClient::Result result)> SendCallback;
typedef base::Callback<void(GCMClient::Result result)> UnregisterCallback;
typedef base::Callback<void(const GCMClient::GCMStatistics& stats)>
- RequestGCMStatisticsCallback;
+ GetGCMStatisticsCallback;
// Any change made to this enum should have corresponding change in the
// GetGCMEnabledStateString(...) function.
@@ -129,9 +129,14 @@ class GCMProfileService : public KeyedService,
// Returns true if the gcm client is ready.
bool IsGCMClientReady() const;
- // Get GCM client internal states and statistics. If it has not been created
- // then stats won't be modified.
- void RequestGCMStatistics(RequestGCMStatisticsCallback callback);
+ // Get GCM client internal states and statistics.
+ // If clear_logs is true then activity logs will be cleared before the stats
+ // are returned.
+ void GetGCMStatistics(GetGCMStatisticsCallback callback,
+ bool clear_logs);
+
+ // Enables/disables GCM activity recording, and then returns the stats.
+ void SetGCMRecording(GetGCMStatisticsCallback callback, bool recording);
private:
friend class GCMProfileServiceTestConsumer;
@@ -199,7 +204,7 @@ class GCMProfileService : public KeyedService,
// Returns the handler for the given app.
GCMAppHandler* GetAppHandler(const std::string& app_id);
- void RequestGCMStatisticsFinished(GCMClient::GCMStatistics stats);
+ void GetGCMStatisticsFinished(GCMClient::GCMStatistics stats);
// The profile which owns this object.
Profile* profile_;
@@ -233,8 +238,8 @@ class GCMProfileService : public KeyedService,
// Callback map (from <app_id, message_id> to callback) for Send.
std::map<std::pair<std::string, std::string>, SendCallback> send_callbacks_;
- // Callback for RequestGCMStatistics.
- RequestGCMStatisticsCallback request_gcm_statistics_callback_;
+ // Callback for GetGCMStatistics.
+ GetGCMStatisticsCallback request_gcm_statistics_callback_;
// Used to pass a weak pointer to the IO worker.
base::WeakPtrFactory<GCMProfileService> weak_ptr_factory_;
diff --git a/chrome/browser/ui/webui/gcm_internals_ui.cc b/chrome/browser/ui/webui/gcm_internals_ui.cc
index be9fe84..2130cd8 100644
--- a/chrome/browser/ui/webui/gcm_internals_ui.cc
+++ b/chrome/browser/ui/webui/gcm_internals_ui.cc
@@ -4,10 +4,13 @@
#include "chrome/browser/ui/webui/gcm_internals_ui.h"
+#include <vector>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/format_macros.h"
#include "base/memory/weak_ptr.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile.h"
@@ -23,6 +26,24 @@
namespace {
+void SetSendingInfo(
+ const std::vector<gcm::GCMStatsRecorder::SendingActivity>& sends,
+ base::ListValue* send_info) {
+ std::vector<gcm::GCMStatsRecorder::SendingActivity>::const_iterator it =
+ sends.begin();
+ for (; it < sends.end(); ++it) {
+ base::ListValue* row = new base::ListValue();
+ send_info->Append(row);
+
+ row->AppendDouble(it->time.ToJsTime());
+ row->AppendString(it->app_id);
+ row->AppendString(it->receiver_id);
+ row->AppendString(it->message_id);
+ row->AppendString(it->event);
+ row->AppendString(it->details);
+ }
+}
+
// Class acting as a controller of the chrome://gcm-internals WebUI.
class GcmInternalsUIMessageHandler : public content::WebUIMessageHandler {
public:
@@ -42,6 +63,9 @@ class GcmInternalsUIMessageHandler : public content::WebUIMessageHandler {
// Request all of the GCM related infos through gcm profile service.
void RequestAllInfo(const base::ListValue* args);
+ // Enables/disables GCM activity recording through gcm profile service.
+ void SetRecording(const base::ListValue* args);
+
// Callback function of the request for all gcm related infos.
void RequestGCMStatisticsFinished(
const gcm::GCMClient::GCMStatistics& args) const;
@@ -76,16 +100,27 @@ void GcmInternalsUIMessageHandler::ReturnResults(
profile_service->IsGCMClientReady());
}
if (stats) {
+ results.SetBoolean("isRecording", stats->is_recording);
device_info->SetBoolean("gcmClientCreated", stats->gcm_client_created);
device_info->SetString("gcmClientState", stats->gcm_client_state);
device_info->SetBoolean("connectionClientCreated",
stats->connection_client_created);
+ device_info->SetString("registeredAppIds",
+ JoinString(stats->registered_app_ids, ","));
if (stats->connection_client_created)
device_info->SetString("connectionState", stats->connection_state);
if (stats->android_id > 0) {
device_info->SetString("androidId",
base::StringPrintf("0x%" PRIx64, stats->android_id));
}
+ device_info->SetInteger("sendQueueSize", stats->send_queue_size);
+ device_info->SetInteger("resendQueueSize", stats->resend_queue_size);
+
+ if (stats->sending_activities.size() > 0) {
+ base::ListValue* send_info = new base::ListValue();
+ results.Set("sendInfo", send_info);
+ SetSendingInfo(stats->sending_activities, send_info);
+ }
}
web_ui()->CallJavascriptFunction("gcmInternals.setGcmInternalsInfo",
results);
@@ -93,17 +128,61 @@ void GcmInternalsUIMessageHandler::ReturnResults(
void GcmInternalsUIMessageHandler::RequestAllInfo(
const base::ListValue* args) {
+ if (args->GetSize() != 1) {
+ NOTREACHED();
+ return;
+ }
+ bool clear_logs = false;
+ if (!args->GetBoolean(0, &clear_logs)) {
+ NOTREACHED();
+ return;
+ }
+
Profile* profile = Profile::FromWebUI(web_ui());
gcm::GCMProfileService* profile_service =
gcm::GCMProfileServiceFactory::GetForProfile(profile);
if (!profile_service) {
ReturnResults(profile, NULL, NULL);
+ } else if (profile_service->SignedInUserName().empty()) {
+ ReturnResults(profile, profile_service, NULL);
} else {
- profile_service->RequestGCMStatistics(base::Bind(
- &GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished,
- weak_ptr_factory_.GetWeakPtr()));
+ profile_service->GetGCMStatistics(
+ base::Bind(&GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished,
+ weak_ptr_factory_.GetWeakPtr()),
+ clear_logs);
+ }
+}
+
+void GcmInternalsUIMessageHandler::SetRecording(const base::ListValue* args) {
+ if (args->GetSize() != 1) {
+ NOTREACHED();
+ return;
+ }
+ bool recording = false;
+ if (!args->GetBoolean(0, &recording)) {
+ NOTREACHED();
+ return;
+ }
+
+ Profile* profile = Profile::FromWebUI(web_ui());
+ gcm::GCMProfileService* profile_service =
+ gcm::GCMProfileServiceFactory::GetForProfile(profile);
+
+ if (!profile_service) {
+ ReturnResults(profile, NULL, NULL);
+ return;
+ }
+ if (profile_service->SignedInUserName().empty()) {
+ ReturnResults(profile, profile_service, NULL);
+ return;
}
+ // Get fresh stats after changing recording setting.
+ profile_service->SetGCMRecording(
+ base::Bind(
+ &GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished,
+ weak_ptr_factory_.GetWeakPtr()),
+ recording);
}
void GcmInternalsUIMessageHandler::RequestGCMStatisticsFinished(
@@ -120,7 +199,11 @@ void GcmInternalsUIMessageHandler::RegisterMessages() {
web_ui()->RegisterMessageCallback(
"getGcmInternalsInfo",
base::Bind(&GcmInternalsUIMessageHandler::RequestAllInfo,
- base::Unretained(this)));
+ weak_ptr_factory_.GetWeakPtr()));
+ web_ui()->RegisterMessageCallback(
+ "setGcmInternalsRecording",
+ base::Bind(&GcmInternalsUIMessageHandler::SetRecording,
+ weak_ptr_factory_.GetWeakPtr()));
}
} // namespace