sync_internals_ui.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/sync_internals_ui.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/tracked_objects.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/about_sync_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/profile_sync_service_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/sync_ui_util.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tab_contents/tab_contents.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/chrome_url_data_manager.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/chrome_web_ui_data_source.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_messages.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_ui.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/sync_internals_resources.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/util/weak_handle.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/js/js_arg_list.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/js/js_controller.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/js/js_event_details.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::JsArgList;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::JsEventDetails;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::JsReplyHandler;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using syncer::WeakHandle;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeWebUIDataSource* CreateSyncInternalsHTMLSource() {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromeWebUIDataSource* source =
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new ChromeWebUIDataSource(chrome::kChromeUISyncInternalsHost);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->set_json_path("strings.js");
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("sync_index.js", IDR_SYNC_INTERNALS_INDEX_JS);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("chrome_sync.js",
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_CHROME_SYNC_JS);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("sync_log.js", IDR_SYNC_INTERNALS_SYNC_LOG_JS);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("sync_node_browser.js",
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_SYNC_NODE_BROWSER_JS);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("sync_search.js",
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_SYNC_SEARCH_JS);
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("about.js", IDR_SYNC_INTERNALS_ABOUT_JS);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("data.js", IDR_SYNC_INTERNALS_DATA_JS);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("events.js", IDR_SYNC_INTERNALS_EVENTS_JS);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("notifications.js",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_NOTIFICATIONS_JS);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("search.js", IDR_SYNC_INTERNALS_SEARCH_JS);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("node_browser.js",
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_NODE_BROWSER_JS);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->add_resource_path("traffic.js",
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IDR_SYNC_INTERNALS_TRAFFIC_JS);
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  source->set_default_resource(IDR_SYNC_INTERNALS_INDEX_HTML);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return source;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets the ProfileSyncService of the underlying original profile.
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// May return NULL (e.g., if sync is disabled on the command line).
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProfileSyncService* GetProfileSyncService(Profile* profile) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProfileSyncServiceFactory::GetInstance()->GetForProfile(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile->GetOriginalProfile());
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncInternalsUI::SyncInternalsUI(content::WebUI* web_ui)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : WebUIController(web_ui),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(akalin): Fix.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Profile* profile = Profile::FromWebUI(web_ui);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromeURLDataManager::AddDataSource(profile, CreateSyncInternalsHTMLSource());
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProfileSyncService* sync_service = GetProfileSyncService(profile);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sync_service) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_controller_ = sync_service->GetJsController();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (js_controller_.get()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_controller_->AddJsEventHandler(this);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncInternalsUI::~SyncInternalsUI() {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (js_controller_.get()) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    js_controller_->RemoveJsEventHandler(this);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncInternalsUI::OverrideHandleWebUIMessage(const GURL& source_url,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const std::string& name,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 const ListValue& content) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ListValue> content_copy(content.DeepCopy());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  JsArgList args(content_copy.get());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Received message: " << name << " with args "
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << args.ToString();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We handle this case directly because it needs to work even if
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the sync service doesn't exist.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (name == "getAboutInfo") {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ListValue return_args;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile = Profile::FromWebUI(web_ui());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProfileSyncService* service = GetProfileSyncService(profile);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return_args.Append(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sync_ui_util::ConstructAboutInformation(service).release());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandleJsReply(name, JsArgList(&return_args));
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (js_controller_.get()) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      js_controller_->ProcessJsMessage(
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          name, args,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          MakeWeakHandle(weak_ptr_factory_.GetWeakPtr()));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(WARNING) << "No sync service; dropping message " << name
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   << " with args " << args.ToString();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInternalsUI::HandleJsEvent(
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name, const JsEventDetails& details) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Handling event: " << name << " with details "
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << details.ToString();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& event_handler = "chrome.sync." + name + ".fire";
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const Value*> arg_list(1, &details.Get());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(event_handler, arg_list);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncInternalsUI::HandleJsReply(
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& name, const JsArgList& args) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Handling reply for " << name << " message with args "
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << args.ToString();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& reply_handler = "chrome.sync." + name + ".handleReply";
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<const Value*> arg_list(args.Get().begin(), args.Get().end());
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  web_ui()->CallJavascriptFunction(reply_handler, arg_list);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
148