Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/ui/webui/sync_internals_message_handler.h" | 5 #include "chrome/browser/ui/webui/sync_internals_message_handler.h" |
| 6 | 6 |
| 7 #include <stdint.h> | |
| 8 | |
| 7 #include <utility> | 9 #include <utility> |
| 8 #include <vector> | 10 #include <vector> |
| 9 | 11 |
| 10 #include "base/logging.h" | 12 #include "base/logging.h" |
| 11 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 12 #include "chrome/browser/profiles/profile.h" | 14 #include "chrome/browser/profiles/profile.h" |
| 13 #include "chrome/browser/sync/profile_sync_service_factory.h" | 15 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 14 #include "chrome/common/channel_info.h" | 16 #include "chrome/common/channel_info.h" |
| 15 #include "components/browser_sync/profile_sync_service.h" | 17 #include "components/browser_sync/profile_sync_service.h" |
| 16 #include "components/signin/core/browser/signin_manager_base.h" | |
| 17 #include "components/sync/base/weak_handle.h" | 18 #include "components/sync/base/weak_handle.h" |
| 18 #include "components/sync/driver/about_sync_util.h" | 19 #include "components/sync/driver/about_sync_util.h" |
| 19 #include "components/sync/driver/sync_service.h" | 20 #include "components/sync/driver/sync_service.h" |
| 20 #include "components/sync/engine/cycle/commit_counters.h" | 21 #include "components/sync/engine/cycle/commit_counters.h" |
| 21 #include "components/sync/engine/cycle/status_counters.h" | 22 #include "components/sync/engine/cycle/status_counters.h" |
| 22 #include "components/sync/engine/cycle/update_counters.h" | 23 #include "components/sync/engine/cycle/update_counters.h" |
| 23 #include "components/sync/engine/events/protocol_event.h" | 24 #include "components/sync/engine/events/protocol_event.h" |
| 24 #include "components/sync/js/js_event_details.h" | 25 #include "components/sync/js/js_event_details.h" |
| 25 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
| 26 #include "content/public/browser/web_ui.h" | 27 #include "content/public/browser/web_ui.h" |
| 27 | 28 |
| 29 using base::DictionaryValue; | |
| 30 using base::ListValue; | |
| 31 using base::Value; | |
| 28 using browser_sync::ProfileSyncService; | 32 using browser_sync::ProfileSyncService; |
| 29 using syncer::JsEventDetails; | 33 using syncer::JsEventDetails; |
| 30 using syncer::ModelTypeSet; | 34 using syncer::ModelTypeSet; |
| 35 using syncer::SyncService; | |
| 31 using syncer::WeakHandle; | 36 using syncer::WeakHandle; |
| 32 | 37 |
| 33 namespace { | |
| 34 class UtilAboutSyncDataExtractor : public AboutSyncDataExtractor { | |
| 35 public: | |
| 36 std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( | |
| 37 syncer::SyncService* service, | |
| 38 SigninManagerBase* signin) override { | |
| 39 return syncer::sync_ui_util::ConstructAboutInformation( | |
| 40 service, signin, chrome::GetChannel()); | |
| 41 } | |
| 42 }; | |
| 43 } // namespace | |
| 44 | |
| 45 SyncInternalsMessageHandler::SyncInternalsMessageHandler() | 38 SyncInternalsMessageHandler::SyncInternalsMessageHandler() |
| 46 : SyncInternalsMessageHandler( | 39 : SyncInternalsMessageHandler( |
| 47 base::MakeUnique<UtilAboutSyncDataExtractor>()) {} | 40 base::BindRepeating( |
| 41 &SyncInternalsMessageHandler::BindForSyncServiceProvider, | |
| 42 base::Unretained(this)), | |
| 43 base::BindRepeating( | |
| 44 &syncer::sync_ui_util::ConstructAboutInformation)) {} | |
| 48 | 45 |
| 49 SyncInternalsMessageHandler::SyncInternalsMessageHandler( | 46 SyncInternalsMessageHandler::SyncInternalsMessageHandler( |
| 50 std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) | 47 SyncServiceProvider sync_service_provider, |
| 51 : about_sync_data_extractor_(std::move(about_sync_data_extractor)), | 48 AboutSyncDataDelegate about_sync_data_delegate) |
| 49 : sync_service_provider_(std::move(sync_service_provider)), | |
| 50 about_sync_data_delegate_(std::move(about_sync_data_delegate)), | |
| 52 weak_ptr_factory_(this) {} | 51 weak_ptr_factory_(this) {} |
| 53 | 52 |
| 54 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { | 53 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { |
| 55 if (js_controller_) | 54 UnregisterModelNotifications(); |
| 56 js_controller_->RemoveJsEventHandler(this); | 55 } |
| 57 | 56 |
| 58 ProfileSyncService* service = GetProfileSyncService(); | 57 void SyncInternalsMessageHandler::OnJavascriptDisallowed() { |
| 59 if (service && service->HasObserver(this)) { | 58 UnregisterModelNotifications(); |
|
Dan Beam
2017/05/22 23:31:43
can we just call weak_ptr_factory_.InvalidateWeakP
skym
2017/05/24 00:20:16
Woah. It seems I can call WeakPtrFactory::Invalida
| |
| 60 service->RemoveObserver(this); | |
| 61 service->RemoveProtocolEventObserver(this); | |
| 62 } | |
| 63 | |
| 64 if (service && is_registered_for_counters_) { | |
| 65 service->RemoveTypeDebugInfoObserver(this); | |
| 66 } | |
| 67 } | 59 } |
| 68 | 60 |
| 69 void SyncInternalsMessageHandler::RegisterMessages() { | 61 void SyncInternalsMessageHandler::RegisterMessages() { |
| 70 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 62 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 71 | 63 |
| 72 web_ui()->RegisterMessageCallback( | 64 web_ui()->RegisterMessageCallback( |
| 73 syncer::sync_ui_util::kRegisterForEvents, | 65 syncer::sync_ui_util::kRegisterForEvents, |
| 74 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents, | 66 base::Bind(&SyncInternalsMessageHandler::HandleRegisterForEvents, |
| 75 base::Unretained(this))); | 67 base::Unretained(this))); |
| 76 | 68 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 89 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, | 81 base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes, |
| 90 base::Unretained(this))); | 82 base::Unretained(this))); |
| 91 | 83 |
| 92 web_ui()->RegisterMessageCallback( | 84 web_ui()->RegisterMessageCallback( |
| 93 syncer::sync_ui_util::kGetAllNodes, | 85 syncer::sync_ui_util::kGetAllNodes, |
| 94 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, | 86 base::Bind(&SyncInternalsMessageHandler::HandleGetAllNodes, |
| 95 base::Unretained(this))); | 87 base::Unretained(this))); |
| 96 } | 88 } |
| 97 | 89 |
| 98 void SyncInternalsMessageHandler::HandleRegisterForEvents( | 90 void SyncInternalsMessageHandler::HandleRegisterForEvents( |
| 99 const base::ListValue* args) { | 91 const ListValue* args) { |
| 100 DCHECK(args->empty()); | 92 DCHECK(args->empty()); |
| 93 AllowJavascript(); | |
| 101 | 94 |
| 102 // is_registered_ flag protects us from double-registering. This could | 95 // is_registered_ flag protects us from double-registering. This could |
| 103 // happen on a page refresh, where the JavaScript gets re-run but the | 96 // happen on a page refresh, where the JavaScript gets re-run but the |
| 104 // message handler remains unchanged. | 97 // message handler remains unchanged. |
| 105 ProfileSyncService* service = GetProfileSyncService(); | 98 SyncService* service = sync_service_provider_.Run(); |
| 106 if (service && !is_registered_) { | 99 if (service && !is_registered_) { |
| 107 service->AddObserver(this); | 100 service->AddObserver(this); |
| 108 service->AddProtocolEventObserver(this); | 101 service->AddProtocolEventObserver(this); |
| 109 js_controller_ = service->GetJsController(); | 102 js_controller_ = service->GetJsController(); |
| 110 js_controller_->AddJsEventHandler(this); | 103 js_controller_->AddJsEventHandler(this); |
| 111 is_registered_ = true; | 104 is_registered_ = true; |
| 112 } | 105 } |
| 113 } | 106 } |
| 114 | 107 |
| 115 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( | 108 void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( |
| 116 const base::ListValue* args) { | 109 const ListValue* args) { |
| 117 DCHECK(args->empty()); | 110 DCHECK(args->empty()); |
| 111 AllowJavascript(); | |
| 118 | 112 |
| 119 if (ProfileSyncService* service = GetProfileSyncService()) { | 113 if (SyncService* service = sync_service_provider_.Run()) { |
|
Dan Beam
2017/05/22 23:31:43
i think it's fairly uncommon to do assignment in a
skym
2017/05/24 00:20:16
Moved this invocation out of the if check, added a
| |
| 120 if (!is_registered_for_counters_) { | 114 if (!is_registered_for_counters_) { |
| 121 service->AddTypeDebugInfoObserver(this); | 115 service->AddTypeDebugInfoObserver(this); |
| 122 is_registered_for_counters_ = true; | 116 is_registered_for_counters_ = true; |
| 123 } else { | 117 } else { |
| 124 // Re-register to ensure counters get re-emitted. | 118 // Re-register to ensure counters get re-emitted. |
| 125 service->RemoveTypeDebugInfoObserver(this); | 119 service->RemoveTypeDebugInfoObserver(this); |
| 126 service->AddTypeDebugInfoObserver(this); | 120 service->AddTypeDebugInfoObserver(this); |
| 127 } | 121 } |
| 128 } | 122 } |
| 129 } | 123 } |
| 130 | 124 |
| 131 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( | 125 void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( |
| 132 const base::ListValue* args) { | 126 const ListValue* args) { |
| 133 DCHECK(args->empty()); | 127 DCHECK(args->empty()); |
| 128 AllowJavascript(); | |
| 134 SendAboutInfo(); | 129 SendAboutInfo(); |
| 135 } | 130 } |
| 136 | 131 |
| 137 void SyncInternalsMessageHandler::HandleRequestListOfTypes( | 132 void SyncInternalsMessageHandler::HandleRequestListOfTypes( |
| 138 const base::ListValue* args) { | 133 const ListValue* args) { |
| 139 DCHECK(args->empty()); | 134 DCHECK(args->empty()); |
| 140 base::DictionaryValue event_details; | 135 AllowJavascript(); |
| 141 std::unique_ptr<base::ListValue> type_list(new base::ListValue()); | 136 |
| 142 ModelTypeSet protocol_types = syncer::ProtocolTypes(); | 137 DictionaryValue event_details; |
| 143 for (ModelTypeSet::Iterator it = protocol_types.First(); | 138 auto type_list = base::MakeUnique<ListValue>(); |
| 144 it.Good(); it.Inc()) { | 139 for (ModelTypeSet::Iterator it = syncer::ProtocolTypes().First(); it.Good(); |
| 140 it.Inc()) { | |
| 145 type_list->AppendString(ModelTypeToString(it.Get())); | 141 type_list->AppendString(ModelTypeToString(it.Get())); |
| 146 } | 142 } |
| 147 event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list)); | 143 event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list)); |
| 148 web_ui()->CallJavascriptFunctionUnsafe( | 144 DispatchEvent(syncer::sync_ui_util::kOnReceivedListOfTypes, event_details); |
| 149 syncer::sync_ui_util::kDispatchEvent, | |
| 150 base::Value(syncer::sync_ui_util::kOnReceivedListOfTypes), event_details); | |
| 151 } | 145 } |
| 152 | 146 |
| 153 void SyncInternalsMessageHandler::HandleGetAllNodes( | 147 void SyncInternalsMessageHandler::HandleGetAllNodes(const ListValue* args) { |
| 154 const base::ListValue* args) { | |
| 155 DCHECK_EQ(1U, args->GetSize()); | 148 DCHECK_EQ(1U, args->GetSize()); |
| 149 AllowJavascript(); | |
| 150 | |
| 156 int request_id = 0; | 151 int request_id = 0; |
| 157 bool success = ExtractIntegerValue(args, &request_id); | 152 bool success = ExtractIntegerValue(args, &request_id); |
| 158 DCHECK(success); | 153 DCHECK(success); |
| 159 | 154 |
| 160 ProfileSyncService* service = GetProfileSyncService(); | 155 SyncService* service = sync_service_provider_.Run(); |
| 161 if (service) { | 156 if (service) { |
| 162 service->GetAllNodes( | 157 service->GetAllNodes( |
| 163 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, | 158 base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, |
| 164 weak_ptr_factory_.GetWeakPtr(), request_id)); | 159 weak_ptr_factory_.GetWeakPtr(), request_id)); |
| 165 } | 160 } |
| 166 } | 161 } |
| 167 | 162 |
| 168 void SyncInternalsMessageHandler::OnReceivedAllNodes( | 163 void SyncInternalsMessageHandler::OnReceivedAllNodes( |
| 169 int request_id, | 164 int request_id, |
| 170 std::unique_ptr<base::ListValue> nodes) { | 165 std::unique_ptr<ListValue> nodes) { |
| 171 base::Value id(request_id); | 166 // This is a callback that's invoked asyncrhonously. However, it's possible |
| 172 web_ui()->CallJavascriptFunctionUnsafe( | 167 // that our UI is no longer allowing javascript, and we need to manually check |
| 173 syncer::sync_ui_util::kGetAllNodesCallback, id, *nodes); | 168 // before proceeding. |
| 169 if (IsJavascriptAllowed()) { | |
| 170 CallJavascriptFunction(syncer::sync_ui_util::kGetAllNodesCallback, | |
| 171 Value(request_id), *nodes); | |
| 172 } | |
| 174 } | 173 } |
| 175 | 174 |
| 176 void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) { | 175 void SyncInternalsMessageHandler::OnStateChanged(SyncService* sync) { |
| 177 SendAboutInfo(); | 176 SendAboutInfo(); |
| 178 } | 177 } |
| 179 | 178 |
| 180 void SyncInternalsMessageHandler::OnProtocolEvent( | 179 void SyncInternalsMessageHandler::OnProtocolEvent( |
| 181 const syncer::ProtocolEvent& event) { | 180 const syncer::ProtocolEvent& event) { |
| 182 std::unique_ptr<base::DictionaryValue> value( | 181 std::unique_ptr<DictionaryValue> value(syncer::ProtocolEvent::ToValue(event)); |
| 183 syncer::ProtocolEvent::ToValue(event)); | 182 DispatchEvent(syncer::sync_ui_util::kOnProtocolEvent, *value); |
| 184 web_ui()->CallJavascriptFunctionUnsafe( | |
| 185 syncer::sync_ui_util::kDispatchEvent, | |
| 186 base::Value(syncer::sync_ui_util::kOnProtocolEvent), *value); | |
| 187 } | 183 } |
| 188 | 184 |
| 189 void SyncInternalsMessageHandler::OnCommitCountersUpdated( | 185 void SyncInternalsMessageHandler::OnCommitCountersUpdated( |
| 190 syncer::ModelType type, | 186 syncer::ModelType type, |
| 191 const syncer::CommitCounters& counters) { | 187 const syncer::CommitCounters& counters) { |
| 192 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue()); | 188 EmitCounterUpdate(type, syncer::sync_ui_util::kCommit, counters.ToValue()); |
| 193 } | 189 } |
| 194 | 190 |
| 195 void SyncInternalsMessageHandler::OnUpdateCountersUpdated( | 191 void SyncInternalsMessageHandler::OnUpdateCountersUpdated( |
| 196 syncer::ModelType type, | 192 syncer::ModelType type, |
| 197 const syncer::UpdateCounters& counters) { | 193 const syncer::UpdateCounters& counters) { |
| 198 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue()); | 194 EmitCounterUpdate(type, syncer::sync_ui_util::kUpdate, counters.ToValue()); |
| 199 } | 195 } |
| 200 | 196 |
| 201 void SyncInternalsMessageHandler::OnStatusCountersUpdated( | 197 void SyncInternalsMessageHandler::OnStatusCountersUpdated( |
| 202 syncer::ModelType type, | 198 syncer::ModelType type, |
| 203 const syncer::StatusCounters& counters) { | 199 const syncer::StatusCounters& counters) { |
| 204 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue()); | 200 EmitCounterUpdate(type, syncer::sync_ui_util::kStatus, counters.ToValue()); |
| 205 } | 201 } |
| 206 | 202 |
| 207 void SyncInternalsMessageHandler::EmitCounterUpdate( | 203 void SyncInternalsMessageHandler::EmitCounterUpdate( |
| 208 syncer::ModelType type, | 204 syncer::ModelType type, |
| 209 const std::string& counter_type, | 205 const std::string& counter_type, |
| 210 std::unique_ptr<base::DictionaryValue> value) { | 206 std::unique_ptr<DictionaryValue> value) { |
| 211 std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue()); | 207 auto details = base::MakeUnique<DictionaryValue>(); |
| 212 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); | 208 details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); |
| 213 details->SetString(syncer::sync_ui_util::kCounterType, counter_type); | 209 details->SetString(syncer::sync_ui_util::kCounterType, counter_type); |
| 214 details->Set(syncer::sync_ui_util::kCounters, std::move(value)); | 210 details->Set(syncer::sync_ui_util::kCounters, std::move(value)); |
| 215 web_ui()->CallJavascriptFunctionUnsafe( | 211 DispatchEvent(syncer::sync_ui_util::kOnCountersUpdated, *details); |
| 216 syncer::sync_ui_util::kDispatchEvent, | |
| 217 base::Value(syncer::sync_ui_util::kOnCountersUpdated), *details); | |
| 218 } | 212 } |
| 219 | 213 |
| 220 void SyncInternalsMessageHandler::HandleJsEvent( | 214 void SyncInternalsMessageHandler::HandleJsEvent( |
| 221 const std::string& name, | 215 const std::string& name, |
| 222 const JsEventDetails& details) { | 216 const JsEventDetails& details) { |
| 223 DVLOG(1) << "Handling event: " << name | 217 DVLOG(1) << "Handling event: " << name |
| 224 << " with details " << details.ToString(); | 218 << " with details " << details.ToString(); |
| 225 web_ui()->CallJavascriptFunctionUnsafe(syncer::sync_ui_util::kDispatchEvent, | 219 DispatchEvent(name, details.Get()); |
| 226 base::Value(name), details.Get()); | |
| 227 } | 220 } |
| 228 | 221 |
| 229 void SyncInternalsMessageHandler::SendAboutInfo() { | 222 void SyncInternalsMessageHandler::SendAboutInfo() { |
| 230 ProfileSyncService* sync_service = GetProfileSyncService(); | 223 std::unique_ptr<DictionaryValue> value = about_sync_data_delegate_.Run( |
| 231 SigninManagerBase* signin = sync_service ? sync_service->signin() : nullptr; | 224 sync_service_provider_.Run(), chrome::GetChannel()); |
| 232 std::unique_ptr<base::DictionaryValue> value = | 225 DispatchEvent(syncer::sync_ui_util::kOnAboutInfoUpdated, *value); |
| 233 about_sync_data_extractor_->ConstructAboutInformation(sync_service, | |
| 234 signin); | |
| 235 web_ui()->CallJavascriptFunctionUnsafe( | |
| 236 syncer::sync_ui_util::kDispatchEvent, | |
| 237 base::Value(syncer::sync_ui_util::kOnAboutInfoUpdated), *value); | |
| 238 } | 226 } |
| 239 | 227 |
| 240 // Gets the ProfileSyncService of the underlying original profile. | 228 SyncService* SyncInternalsMessageHandler::BindForSyncServiceProvider() { |
| 241 // May return NULL (e.g., if sync is disabled on the command line). | |
| 242 ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() { | |
| 243 Profile* profile = Profile::FromWebUI(web_ui()); | |
| 244 return ProfileSyncServiceFactory::GetForProfile( | 229 return ProfileSyncServiceFactory::GetForProfile( |
| 245 profile->GetOriginalProfile()); | 230 Profile::FromWebUI(web_ui())->GetOriginalProfile()); |
| 246 } | 231 } |
| 232 | |
| 233 void SyncInternalsMessageHandler::DispatchEvent(const std::string& name, | |
| 234 const Value& details_value) { | |
| 235 CallJavascriptFunction(syncer::sync_ui_util::kDispatchEvent, Value(name), | |
| 236 details_value); | |
| 237 } | |
| 238 | |
| 239 void SyncInternalsMessageHandler::UnregisterModelNotifications() { | |
| 240 // Cannot use ScopedObserver to do all the tracking because most don't follow | |
| 241 // AddObserver/RemoveObserver method naming style. | |
| 242 SyncService* service = sync_service_provider_.Run(); | |
|
Dan Beam
2017/05/22 23:31:43
can we get this later (inside both ifs) or early o
skym
2017/05/24 00:20:16
Done, and removed the DCHECKs that don't make sens
| |
| 243 if (is_registered_) { | |
| 244 DCHECK(js_controller_); | |
| 245 DCHECK(service); | |
| 246 | |
| 247 service->RemoveObserver(this); | |
| 248 service->RemoveProtocolEventObserver(this); | |
| 249 js_controller_->RemoveJsEventHandler(this); | |
| 250 | |
| 251 js_controller_ = nullptr; | |
| 252 is_registered_ = false; | |
| 253 } | |
| 254 | |
| 255 if (is_registered_for_counters_) { | |
| 256 DCHECK(service); | |
| 257 service->RemoveTypeDebugInfoObserver(this); | |
| 258 is_registered_for_counters_ = false; | |
| 259 } | |
| 260 } | |
| OLD | NEW |