Index: chrome/browser/ui/webui/sync_internals_message_handler.cc |
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc |
index 4e29f99aa8637096092f329813a2d08459577e35..3a68db41789f4ca9e129e3fed8c5468fd2d34065 100644 |
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc |
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc |
@@ -4,6 +4,8 @@ |
#include "chrome/browser/ui/webui/sync_internals_message_handler.h" |
+#include <stdint.h> |
+ |
#include <utility> |
#include <vector> |
@@ -13,7 +15,6 @@ |
#include "chrome/browser/sync/profile_sync_service_factory.h" |
#include "chrome/common/channel_info.h" |
#include "components/browser_sync/profile_sync_service.h" |
-#include "components/signin/core/browser/signin_manager_base.h" |
#include "components/sync/base/weak_handle.h" |
#include "components/sync/driver/about_sync_util.h" |
#include "components/sync/driver/sync_service.h" |
@@ -25,45 +26,41 @@ |
#include "content/public/browser/browser_thread.h" |
#include "content/public/browser/web_ui.h" |
+using base::DictionaryValue; |
+using base::ListValue; |
+using base::Value; |
using browser_sync::ProfileSyncService; |
using syncer::JsEventDetails; |
using syncer::ModelTypeSet; |
+using syncer::SyncService; |
using syncer::WeakHandle; |
-namespace { |
-class UtilAboutSyncDataExtractor : public AboutSyncDataExtractor { |
- public: |
- std::unique_ptr<base::DictionaryValue> ConstructAboutInformation( |
- syncer::SyncService* service, |
- SigninManagerBase* signin) override { |
- return syncer::sync_ui_util::ConstructAboutInformation( |
- service, signin, chrome::GetChannel()); |
- } |
-}; |
-} // namespace |
- |
SyncInternalsMessageHandler::SyncInternalsMessageHandler() |
: SyncInternalsMessageHandler( |
- base::MakeUnique<UtilAboutSyncDataExtractor>()) {} |
+ base::BindRepeating( |
+ &SyncInternalsMessageHandler::BindForSyncServiceProvider, |
+ base::Unretained(this)), |
+ base::BindRepeating( |
+ &syncer::sync_ui_util::ConstructAboutInformation)) {} |
SyncInternalsMessageHandler::SyncInternalsMessageHandler( |
- std::unique_ptr<AboutSyncDataExtractor> about_sync_data_extractor) |
- : about_sync_data_extractor_(std::move(about_sync_data_extractor)), |
+ SyncServiceProvider sync_service_provider, |
+ AboutSyncDataDelegate about_sync_data_delegate) |
+ : sync_service_provider_(std::move(sync_service_provider)), |
+ about_sync_data_delegate_(std::move(about_sync_data_delegate)), |
weak_ptr_factory_(this) {} |
SyncInternalsMessageHandler::~SyncInternalsMessageHandler() { |
- if (js_controller_) |
- js_controller_->RemoveJsEventHandler(this); |
- |
- ProfileSyncService* service = GetProfileSyncService(); |
- if (service && service->HasObserver(this)) { |
- service->RemoveObserver(this); |
- service->RemoveProtocolEventObserver(this); |
- } |
+ UnregisterModelNotifications(); |
+} |
- if (service && is_registered_for_counters_) { |
- service->RemoveTypeDebugInfoObserver(this); |
- } |
+void SyncInternalsMessageHandler::OnJavascriptDisallowed() { |
+ // Invaliding weak ptrs works well here because the only weak ptr we vend is |
+ // to the sync side to give us information that should be used to populate the |
+ // javascript side. If javascript is disallowed, we don't care about updating |
+ // the UI with data, so dropping those callbacks is fine. |
+ weak_ptr_factory_.InvalidateWeakPtrs(); |
+ UnregisterModelNotifications(); |
} |
void SyncInternalsMessageHandler::RegisterMessages() { |
@@ -96,13 +93,14 @@ void SyncInternalsMessageHandler::RegisterMessages() { |
} |
void SyncInternalsMessageHandler::HandleRegisterForEvents( |
- const base::ListValue* args) { |
+ const ListValue* args) { |
DCHECK(args->empty()); |
+ AllowJavascript(); |
// is_registered_ flag protects us from double-registering. This could |
// happen on a page refresh, where the JavaScript gets re-run but the |
// message handler remains unchanged. |
- ProfileSyncService* service = GetProfileSyncService(); |
+ SyncService* service = sync_service_provider_.Run(); |
if (service && !is_registered_) { |
service->AddObserver(this); |
service->AddProtocolEventObserver(this); |
@@ -113,52 +111,61 @@ void SyncInternalsMessageHandler::HandleRegisterForEvents( |
} |
void SyncInternalsMessageHandler::HandleRegisterForPerTypeCounters( |
- const base::ListValue* args) { |
+ const ListValue* args) { |
DCHECK(args->empty()); |
+ AllowJavascript(); |
+ |
+ SyncService* service = sync_service_provider_.Run(); |
+ if (!service) |
+ return; |
- if (ProfileSyncService* service = GetProfileSyncService()) { |
- if (!is_registered_for_counters_) { |
- service->AddTypeDebugInfoObserver(this); |
- is_registered_for_counters_ = true; |
- } else { |
- // Re-register to ensure counters get re-emitted. |
- service->RemoveTypeDebugInfoObserver(this); |
- service->AddTypeDebugInfoObserver(this); |
- } |
+ if (!is_registered_for_counters_) { |
+ service->AddTypeDebugInfoObserver(this); |
+ is_registered_for_counters_ = true; |
+ } else { |
+ // Re-register to ensure counters get re-emitted. |
+ service->RemoveTypeDebugInfoObserver(this); |
+ service->AddTypeDebugInfoObserver(this); |
} |
} |
void SyncInternalsMessageHandler::HandleRequestUpdatedAboutInfo( |
- const base::ListValue* args) { |
+ const ListValue* args) { |
DCHECK(args->empty()); |
+ AllowJavascript(); |
SendAboutInfo(); |
} |
void SyncInternalsMessageHandler::HandleRequestListOfTypes( |
- const base::ListValue* args) { |
+ const ListValue* args) { |
DCHECK(args->empty()); |
- base::DictionaryValue event_details; |
- std::unique_ptr<base::ListValue> type_list(new base::ListValue()); |
+ AllowJavascript(); |
+ |
+ DictionaryValue event_details; |
+ auto type_list = base::MakeUnique<ListValue>(); |
ModelTypeSet protocol_types = syncer::ProtocolTypes(); |
- for (ModelTypeSet::Iterator it = protocol_types.First(); |
- it.Good(); it.Inc()) { |
+ for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); |
+ it.Inc()) { |
type_list->AppendString(ModelTypeToString(it.Get())); |
} |
event_details.Set(syncer::sync_ui_util::kTypes, std::move(type_list)); |
- web_ui()->CallJavascriptFunctionUnsafe( |
- syncer::sync_ui_util::kDispatchEvent, |
- base::Value(syncer::sync_ui_util::kOnReceivedListOfTypes), event_details); |
+ DispatchEvent(syncer::sync_ui_util::kOnReceivedListOfTypes, event_details); |
} |
-void SyncInternalsMessageHandler::HandleGetAllNodes( |
- const base::ListValue* args) { |
+void SyncInternalsMessageHandler::HandleGetAllNodes(const ListValue* args) { |
DCHECK_EQ(1U, args->GetSize()); |
+ AllowJavascript(); |
+ |
int request_id = 0; |
bool success = ExtractIntegerValue(args, &request_id); |
DCHECK(success); |
- ProfileSyncService* service = GetProfileSyncService(); |
+ SyncService* service = sync_service_provider_.Run(); |
if (service) { |
+ // This opens up the possibility of non-javascript code calling us |
+ // asynchronously, and potentially at times we're not allowed to call into |
+ // the javascript side. We guard against this by invalidating this weak ptr |
+ // should javascript become disallowed. |
service->GetAllNodes( |
base::Bind(&SyncInternalsMessageHandler::OnReceivedAllNodes, |
weak_ptr_factory_.GetWeakPtr(), request_id)); |
@@ -167,23 +174,19 @@ void SyncInternalsMessageHandler::HandleGetAllNodes( |
void SyncInternalsMessageHandler::OnReceivedAllNodes( |
int request_id, |
- std::unique_ptr<base::ListValue> nodes) { |
- base::Value id(request_id); |
- web_ui()->CallJavascriptFunctionUnsafe( |
- syncer::sync_ui_util::kGetAllNodesCallback, id, *nodes); |
+ std::unique_ptr<ListValue> nodes) { |
+ CallJavascriptFunction(syncer::sync_ui_util::kGetAllNodesCallback, |
+ Value(request_id), *nodes); |
} |
-void SyncInternalsMessageHandler::OnStateChanged(syncer::SyncService* sync) { |
+void SyncInternalsMessageHandler::OnStateChanged(SyncService* sync) { |
SendAboutInfo(); |
} |
void SyncInternalsMessageHandler::OnProtocolEvent( |
const syncer::ProtocolEvent& event) { |
- std::unique_ptr<base::DictionaryValue> value( |
- syncer::ProtocolEvent::ToValue(event)); |
- web_ui()->CallJavascriptFunctionUnsafe( |
- syncer::sync_ui_util::kDispatchEvent, |
- base::Value(syncer::sync_ui_util::kOnProtocolEvent), *value); |
+ std::unique_ptr<DictionaryValue> value(syncer::ProtocolEvent::ToValue(event)); |
+ DispatchEvent(syncer::sync_ui_util::kOnProtocolEvent, *value); |
} |
void SyncInternalsMessageHandler::OnCommitCountersUpdated( |
@@ -207,14 +210,12 @@ void SyncInternalsMessageHandler::OnStatusCountersUpdated( |
void SyncInternalsMessageHandler::EmitCounterUpdate( |
syncer::ModelType type, |
const std::string& counter_type, |
- std::unique_ptr<base::DictionaryValue> value) { |
- std::unique_ptr<base::DictionaryValue> details(new base::DictionaryValue()); |
+ std::unique_ptr<DictionaryValue> value) { |
+ auto details = base::MakeUnique<DictionaryValue>(); |
details->SetString(syncer::sync_ui_util::kModelType, ModelTypeToString(type)); |
details->SetString(syncer::sync_ui_util::kCounterType, counter_type); |
details->Set(syncer::sync_ui_util::kCounters, std::move(value)); |
- web_ui()->CallJavascriptFunctionUnsafe( |
- syncer::sync_ui_util::kDispatchEvent, |
- base::Value(syncer::sync_ui_util::kOnCountersUpdated), *details); |
+ DispatchEvent(syncer::sync_ui_util::kOnCountersUpdated, *details); |
} |
void SyncInternalsMessageHandler::HandleJsEvent( |
@@ -222,25 +223,44 @@ void SyncInternalsMessageHandler::HandleJsEvent( |
const JsEventDetails& details) { |
DVLOG(1) << "Handling event: " << name |
<< " with details " << details.ToString(); |
- web_ui()->CallJavascriptFunctionUnsafe(syncer::sync_ui_util::kDispatchEvent, |
- base::Value(name), details.Get()); |
+ DispatchEvent(name, details.Get()); |
} |
void SyncInternalsMessageHandler::SendAboutInfo() { |
- ProfileSyncService* sync_service = GetProfileSyncService(); |
- SigninManagerBase* signin = sync_service ? sync_service->signin() : nullptr; |
- std::unique_ptr<base::DictionaryValue> value = |
- about_sync_data_extractor_->ConstructAboutInformation(sync_service, |
- signin); |
- web_ui()->CallJavascriptFunctionUnsafe( |
- syncer::sync_ui_util::kDispatchEvent, |
- base::Value(syncer::sync_ui_util::kOnAboutInfoUpdated), *value); |
-} |
- |
-// Gets the ProfileSyncService of the underlying original profile. |
-// May return NULL (e.g., if sync is disabled on the command line). |
-ProfileSyncService* SyncInternalsMessageHandler::GetProfileSyncService() { |
- Profile* profile = Profile::FromWebUI(web_ui()); |
+ std::unique_ptr<DictionaryValue> value = about_sync_data_delegate_.Run( |
+ sync_service_provider_.Run(), chrome::GetChannel()); |
+ DispatchEvent(syncer::sync_ui_util::kOnAboutInfoUpdated, *value); |
+} |
+ |
+SyncService* SyncInternalsMessageHandler::BindForSyncServiceProvider() { |
return ProfileSyncServiceFactory::GetForProfile( |
- profile->GetOriginalProfile()); |
+ Profile::FromWebUI(web_ui())->GetOriginalProfile()); |
+} |
+ |
+void SyncInternalsMessageHandler::DispatchEvent(const std::string& name, |
+ const Value& details_value) { |
+ CallJavascriptFunction(syncer::sync_ui_util::kDispatchEvent, Value(name), |
+ details_value); |
+} |
+ |
+void SyncInternalsMessageHandler::UnregisterModelNotifications() { |
+ SyncService* service = sync_service_provider_.Run(); |
+ if (!service) |
+ return; |
+ |
+ // Cannot use ScopedObserver to do all the tracking because most don't follow |
+ // AddObserver/RemoveObserver method naming style. |
+ if (is_registered_) { |
+ DCHECK(js_controller_); |
+ service->RemoveObserver(this); |
+ service->RemoveProtocolEventObserver(this); |
+ js_controller_->RemoveJsEventHandler(this); |
+ js_controller_ = nullptr; |
+ is_registered_ = false; |
+ } |
+ |
+ if (is_registered_for_counters_) { |
+ service->RemoveTypeDebugInfoObserver(this); |
+ is_registered_for_counters_ = false; |
+ } |
} |