| Index: chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
|
| diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..566fed4382cb16cf70fe7c47fcb9a6b37f85eb65
|
| --- /dev/null
|
| +++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
|
| @@ -0,0 +1,430 @@
|
| +// Copyright (c) 2010 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.
|
| +
|
| +#include "chrome/browser/printing/cloud_print/cloud_print_setup_flow.h"
|
| +
|
| +#include "app/gfx/font_util.h"
|
| +#include "base/json/json_writer.h"
|
| +#include "base/singleton.h"
|
| +#include "base/string_util.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/browser.h"
|
| +#include "chrome/browser/browser_list.h"
|
| +#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
|
| +#include "chrome/browser/dom_ui/dom_ui_util.h"
|
| +#include "chrome/browser/platform_util.h"
|
| +#include "chrome/browser/prefs/pref_service.h"
|
| +#include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h"
|
| +#include "chrome/browser/profile.h"
|
| +#include "chrome/browser/remoting/remoting_resources_source.h"
|
| +#include "chrome/browser/renderer_host/render_view_host.h"
|
| +#include "chrome/browser/service/service_process_control.h"
|
| +#include "chrome/browser/service/service_process_control_manager.h"
|
| +#include "chrome/browser/tab_contents/tab_contents.h"
|
| +#include "chrome/common/net/gaia/gaia_authenticator2.h"
|
| +#include "chrome/common/net/gaia/gaia_constants.h"
|
| +#include "chrome/common/net/gaia/google_service_auth_error.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "chrome/common/service_messages.h"
|
| +#include "chrome/common/service_process_type.h"
|
| +#include "gfx/font.h"
|
| +#include "grit/locale_settings.h"
|
| +
|
| +static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
|
| +static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']";
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// CloudPrintServiceProcessHelper
|
| +//
|
| +// This is a helper class to perform actions when the service process
|
| +// is connected or launched. The events are sent back to CloudPrintSetupFlow
|
| +// when the dialog is still active. CloudPrintSetupFlow can detach from this
|
| +// helper class when the dialog is closed.
|
| +
|
| +class CloudPrintServiceProcessHelper
|
| + : public base::RefCountedThreadSafe<CloudPrintServiceProcessHelper> {
|
| + public:
|
| + explicit CloudPrintServiceProcessHelper(CloudPrintSetupFlow* flow)
|
| + : flow_(flow) {
|
| + }
|
| +
|
| + void Detach() {
|
| + flow_ = NULL;
|
| + }
|
| +
|
| + void OnProcessLaunched() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| + // If the flow is detached then show the done page.
|
| + if (!flow_)
|
| + return;
|
| +
|
| + flow_->OnProcessLaunched();
|
| + }
|
| +
|
| + private:
|
| + CloudPrintSetupFlow* flow_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceProcessHelper);
|
| +};
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// CloudPrintServiceDisableTask
|
| +//
|
| +// This is a helper class to get the proxy service launched if it
|
| +// isn't, in order to properly inform it that it should be disabled.
|
| +
|
| +class CloudPrintServiceDisableTask
|
| + : public base::RefCountedThreadSafe<CloudPrintServiceDisableTask> {
|
| + public:
|
| + explicit CloudPrintServiceDisableTask(Profile* profile)
|
| + : profile_(profile),
|
| + process_control_(NULL) {
|
| + }
|
| +
|
| + void StartDisable() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| +
|
| + process_control_ =
|
| + ServiceProcessControlManager::instance()->GetProcessControl(
|
| + profile_,
|
| + kServiceProcessCloudPrint);
|
| +
|
| + if (process_control_) {
|
| + // If the process isn't connected, launch it now. This will run
|
| + // the task whether the process is already launched or not, as
|
| + // long as it's able to connect back up.
|
| + process_control_->Launch(
|
| + NewRunnableMethod(
|
| + this, &CloudPrintServiceDisableTask::OnProcessLaunched));
|
| + }
|
| + }
|
| +
|
| + void OnProcessLaunched() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| + DCHECK(process_control_);
|
| + if (process_control_->is_connected())
|
| + process_control_->Send(new ServiceMsg_DisableCloudPrintProxy());
|
| + profile_->GetPrefs()->SetString(prefs::kCloudPrintEmail, std::string());
|
| + }
|
| +
|
| + private:
|
| + Profile* profile_;
|
| + ServiceProcessControl* process_control_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceDisableTask);
|
| +};
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// CloudPrintServiceRefreshTask
|
| +//
|
| +// This is a helper class to perform a preferences refresh of the
|
| +// enablement state and registered e-mail from the cloud print proxy
|
| +// service.
|
| +
|
| +class CloudPrintServiceRefreshTask
|
| + : public base::RefCountedThreadSafe<CloudPrintServiceRefreshTask> {
|
| + public:
|
| + explicit CloudPrintServiceRefreshTask(
|
| + Profile* profile,
|
| + Callback2<bool, std::string>::Type* callback)
|
| + : profile_(profile),
|
| + process_control_(NULL),
|
| + callback_(callback) {
|
| + DCHECK(callback);
|
| + }
|
| +
|
| + void StartRefresh() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| +
|
| + process_control_ =
|
| + ServiceProcessControlManager::instance()->GetProcessControl(
|
| + profile_,
|
| + kServiceProcessCloudPrint);
|
| +
|
| + if (process_control_) {
|
| + // If the process isn't connected, launch it now. This will run
|
| + // the task whether the process is already launched or not, as
|
| + // long as it's able to connect back up.
|
| + process_control_->Launch(
|
| + NewRunnableMethod(
|
| + this, &CloudPrintServiceRefreshTask::OnProcessLaunched));
|
| + }
|
| + }
|
| +
|
| + void OnProcessLaunched() {
|
| + DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
|
| + DCHECK(process_control_);
|
| +
|
| + if (callback_ != NULL)
|
| + process_control_->GetCloudPrintProxyStatus(callback_.release());
|
| + }
|
| +
|
| + private:
|
| + Profile* profile_;
|
| + ServiceProcessControl* process_control_;
|
| +
|
| + // Callback that gets invoked when a status message is received from
|
| + // the cloud print proxy.
|
| + scoped_ptr<Callback2<bool, std::string>::Type> callback_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CloudPrintServiceRefreshTask);
|
| +};
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// CloudPrintSetupFlow implementation.
|
| +
|
| +// static
|
| +CloudPrintSetupFlow* CloudPrintSetupFlow::OpenDialog(Profile* profile) {
|
| + // Set the arguments for showing the gaia login page.
|
| + DictionaryValue args;
|
| + args.SetString("iframeToShow", "login");
|
| + args.SetString("user", "");
|
| + args.SetInteger("error", 0);
|
| + args.SetBoolean("editable_user", true);
|
| +
|
| + if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
|
| + !profile->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty()) {
|
| + args.SetString("iframeToShow", "done");
|
| + }
|
| +
|
| + std::string json_args;
|
| + base::JSONWriter::Write(&args, false, &json_args);
|
| +
|
| + // Create a browser to run the dialog. The new CloudPrintSetupFlow
|
| + // class takes ownership.
|
| + Browser* browser = Browser::CreateForPopup(profile);
|
| + DCHECK(browser);
|
| +
|
| + CloudPrintSetupFlow* flow = new CloudPrintSetupFlow(json_args, browser);
|
| + browser->BrowserShowHtmlDialog(flow, NULL);
|
| + return flow;
|
| +}
|
| +
|
| +// static
|
| +void CloudPrintSetupFlow::DisableCloudPrintProxy(Profile* profile) {
|
| + scoped_refptr<CloudPrintServiceDisableTask> refresh_task =
|
| + new CloudPrintServiceDisableTask(profile);
|
| + ChromeThread::PostTask(
|
| + ChromeThread::UI, FROM_HERE,
|
| + NewRunnableMethod(refresh_task.get(),
|
| + &CloudPrintServiceDisableTask::StartDisable));
|
| +}
|
| +
|
| +// static
|
| +void CloudPrintSetupFlow::RefreshPreferencesFromService(
|
| + Profile* profile,
|
| + Callback2<bool, std::string>::Type* callback) {
|
| + scoped_refptr<CloudPrintServiceRefreshTask> refresh_task =
|
| + new CloudPrintServiceRefreshTask(profile, callback);
|
| + ChromeThread::PostTask(
|
| + ChromeThread::UI, FROM_HERE,
|
| + NewRunnableMethod(refresh_task.get(),
|
| + &CloudPrintServiceRefreshTask::StartRefresh));
|
| +}
|
| +
|
| +CloudPrintSetupFlow::CloudPrintSetupFlow(const std::string& args,
|
| + Browser* browser)
|
| + : dom_ui_(NULL),
|
| + dialog_start_args_(args),
|
| + process_control_(NULL) {
|
| + // TODO(hclam): The data source should be added once.
|
| + browser_.reset(browser);
|
| + ChromeThread::PostTask(
|
| + ChromeThread::IO, FROM_HERE,
|
| + NewRunnableMethod(Singleton<ChromeURLDataManager>::get(),
|
| + &ChromeURLDataManager::AddDataSource,
|
| + make_scoped_refptr(new RemotingResourcesSource())));
|
| +}
|
| +
|
| +CloudPrintSetupFlow::~CloudPrintSetupFlow() {
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::Focus() {
|
| + // TODO(pranavk): implement this method.
|
| + NOTIMPLEMENTED();
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// HtmlDialogUIDelegate implementation.
|
| +GURL CloudPrintSetupFlow::GetDialogContentURL() const {
|
| + return GURL("chrome://remotingresources/setup");
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::GetDOMMessageHandlers(
|
| + std::vector<DOMMessageHandler*>* handlers) const {
|
| + // Create the message handler only after we are asked, the caller is
|
| + // responsible for deleting the objects.
|
| + handlers->push_back(
|
| + new CloudPrintSetupMessageHandler(
|
| + const_cast<CloudPrintSetupFlow*>(this)));
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::GetDialogSize(gfx::Size* size) const {
|
| + PrefService* prefs = browser_->profile()->GetPrefs();
|
| + gfx::Font approximate_web_font(
|
| + UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
|
| + prefs->GetInteger(prefs::kWebKitDefaultFontSize));
|
| +
|
| + // TODO(pranavk) Replace the following SYNC resources with REMOTING Resources.
|
| + *size = gfx::GetLocalizedContentsSizeForFont(
|
| + IDS_SYNC_SETUP_WIZARD_WIDTH_CHARS,
|
| + IDS_SYNC_SETUP_WIZARD_HEIGHT_LINES,
|
| + approximate_web_font);
|
| +}
|
| +
|
| +// A callback to notify the delegate that the dialog closed.
|
| +void CloudPrintSetupFlow::OnDialogClosed(const std::string& json_retval) {
|
| + // If we are fetching the token then cancel the request.
|
| + if (authenticator_.get())
|
| + authenticator_->CancelRequest();
|
| +
|
| + // If the service process helper is still active then detach outself from it.
|
| + // This is because the dialog is closing and this object is going to be
|
| + // deleted but the service process launch is still in progress so we don't
|
| + // the service process helper to call us when the process is launched.
|
| + if (service_process_helper_.get())
|
| + service_process_helper_->Detach();
|
| + delete this;
|
| +}
|
| +
|
| +std::string CloudPrintSetupFlow::GetDialogArgs() const {
|
| + return dialog_start_args_;
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::OnCloseContents(TabContents* source,
|
| + bool* out_close_dialog) {
|
| +}
|
| +
|
| +std::wstring CloudPrintSetupFlow::GetDialogTitle() const {
|
| + return l10n_util::GetString(IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE);
|
| +}
|
| +
|
| +bool CloudPrintSetupFlow::IsDialogModal() const {
|
| + return true;
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// GaiaAuthConsumer implementation.
|
| +void CloudPrintSetupFlow::OnClientLoginFailure(
|
| + const GoogleServiceAuthError& error) {
|
| + ShowGaiaFailed(error);
|
| + authenticator_.reset();
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::OnClientLoginSuccess(
|
| + const GaiaAuthConsumer::ClientLoginResult& credentials) {
|
| + // Save the token for the cloud print proxy.
|
| + lsid_ = credentials.lsid;
|
| +
|
| + // Show that Gaia login has succeeded.
|
| + ShowGaiaSuccessAndSettingUp();
|
| + authenticator_.reset();
|
| +
|
| + // And then launch the service process if it has not started yet.
|
| + // If we have already connected to the service process then submit the tokens
|
| + // to it to register the host.
|
| + process_control_ =
|
| + ServiceProcessControlManager::instance()->GetProcessControl(
|
| + browser_->profile(),
|
| + kServiceProcessCloudPrint);
|
| +
|
| +#if defined(OS_WIN)
|
| + // TODO(hclam): This call only works on Windows. I need to make it
|
| + // work on other platforms.
|
| + service_process_helper_ = new CloudPrintServiceProcessHelper(this);
|
| +
|
| + // If the process isn't connected, launch it now. This will run the
|
| + // task whether the process is already launched or not, as long as
|
| + // it's able to connect back up.
|
| + process_control_->Launch(
|
| + NewRunnableMethod(service_process_helper_.get(),
|
| + &CloudPrintServiceProcessHelper::OnProcessLaunched));
|
| +#else
|
| + ShowSetupDone();
|
| +#endif
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// Methods called by CloudPrintSetupMessageHandler
|
| +void CloudPrintSetupFlow::Attach(DOMUI* dom_ui) {
|
| + dom_ui_ = dom_ui;
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::OnUserSubmittedAuth(const std::string& user,
|
| + const std::string& password,
|
| + const std::string& captcha) {
|
| + // Save the login name only.
|
| + login_ = user;
|
| +
|
| + // Start the authenticator.
|
| + authenticator_.reset(
|
| + new GaiaAuthenticator2(this, GaiaConstants::kChromeSource,
|
| + browser_->profile()->GetRequestContext()));
|
| + authenticator_->StartClientLogin(user, password,
|
| + GaiaConstants::kCloudPrintService,
|
| + "", captcha);
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// Method called by CloudPrintServiceProcessHelper
|
| +void CloudPrintSetupFlow::OnProcessLaunched() {
|
| + DCHECK(process_control_->is_connected());
|
| + // TODO(scottbyer): Need to wait for an ACK to be sure that it is
|
| + // actually active.
|
| + if (!lsid_.empty())
|
| + process_control_->Send(new ServiceMsg_EnableCloudPrintProxy(lsid_));
|
| +
|
| + // Save the preference that we have completed the setup of cloud
|
| + // print.
|
| + browser_->profile()->GetPrefs()->SetString(prefs::kCloudPrintEmail, login_);
|
| + ShowSetupDone();
|
| +}
|
| +
|
| +///////////////////////////////////////////////////////////////////////////////
|
| +// Helper methods for showing contents of the DOM UI
|
| +void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) {
|
| + if (dom_ui_)
|
| + dom_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
|
| +
|
| + std::string json;
|
| + base::JSONWriter::Write(&args, false, &json);
|
| + std::wstring javascript = std::wstring(L"showGaiaLogin") +
|
| + L"(" + UTF8ToWide(json) + L");";
|
| + ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::ShowGaiaSuccessAndSettingUp() {
|
| + ExecuteJavascriptInIFrame(kLoginIFrameXPath,
|
| + L"showGaiaSuccessAndSettingUp();");
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::ShowGaiaFailed(const GoogleServiceAuthError& error) {
|
| + DictionaryValue args;
|
| + args.SetString("iframeToShow", "login");
|
| + args.SetString("user", "");
|
| + args.SetInteger("error", error.state());
|
| + args.SetBoolean("editable_user", true);
|
| + args.SetString("captchaUrl", error.captcha().image_url.spec());
|
| + ShowGaiaLogin(args);
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::ShowSetupDone() {
|
| + std::wstring javascript = L"setMessage('You are all set!');";
|
| + ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
|
| +
|
| + if (dom_ui_)
|
| + dom_ui_->CallJavascriptFunction(L"showSetupDone");
|
| +
|
| + ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();");
|
| +}
|
| +
|
| +void CloudPrintSetupFlow::ExecuteJavascriptInIFrame(
|
| + const std::wstring& iframe_xpath,
|
| + const std::wstring& js) {
|
| + if (dom_ui_) {
|
| + RenderViewHost* rvh = dom_ui_->tab_contents()->render_view_host();
|
| + rvh->ExecuteJavascriptInWebFrame(iframe_xpath, js);
|
| + }
|
| +}
|
|
|