Index: chrome/browser/sync/personalization.cc |
=================================================================== |
--- chrome/browser/sync/personalization.cc (revision 0) |
+++ chrome/browser/sync/personalization.cc (revision 0) |
@@ -0,0 +1,339 @@ |
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifdef CHROME_PERSONALIZATION |
+ |
+#include "chrome/browser/sync/personalization.h" |
+ |
+#include "app/resource_bundle.h" |
+#include "base/command_line.h" |
+#include "base/file_path.h" |
+#include "base/file_util.h" |
+#include "base/path_service.h" |
+#include "base/string_util.h" |
+#include "chrome/app/chrome_dll_resource.h" |
+#include "chrome/browser/browser.h" |
+#include "chrome/browser/browser_process.h" |
+#include "chrome/browser/browser_url_handler.h" |
+#include "chrome/browser/command_updater.h" |
+#include "chrome/browser/options_window.h" |
+#include "chrome/browser/profile.h" |
+#include "chrome/browser/profile_manager.h" |
+#include "chrome/common/chrome_paths.h" |
+#include "chrome/common/chrome_switches.h" |
+#include "chrome/common/jstemplate_builder.h" |
+#include "chrome/common/notification_service.h" |
+#include "chrome/common/pref_service.h" |
+#include "chrome/browser/dom_ui/new_tab_page_sync_handler.h" |
+#include "chrome/browser/sync/personalization_strings.h" |
+#include "chrome/browser/sync/auth_error_state.h" |
+#include "chrome/browser/sync/profile_sync_service.h" |
+#include "googleurl/src/gurl.h" |
+#include "grit/app_resources.h" |
+#include "grit/browser_resources.h" |
+#include "net/url_request/url_request.h" |
+ |
+using sync_api::SyncManager; |
+ |
+// TODO(ncarter): Move these switches into chrome_switches. They are here |
+// now because we want to keep them secret during early development. |
+namespace switches { |
+ const wchar_t kSyncServiceURL[] = L"sync-url"; |
+ const wchar_t kSyncServicePort[] = L"sync-port"; |
+ const wchar_t kSyncUserForTest[] = L"sync-user-for-test"; |
+ const wchar_t kSyncPasswordForTest[] = L"sync-password-for-test"; |
+} |
+ |
+// TODO(munjal): Move these preferences to common/pref_names.h. |
+// Names of various preferences. |
+namespace prefs { |
+ const wchar_t kSyncPath[] = L"sync"; |
+ const wchar_t kSyncLastSyncedTime[] = L"sync.last_synced_time"; |
+ const wchar_t kSyncUserName[] = L"sync.username"; |
+ const wchar_t kSyncHasSetupCompleted[] = L"sync.has_setup_completed"; |
+} |
+ |
+// Top-level path for our network layer DataSource. |
+static const char kCloudyResourcesPath[] = "resources"; |
+// Path for cloudy:stats page. |
+static const char kCloudyStatsPath[] = "stats"; |
+// Path for the gaia sync login dialog. |
+static const char kCloudyGaiaLoginPath[] = "gaialogin"; |
+static const char kCloudyMergeAndSyncPath[] = "mergeandsync"; |
+static const char kCloudyThrobberPath[] = "throbber.png"; |
+static const char kCloudySetupFlowPath[] = "setup"; |
+ |
+namespace Personalization { |
+ |
+static std::wstring MakeAuthErrorText(AuthErrorState state) { |
+ switch (state) { |
+ case AUTH_ERROR_INVALID_GAIA_CREDENTIALS: |
+ return L"INVALID_GAIA_CREDENTIALS"; |
+ case AUTH_ERROR_USER_NOT_SIGNED_UP: |
+ return L"USER_NOT_SIGNED_UP"; |
+ case AUTH_ERROR_CONNECTION_FAILED: |
+ return L"CONNECTION_FAILED"; |
+ default: |
+ return std::wstring(); |
+ } |
+} |
+ |
+bool IsP13NDisabled(Profile* profile) { |
+ const CommandLine* command_line = CommandLine::ForCurrentProcess(); |
+ if (command_line->HasSwitch(switches::kDisableP13n)) |
+ return true; |
+ return !profile || profile->GetProfilePersonalization() == NULL; |
+} |
+ |
+bool NeedsDOMUI(const GURL& url) { |
+ return url.SchemeIs(kPersonalizationScheme) && |
+ (url.path().find(kCloudyGaiaLoginPath) != std::string::npos) || |
+ (url.path().find(kCloudySetupFlowPath) != std::string::npos) || |
+ (url.path().find(kCloudyMergeAndSyncPath) != std::string::npos); |
+} |
+ |
+class CloudyResourceSource : public ChromeURLDataManager::DataSource { |
+ public: |
+ CloudyResourceSource() |
+ : DataSource(kCloudyResourcesPath, MessageLoop::current()) { |
+ } |
+ virtual ~CloudyResourceSource() { } |
+ |
+ virtual void StartDataRequest(const std::string& path, int request_id); |
+ |
+ virtual std::string GetMimeType(const std::string& path) const { |
+ if (path == kCloudyThrobberPath) |
+ return "image/png"; |
+ else |
+ return "text/html"; |
+ } |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(CloudyResourceSource); |
+}; |
+ |
+class CloudyStatsSource : public ChromeURLDataManager::DataSource { |
+ public: |
+ CloudyStatsSource() : DataSource(kCloudyStatsPath, MessageLoop::current()) { |
+ } |
+ virtual ~CloudyStatsSource() { } |
+ virtual void StartDataRequest(const std::string& path, int request_id) { |
+ std::string response(MakeCloudyStats()); |
+ scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
+ html_bytes->data.resize(response.size()); |
+ std::copy(response.begin(), response.end(), html_bytes->data.begin()); |
+ SendResponse(request_id, html_bytes); |
+ } |
+ virtual std::string GetMimeType(const std::string& path) const { |
+ return "text/html"; |
+ } |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(CloudyStatsSource); |
+}; |
+ |
+DOMMessageHandler* CreateNewTabPageHandler(DOMUI* dom_ui) { |
+ return (new NewTabPageSyncHandler())->Attach(dom_ui); |
+} |
+ |
+std::string GetNewTabSource() { |
+ static const StringPiece new_tab_html( |
+ ResourceBundle::GetSharedInstance().GetRawDataResource( |
+ IDR_NEW_TAB_P13N_HTML)); |
+ |
+ std::string data_uri("data:text/html,"); |
+ data_uri.append(std::string(new_tab_html.data(), new_tab_html.size())); |
+ return GURL(data_uri).spec(); |
+} |
+ |
+std::wstring GetMenuItemInfoText(Browser* browser) { |
+ browser->command_updater()->UpdateCommandEnabled(IDC_P13N_INFO, true); |
+ return kMenuLabelStartSync; |
+} |
+ |
+void HandleMenuItemClick(Profile* p) { |
+ // The menu item is enabled either when the sync is not enabled by the user |
+ // or when it's enabled but the user name is empty. In the former case enable |
+ // sync. In the latter case, show the login dialog. |
+ ProfileSyncService* service = p->GetProfilePersonalization()->sync_service(); |
+ DCHECK(service); |
+ if (service->IsSyncEnabledByUser()) { |
+ ShowOptionsWindow(OPTIONS_PAGE_USER_DATA, OPTIONS_GROUP_NONE, p); |
+ } else { |
+ service->EnableForUser(); |
+ } |
+} |
+ |
+} // namespace Personalization |
+ |
+class ProfilePersonalizationImpl : public ProfilePersonalization, |
+ public NotificationObserver { |
+ public: |
+ explicit ProfilePersonalizationImpl(Profile *p) |
+ : profile_(p) { |
+ // g_browser_process and/or io_thread may not exist during testing. |
+ if (g_browser_process && g_browser_process->io_thread()) { |
+ // Add our network layer data source for 'cloudy' URLs. |
+ // TODO(timsteele): This one belongs in BrowserAboutHandler. |
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, |
+ NewRunnableMethod(&chrome_url_data_manager, |
+ &ChromeURLDataManager::AddDataSource, |
+ new Personalization::CloudyStatsSource())); |
+ g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, |
+ NewRunnableMethod(&chrome_url_data_manager, |
+ &ChromeURLDataManager::AddDataSource, |
+ new Personalization::CloudyResourceSource())); |
+ } |
+ |
+ registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED, |
+ Source<Profile>(profile_)); |
+ } |
+ virtual ~ProfilePersonalizationImpl() {} |
+ |
+ // ProfilePersonalization implementation |
+ virtual ProfileSyncService* sync_service() { |
+ if (!sync_service_.get()) |
+ InitSyncService(); |
+ return sync_service_.get(); |
+ } |
+ |
+ // NotificationObserver implementation. |
+ virtual void Observe(NotificationType type, |
+ const NotificationSource& source, |
+ const NotificationDetails& details) { |
+ DCHECK_EQ(type.value, NotificationType::BOOKMARK_MODEL_LOADED); |
+ if (!sync_service_.get()) |
+ InitSyncService(); |
+ registrar_.RemoveAll(); |
+ } |
+ |
+ void InitSyncService() { |
+ sync_service_.reset(new ProfileSyncService(profile_)); |
+ sync_service_->Initialize(); |
+ } |
+ |
+ private: |
+ Profile* profile_; |
+ NotificationRegistrar registrar_; |
+ scoped_ptr<ProfileSyncService> sync_service_; |
+ DISALLOW_COPY_AND_ASSIGN(ProfilePersonalizationImpl); |
+}; |
+ |
+namespace Personalization { |
+ |
+void CloudyResourceSource::StartDataRequest(const std::string& path_raw, |
+ int request_id) { |
+ scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes); |
+ if (path_raw == kCloudyThrobberPath) { |
+ ResourceBundle::GetSharedInstance().LoadImageResourceBytes(IDR_THROBBER, |
+ &html_bytes->data); |
+ SendResponse(request_id, html_bytes); |
+ return; |
+ } |
+ |
+ std::string response; |
+ if (path_raw == kCloudyGaiaLoginPath) { |
+ static const StringPiece html(ResourceBundle::GetSharedInstance() |
+ .GetRawDataResource(IDR_GAIA_LOGIN_HTML)); |
+ response = html.as_string(); |
+ } else if (path_raw == kCloudyMergeAndSyncPath) { |
+ static const StringPiece html(ResourceBundle::GetSharedInstance() |
+ .GetRawDataResource(IDR_MERGE_AND_SYNC_HTML)); |
+ response = html.as_string(); |
+ } else if (path_raw == kCloudySetupFlowPath) { |
+ static const StringPiece html(ResourceBundle::GetSharedInstance() |
+ .GetRawDataResource(IDR_SYNC_SETUP_FLOW_HTML)); |
+ response = html.as_string(); |
+ } |
+ // Send the response. |
+ html_bytes->data.resize(response.size()); |
+ std::copy(response.begin(), response.end(), html_bytes->data.begin()); |
+ SendResponse(request_id, html_bytes); |
+} |
+ |
+ProfilePersonalization* CreateProfilePersonalization(Profile* p) { |
+ return new ProfilePersonalizationImpl(p); |
+} |
+ |
+void CleanupProfilePersonalization(ProfilePersonalization* p) { |
+ if (p) delete p; |
+} |
+ |
+static void AddBoolDetail(ListValue* details, const std::wstring& stat_name, |
+ bool stat_value) { |
+ DictionaryValue* val = new DictionaryValue; |
+ val->SetString(L"stat_name", stat_name); |
+ val->SetBoolean(L"stat_value", stat_value); |
+ details->Append(val); |
+} |
+ |
+static void AddIntDetail(ListValue* details, const std::wstring& stat_name, |
+ int64 stat_value) { |
+ DictionaryValue* val = new DictionaryValue; |
+ val->SetString(L"stat_name", stat_name); |
+ val->SetString(L"stat_value", FormatNumber(stat_value)); |
+ details->Append(val); |
+} |
+ |
+std::string MakeCloudyStats() { |
+ FilePath user_data_dir; |
+ if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) |
+ return std::string(); |
+ ProfileManager* profile_manager = g_browser_process->profile_manager(); |
+ Profile* profile = profile_manager->GetDefaultProfile(user_data_dir); |
+ ProfilePersonalization* p13n_profile = profile->GetProfilePersonalization(); |
+ ProfileSyncService* service = p13n_profile->sync_service(); |
+ |
+ DictionaryValue strings; |
+ if (!service->IsSyncEnabledByUser()) { |
+ strings.SetString(L"summary", L"SYNC DISABLED"); |
+ } else { |
+ SyncManager::Status full_status(service->QueryDetailedSyncStatus()); |
+ |
+ strings.SetString(L"summary", |
+ ProfileSyncService::BuildSyncStatusSummaryText( |
+ full_status.summary)); |
+ |
+ strings.Set(L"authenticated", |
+ new FundamentalValue(full_status.authenticated)); |
+ strings.SetString(L"auth_problem", |
+ MakeAuthErrorText(service->GetAuthErrorState())); |
+ |
+ strings.SetString(L"time_since_sync", service->GetLastSyncedTimeString()); |
+ |
+ ListValue* details = new ListValue(); |
+ strings.Set(L"details", details); |
+ AddBoolDetail(details, L"Server Up", full_status.server_up); |
+ AddBoolDetail(details, L"Server Reachable", full_status.server_reachable); |
+ AddBoolDetail(details, L"Server Broken", full_status.server_broken); |
+ AddBoolDetail(details, L"Notifications Enabled", |
+ full_status.notifications_enabled); |
+ AddIntDetail(details, L"Notifications Received", |
+ full_status.notifications_received); |
+ AddIntDetail(details, L"Notifications Sent", |
+ full_status.notifications_sent); |
+ AddIntDetail(details, L"Unsynced Count", full_status.unsynced_count); |
+ AddIntDetail(details, L"Conflicting Count", full_status.conflicting_count); |
+ AddBoolDetail(details, L"Syncing", full_status.syncing); |
+ AddBoolDetail(details, L"Syncer Paused", full_status.syncer_paused); |
+ AddBoolDetail(details, L"Initial Sync Ended", |
+ full_status.initial_sync_ended); |
+ AddBoolDetail(details, L"Syncer Stuck", full_status.syncer_stuck); |
+ AddIntDetail(details, L"Updates Available", full_status.updates_available); |
+ AddIntDetail(details, L"Updates Received", full_status.updates_received); |
+ AddBoolDetail(details, L"Disk Full", full_status.disk_full); |
+ AddBoolDetail(details, L"Invalid Store", full_status.invalid_store); |
+ AddIntDetail(details, L"Max Consecutive Errors", |
+ full_status.max_consecutive_errors); |
+ } |
+ |
+ static const StringPiece sync_html( |
+ ResourceBundle::GetSharedInstance().GetRawDataResource( |
+ IDR_ABOUT_SYNC_HTML)); |
+ |
+ return jstemplate_builder::GetTemplateHtml( |
+ sync_html, &strings , "t" /* template root node id */); |
+} |
+ |
+} // namespace Personalization |
+ |
+#endif // CHROME_PERSONALIZATION |
Property changes on: chrome\browser\sync\personalization.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |