diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/resources/gcm_internals.css | 22 | ||||
-rw-r--r-- | chrome/browser/resources/gcm_internals.html | 82 | ||||
-rw-r--r-- | chrome/browser/resources/gcm_internals.js | 82 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_client_mock.cc | 6 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_client_mock.h | 2 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_profile_service.cc | 53 | ||||
-rw-r--r-- | chrome/browser/services/gcm/gcm_profile_service.h | 19 | ||||
-rw-r--r-- | chrome/browser/ui/webui/gcm_internals_ui.cc | 91 |
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 |