New Cloud Print Proxy setup UI.

New UI to setup the proxy in Chrome.  This UI passed review.  New features
include a friendlier layout, a Learn More link, and a Print Test Page button on
the success page.  This does not yet bring the UI out from behind a flag; that
will be a separate CL.

BUG=60092
TEST=CloudPrintURLTest.CheckDefaultURLs

Review URL: http://codereview.chromium.org/5285001

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67602 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index c55248e..0c6aca7 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -5397,8 +5397,35 @@
       <message name="IDS_CLOUD_PRINT_SETUP_DIALOG_TITLE" desc="Title of the cloud print setup dialog.">
         Set up <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph>
       </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_HEADER" desc="Intro line of the cloud print setup dialog.">
+        Access and share your printers online with <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph>
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_EXPLAIN" desc="Explanation of the cloud print setup dialog.">
+        <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> is built on the idea that printing can be more intuitive, accessible, and useful. Using <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> you can make your printers available to you from any <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> enabled web or mobile app.
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_ANYWHERE_HEADER" desc="Intro line about printing from anywhere.">
+        Print from anywhere
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_ANYWHERE_EXPLAIN" desc="Explanation about printing from anywhere.">
+        Access your printers from any computer or smart phone. <ph name="BEGIN_LINK">&lt;a href="#" onclick="cloudprint.learnMore()"&gt;</ph>Learn more<ph name="END_LINK">&lt;/a&gt;</ph>
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_PRINTER_HEADER" desc="Intro line about printer management.">
+        Manage your printer
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_PRINTER_EXPLAIN" desc="Explanation about printer management.">
+        Review your print jobs and printer status online.
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_SHARING_HEADER" desc="Intro line about printer management.">
+        Shared access
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_SHARING_EXPLAIN" desc="Explanation about printer management.">
+        Share and control access to your printers with any Google account.
+      </message>
       <message name="IDS_CLOUD_PRINT_SETUP_DONE" desc="Message on completed set up of cloud print.">
-        You have successfully enabled <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph>!
+        You have successfully enabled <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph>!  <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> has registered the printers on this machine with &lt;b&gt;<ph name="EMAIL_ADDRESSES">$2<ex>[email protected]</ex></ph>&lt;/b&gt;.  You can now print to your printers from any <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> enabled web or mobile app!
+      </message>
+      <message name="IDS_CLOUD_PRINT_SETUP_TEST_PAGE" desc="Label on button for printing a test page.">
+        Print a Test Page
       </message>
 
       <!-- Print Preview -->
@@ -11162,7 +11189,7 @@
 
     <!-- Cloud Print Strings -->
     <message name="IDS_CLOUD_PRINT_TOKEN_EXPIRED_MESSAGE" desc="The message to display when the cloud print token has expired.">
-      The credentials used to share your printers have expired. Please click here to re-enter your username and password.
+      The credentials used to share your printers to  <ph name="CLOUD_PRINT_NAME">Google Cloud Print</ph> have expired. Please click here to re-enter your username and password.
     </message>
 
     </messages>
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd
index c7853c5a..9f79066 100644
--- a/chrome/app/resources/locale_settings.grd
+++ b/chrome/app/resources/locale_settings.grd
@@ -581,6 +581,34 @@
         https://www.google.com/accounts/IssuedAuthSubTokens?hl=[GRITLANGCODE]
       </message>
 
+      <!-- The width of the cloud print setup wizard / login dialog in -->
+      <!-- characters. -->
+      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_WIDTH_CHARS" 
+               use_name_for_id="true">
+        76
+      </message>
+
+      <!-- The height of the cloud print setup wizard / login dialog in -->
+      <!-- characters. -->
+      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_HEIGHT_LINES"
+               use_name_for_id="true">
+        15
+      </message>
+
+      <!-- The width of the cloud print setup wizard / login dialog in -->
+      <!-- characters when showing done. -->
+      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS" 
+               use_name_for_id="true">
+        46
+      </message>
+
+      <!-- The height of the cloud print setup wizard / login dialog in -->
+      <!-- characters when showing done. -->
+      <message name="IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES"
+               use_name_for_id="true">
+        15
+      </message>
+
       <!-- The default width/height for confirmation dialogs. -->
       <message name="IDS_CONFIRM_MESSAGE_BOX_DEFAULT_WIDTH_CHARS" use_name_for_id="true">
         50
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index b01358af..dc37ee2 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -64,6 +64,9 @@
       <include name="IDR_SYNC_SETUP_FLOW_HTML" file="sync\resources\setup_flow.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_REMOTING_SETUP_FLOW_HTML" file="remoting\resources\remoting_setup_flow.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_REMOTING_SETUP_DONE_HTML" file="remoting\resources\remoting_setup_done.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_CLOUD_PRINT_SETUP_FLOW_HTML" file="printing\cloud_print\resources\cloud_print_setup_flow.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_CLOUD_PRINT_SETUP_LOGIN_HTML" file="printing\cloud_print\resources\cloud_print_setup_login.html" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_CLOUD_PRINT_SETUP_DONE_HTML" file="printing\cloud_print\resources\cloud_print_setup_done.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_TEXTFIELDS_HTML" file="resources\textfields.html" flattenhtml="true" type="BINDATA" />
       <include name="IDR_TRANSLATE_JS" file="resources\translate.js" type="BINDATA" />
       <include name="IDR_BUGREPORT_HTML" file="resources\bug_report.html" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/dom_ui/dom_ui_factory.cc b/chrome/browser/dom_ui/dom_ui_factory.cc
index d27329e..414f41f 100644
--- a/chrome/browser/dom_ui/dom_ui_factory.cc
+++ b/chrome/browser/dom_ui/dom_ui_factory.cc
@@ -112,7 +112,8 @@
     return NULL;
 
   if (url.host() == chrome::kChromeUISyncResourcesHost ||
-      url.host() == chrome::kChromeUIRemotingResourcesHost)
+      url.host() == chrome::kChromeUIRemotingResourcesHost ||
+      url.host() == chrome::kCloudPrintSetupHost)
     return &NewDOMUI<HtmlDialogUI>;
 
   // Special case the new tab page. In older versions of Chrome, the new tab
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
index f4f2caf..79e32f4 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.cc
@@ -20,13 +20,15 @@
 #include "chrome/browser/prefs/pref_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
 #include "chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_setup_source.h"
+#include "chrome/browser/printing/cloud_print/cloud_print_url.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/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
 #if defined(TOOLKIT_VIEWS)
 #include "chrome/browser/views/browser_dialogs.h"
 #endif  // defined(TOOLKIT_GTK)
@@ -36,10 +38,12 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/common/service_messages.h"
 #include "gfx/font.h"
+
+#include "grit/chromium_strings.h"
 #include "grit/locale_settings.h"
 
-static const wchar_t kLoginIFrameXPath[] = L"//iframe[@id='login']";
-static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='done']";
+static const wchar_t kGaiaLoginIFrameXPath[] = L"//iframe[@id='gaialogin']";
+static const wchar_t kDoneIframeXPath[] = L"//iframe[@id='setupdone']";
 
 ////////////////////////////////////////////////////////////////////////////////
 // CloudPrintSetupFlow implementation.
@@ -49,21 +53,21 @@
     Profile* profile, Delegate* delegate, gfx::NativeWindow parent_window) {
   // 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);
 
+  bool setup_done = false;
   if (profile->GetPrefs()->HasPrefPath(prefs::kCloudPrintEmail) &&
-      !profile->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty()) {
-    args.SetString("iframeToShow", "done");
-  }
+      !profile->GetPrefs()->GetString(prefs::kCloudPrintEmail).empty())
+    setup_done = true;
+  args.SetString("pageToShow", setup_done ? "setupdone" : "cloudprintsetup");
 
   std::string json_args;
   base::JSONWriter::Write(&args, false, &json_args);
 
   CloudPrintSetupFlow* flow = new CloudPrintSetupFlow(json_args, profile,
-                                                      delegate);
+                                                      delegate, setup_done);
   // We may not always have a browser. This can happen when we are being
   // invoked in the context of a "token expired" notfication. If we don't have
   // a brower, use the underlying dialog system to show the dialog without
@@ -86,9 +90,11 @@
 
 CloudPrintSetupFlow::CloudPrintSetupFlow(const std::string& args,
                                          Profile* profile,
-                                         Delegate* delegate)
+                                         Delegate* delegate,
+                                         bool setup_done)
     : dom_ui_(NULL),
       dialog_start_args_(args),
+      setup_done_(setup_done),
       process_control_(NULL),
       delegate_(delegate) {
   // TODO(hclam): The data source should be added once.
@@ -97,7 +103,7 @@
       BrowserThread::IO, FROM_HERE,
       NewRunnableMethod(Singleton<ChromeURLDataManager>::get(),
                         &ChromeURLDataManager::AddDataSource,
-                        make_scoped_refptr(new RemotingResourcesSource())));
+                        make_scoped_refptr(new CloudPrintSetupSource())));
 }
 
 CloudPrintSetupFlow::~CloudPrintSetupFlow() {
@@ -111,7 +117,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 // HtmlDialogUIDelegate implementation.
 GURL CloudPrintSetupFlow::GetDialogContentURL() const {
-  return GURL("chrome://remotingresources/setup");
+  return GURL("chrome://cloudprintsetup/setupflow");
 }
 
 void CloudPrintSetupFlow::GetDOMMessageHandlers(
@@ -129,11 +135,17 @@
       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);
+  if (setup_done_) {
+    *size = gfx::GetLocalizedContentsSizeForFont(
+        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
+        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
+        approximate_web_font);
+  } else {
+    *size = gfx::GetLocalizedContentsSizeForFont(
+        IDS_CLOUD_PRINT_SETUP_WIZARD_WIDTH_CHARS,
+        IDS_CLOUD_PRINT_SETUP_WIZARD_HEIGHT_LINES,
+        approximate_web_font);
+  }
 }
 
 // A callback to notify the delegate that the dialog closed.
@@ -204,33 +216,46 @@
   authenticator_.reset(
       new GaiaAuthFetcher(this, GaiaConstants::kChromeSource,
                           profile_->GetRequestContext()));
+
   authenticator_->StartClientLogin(user, password,
                                    GaiaConstants::kCloudPrintService,
                                    "", captcha,
                                    GaiaAuthFetcher::HostedAccountsAllowed);
 }
 
+void CloudPrintSetupFlow::OnUserClickedLearnMore() {
+  dom_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintLearnMoreURL(),
+                                   GURL(), NEW_FOREGROUND_TAB,
+                                   PageTransition::LINK);
+}
+
+void CloudPrintSetupFlow::OnUserClickedPrintTestPage() {
+  dom_ui_->tab_contents()->OpenURL(CloudPrintURL::GetCloudPrintTestPageURL(),
+                                   GURL(), NEW_FOREGROUND_TAB,
+                                   PageTransition::LINK);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // Helper methods for showing contents of the DOM UI
 void CloudPrintSetupFlow::ShowGaiaLogin(const DictionaryValue& args) {
   if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showGaiaLoginIframe");
+    dom_ui_->CallJavascriptFunction(L"cloudprint.showSetupLogin");
 
   std::string json;
   base::JSONWriter::Write(&args, false, &json);
   std::wstring javascript = std::wstring(L"showGaiaLogin") +
       L"(" + UTF8ToWide(json) + L");";
-  ExecuteJavascriptInIFrame(kLoginIFrameXPath, javascript);
+  ExecuteJavascriptInIFrame(kGaiaLoginIFrameXPath, javascript);
 }
 
 void CloudPrintSetupFlow::ShowGaiaSuccessAndSettingUp() {
-  ExecuteJavascriptInIFrame(kLoginIFrameXPath,
+  ExecuteJavascriptInIFrame(kGaiaLoginIFrameXPath,
                             L"showGaiaSuccessAndSettingUp();");
 }
 
 void CloudPrintSetupFlow::ShowGaiaFailed(const GoogleServiceAuthError& error) {
   DictionaryValue args;
-  args.SetString("iframeToShow", "login");
+  args.SetString("pageToShow", "cloudprintsetup");
   args.SetString("user", "");
   args.SetInteger("error", error.state());
   args.SetBoolean("editable_user", true);
@@ -239,14 +264,31 @@
 }
 
 void CloudPrintSetupFlow::ShowSetupDone() {
-  std::wstring message = l10n_util::GetString(IDS_CLOUD_PRINT_SETUP_DONE);
-  std::wstring javascript = L"setMessage('" + message + L"');";
+  setup_done_ = true;
+  std::wstring product_name = l10n_util::GetString(IDS_PRODUCT_NAME);
+  std::wstring message = l10n_util::GetStringF(IDS_CLOUD_PRINT_SETUP_DONE,
+                                               product_name,
+                                               UTF8ToWide(login_));
+  std::wstring javascript = L"cloudprint.setMessage('" + message + L"');";
   ExecuteJavascriptInIFrame(kDoneIframeXPath, javascript);
 
-  if (dom_ui_)
-    dom_ui_->CallJavascriptFunction(L"showSetupDone");
+  if (dom_ui_) {
+    PrefService* prefs = profile_->GetPrefs();
+    gfx::Font approximate_web_font(
+        UTF8ToWide(prefs->GetString(prefs::kWebKitSansSerifFontFamily)),
+        prefs->GetInteger(prefs::kWebKitDefaultFontSize));
+    gfx::Size done_size = gfx::GetLocalizedContentsSizeForFont(
+        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_WIDTH_CHARS,
+        IDS_CLOUD_PRINT_SETUP_WIZARD_DONE_HEIGHT_LINES,
+        approximate_web_font);
 
-  ExecuteJavascriptInIFrame(kDoneIframeXPath, L"onPageShown();");
+    FundamentalValue new_width(done_size.width());
+    FundamentalValue new_height(done_size.height());
+    dom_ui_->CallJavascriptFunction(L"cloudprint.showSetupDone",
+                                    new_width, new_height);
+  }
+
+  ExecuteJavascriptInIFrame(kDoneIframeXPath, L"cloudprint.onPageShown();");
 }
 
 void CloudPrintSetupFlow::ExecuteJavascriptInIFrame(
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
index a5ccd979..14354e3 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_flow.h
@@ -84,7 +84,7 @@
 
   // Use static Run method to get an instance.
   CloudPrintSetupFlow(const std::string& args, Profile* profile,
-                      Delegate* delegate);
+                      Delegate* delegate, bool setup_done);
 
   // Called CloudPrintSetupMessageHandler when a DOM is attached. This method
   // is called when the HTML page is fully loaded. We then operate on this
@@ -97,6 +97,11 @@
                            const std::string& password,
                            const std::string& captcha);
 
+  // Called by CloudPrintSetupMessageHandler when the user clicks on various
+  // pieces of UI during setup.
+  void OnUserClickedLearnMore();
+  void OnUserClickedPrintTestPage();
+
   // The following methods control which iframe is visible.
   void ShowGaiaLogin(const DictionaryValue& args);
   void ShowGaiaSuccessAndSettingUp();
@@ -118,6 +123,9 @@
   std::string login_;
   std::string lsid_;
 
+  // Are we in the done state?
+  bool setup_done_;
+
   // Handle to the ServiceProcessControl which talks to the service process.
   ServiceProcessControl* process_control_;
   Delegate* delegate_;
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
index ece0e8e..0bbd25d2 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.cc
@@ -19,6 +19,10 @@
 void CloudPrintSetupMessageHandler::RegisterMessages() {
   dom_ui_->RegisterMessageCallback("SubmitAuth",
       NewCallback(this, &CloudPrintSetupMessageHandler::HandleSubmitAuth));
+  dom_ui_->RegisterMessageCallback("PrintTestPage",
+      NewCallback(this, &CloudPrintSetupMessageHandler::HandlePrintTestPage));
+  dom_ui_->RegisterMessageCallback("LearnMore",
+      NewCallback(this, &CloudPrintSetupMessageHandler::HandleLearnMore));
 }
 
 void CloudPrintSetupMessageHandler::HandleSubmitAuth(const ListValue* args) {
@@ -45,3 +49,13 @@
   if (flow_)
     flow_->OnUserSubmittedAuth(username, password, captcha);
 }
+
+void CloudPrintSetupMessageHandler::HandlePrintTestPage(const ListValue* args) {
+  if (flow_)
+    flow_->OnUserClickedPrintTestPage();
+}
+
+void CloudPrintSetupMessageHandler::HandleLearnMore(const ListValue* args) {
+  if (flow_)
+    flow_->OnUserClickedLearnMore();
+}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
index c59afb3..958f5373 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_message_handler.h
@@ -28,6 +28,8 @@
 
   // Callbacks from the page.
   void HandleSubmitAuth(const ListValue* args);
+  void HandlePrintTestPage(const ListValue* args);
+  void HandleLearnMore(const ListValue* args);
 
  private:
   CloudPrintSetupFlow* flow_;
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
new file mode 100644
index 0000000..62a9a3f
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_source.cc
@@ -0,0 +1,134 @@
+// 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_source.h"
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
+#include "base/message_loop.h"
+#include "base/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/jstemplate_builder.h"
+#include "googleurl/src/gurl.h"
+#include "grit/app_resources.h"
+#include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/locale_settings.h"
+
+// Define the values of standard URLs.
+const char CloudPrintSetupSource::kInvalidPasswordHelpUrl[] =
+  "http://www.google.com/support/accounts/bin/answer.py?ctx=ch&answer=27444";
+const char CloudPrintSetupSource::kCanNotAccessAccountUrl[] =
+  "http://www.google.com/support/accounts/bin/answer.py?answer=48598";
+const char CloudPrintSetupSource::kCreateNewAccountUrl[] =
+  "https://www.google.com/accounts/NewAccount?service=chromiumsync";
+
+namespace {
+
+// Utility method to keep dictionary population code streamlined.
+void AddString(DictionaryValue* dictionary,
+               const std::string& key,
+               int resource_id) {
+  dictionary->SetString(key, l10n_util::GetStringUTF16(resource_id));
+}
+
+}  // namespace
+
+CloudPrintSetupSource::CloudPrintSetupSource()
+  : DataSource(chrome::kCloudPrintSetupHost, MessageLoop::current()) {
+}
+
+void CloudPrintSetupSource::StartDataRequest(const std::string& path_raw,
+    bool is_off_the_record, int request_id) {
+  const char kCloudPrintSetupPath[] = "cloudprintsetup";
+  const char kCloudPrintGaiaLoginPath[] = "gaialogin";
+  const char kCloudPrintSetupFlowPath[] = "setupflow";
+  const char kCloudPrintSetupDonePath[] = "setupdone";
+
+  DictionaryValue localized_strings;
+  DictionaryValue* dict = &localized_strings;
+
+  std::string response;
+  if (path_raw == kCloudPrintSetupPath) {
+    AddString(dict, "header", IDS_CLOUD_PRINT_SETUP_HEADER);
+    AddString(dict, "explain", IDS_CLOUD_PRINT_SETUP_EXPLAIN);
+    AddString(dict, "anywhereheader", IDS_CLOUD_PRINT_SETUP_ANYWHERE_HEADER);
+    AddString(dict, "anywhereexplain", IDS_CLOUD_PRINT_SETUP_ANYWHERE_EXPLAIN);
+    AddString(dict, "printerheader", IDS_CLOUD_PRINT_SETUP_PRINTER_HEADER);
+    AddString(dict, "printerexplain", IDS_CLOUD_PRINT_SETUP_PRINTER_EXPLAIN);
+    AddString(dict, "sharingheader", IDS_CLOUD_PRINT_SETUP_SHARING_HEADER);
+    AddString(dict, "sharingexplain", IDS_CLOUD_PRINT_SETUP_SHARING_EXPLAIN);
+
+    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
+        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_LOGIN_HTML));
+    SetFontAndTextDirection(dict);
+    response = jstemplate_builder::GetI18nTemplateHtml(html, dict);
+  } else if (path_raw == kCloudPrintGaiaLoginPath) {
+    // Start by setting the per-locale URLs we show on the setup wizard.
+    dict->SetString("invalidpasswordhelpurl",
+                   GetLocalizedUrl(kInvalidPasswordHelpUrl));
+    dict->SetString("cannotaccessaccounturl",
+                   GetLocalizedUrl(kCanNotAccessAccountUrl));
+    dict->SetString("createnewaccounturl",
+                   GetLocalizedUrl(kCreateNewAccountUrl));
+
+    // None of the strings used here currently have sync-specific wording in
+    // them.  There is a unit test to catch if that happens.
+    dict->SetString("introduction", "");
+    AddString(dict, "signinprefix", IDS_SYNC_LOGIN_SIGNIN_PREFIX);
+    AddString(dict, "signinsuffix", IDS_SYNC_LOGIN_SIGNIN_SUFFIX);
+    AddString(dict, "cannotbeblank", IDS_SYNC_CANNOT_BE_BLANK);
+    AddString(dict, "emaillabel", IDS_SYNC_LOGIN_EMAIL);
+    AddString(dict, "passwordlabel", IDS_SYNC_LOGIN_PASSWORD);
+    AddString(dict, "invalidcredentials", IDS_SYNC_INVALID_USER_CREDENTIALS);
+    AddString(dict, "signin", IDS_SYNC_SIGNIN);
+    AddString(dict, "couldnotconnect", IDS_SYNC_LOGIN_COULD_NOT_CONNECT);
+    AddString(dict, "cannotaccessaccount", IDS_SYNC_CANNOT_ACCESS_ACCOUNT);
+    AddString(dict, "createaccount", IDS_SYNC_CREATE_ACCOUNT);
+    AddString(dict, "cancel", IDS_CANCEL);
+    AddString(dict, "settingup", IDS_SYNC_LOGIN_SETTING_UP);
+    AddString(dict, "success", IDS_SYNC_SUCCESS);
+    AddString(dict, "errorsigningin", IDS_SYNC_ERROR_SIGNING_IN);
+    AddString(dict, "captchainstructions", IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS);
+    AddString(dict, "invalidaccesscode", IDS_SYNC_INVALID_ACCESS_CODE_LABEL);
+    AddString(dict, "enteraccesscode", IDS_SYNC_ENTER_ACCESS_CODE_LABEL);
+    AddString(dict, "getaccesscodehelp", IDS_SYNC_ACCESS_CODE_HELP_LABEL);
+    AddString(dict, "getaccesscodeurl", IDS_SYNC_GET_ACCESS_CODE_URL);
+
+    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
+        .GetRawDataResource(IDR_GAIA_LOGIN_HTML));
+    SetFontAndTextDirection(dict);
+    response = jstemplate_builder::GetI18nTemplateHtml(html, dict);
+  } else if (path_raw == kCloudPrintSetupDonePath) {
+    AddString(dict, "testpage", IDS_CLOUD_PRINT_SETUP_TEST_PAGE);
+    AddString(dict, "success", IDS_SYNC_SUCCESS);
+    AddString(dict, "okay", IDS_SYNC_SETUP_OK_BUTTON_LABEL);
+    static const base::StringPiece html(ResourceBundle::GetSharedInstance()
+        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_DONE_HTML));
+    SetFontAndTextDirection(dict);
+    response = jstemplate_builder::GetI18nTemplateHtml(html, dict);
+  } else if (path_raw == kCloudPrintSetupFlowPath) {
+    static const base::StringPiece html(
+        ResourceBundle::GetSharedInstance()
+        .GetRawDataResource(IDR_CLOUD_PRINT_SETUP_FLOW_HTML));
+    response = html.as_string();
+  }
+  // Send the response.
+  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);
+}
+
+std::string CloudPrintSetupSource::GetLocalizedUrl(
+    const std::string& url) const {
+  GURL original_url(url);
+  DCHECK(original_url.is_valid());
+  GURL localized_url = google_util::AppendGoogleLocaleParam(original_url);
+  return localized_url.spec();
+}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source.h b/chrome/browser/printing/cloud_print/cloud_print_setup_source.h
new file mode 100644
index 0000000..3fa3048
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_source.h
@@ -0,0 +1,40 @@
+// 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.
+
+#ifndef CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
+#define CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
+
+#include <string>
+
+#include "base/message_loop.h"
+#include "chrome/browser/dom_ui/chrome_url_data_manager.h"
+#include "chrome/common/url_constants.h"
+
+class CloudPrintSetupSource : public ChromeURLDataManager::DataSource {
+ public:
+  CloudPrintSetupSource();
+  virtual void StartDataRequest(const std::string& path,
+                                bool is_off_the_record,
+                                int request_id);
+
+  virtual std::string GetMimeType(const std::string& path) const {
+    return "text/html";
+  }
+
+  static const char kInvalidPasswordHelpUrl[];
+  static const char kCanNotAccessAccountUrl[];
+  static const char kCreateNewAccountUrl[];
+
+ private:
+  virtual ~CloudPrintSetupSource() {}
+
+  // Takes a string containing an URL and returns an URL containing a CGI
+  // parameter of the form "&hl=xy" where 'xy' is the language code of the
+  // current locale.
+  std::string GetLocalizedUrl(const std::string& url) const;
+
+  DISALLOW_COPY_AND_ASSIGN(CloudPrintSetupSource);
+};
+
+#endif  // CHROME_BROWSER_PRINTING_CLOUD_PRINT_CLOUD_PRINT_SETUP_SOURCE_H_
diff --git a/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc b/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
new file mode 100644
index 0000000..10dcd8ab
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/cloud_print_setup_source_unittest.cc
@@ -0,0 +1,47 @@
+// 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 "app/l10n_util.h"

+#include "grit/app_resources.h"

+#include "grit/browser_resources.h"

+#include "grit/chromium_strings.h"

+#include "grit/generated_resources.h"

+#include "grit/locale_settings.h"

+#include "testing/gtest/include/gtest/gtest.h"

+#include "testing/gmock/include/gmock/gmock.h"

+

+using testing::HasSubstr;

+using testing::Not;

+

+void TestStringStillOkForCloudPrint(int resource_id) {

+  std::string resource_string = l10n_util::GetStringUTF8(resource_id);

+  EXPECT_THAT(resource_string, Not(HasSubstr("Sync")));

+  EXPECT_THAT(resource_string, Not(HasSubstr("sync")));

+}

+

+// This set of strings to test was generated from

+// CloudPrintSetupSource::StartDataRequest.  If any of these trip, notify the

+// cloud printing team and we'll split the strings.

+TEST(CloudPrintResources, SharedStringsCheck) {

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_PREFIX);

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SIGNIN_SUFFIX);

+  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_BE_BLANK);

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_EMAIL);

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_PASSWORD);

+  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_USER_CREDENTIALS);

+  TestStringStillOkForCloudPrint(IDS_SYNC_SIGNIN);

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_COULD_NOT_CONNECT);

+  TestStringStillOkForCloudPrint(IDS_SYNC_CANNOT_ACCESS_ACCOUNT);

+  TestStringStillOkForCloudPrint(IDS_SYNC_CREATE_ACCOUNT);

+  TestStringStillOkForCloudPrint(IDS_SYNC_LOGIN_SETTING_UP);

+  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);

+  TestStringStillOkForCloudPrint(IDS_SYNC_ERROR_SIGNING_IN);

+  TestStringStillOkForCloudPrint(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS);

+  TestStringStillOkForCloudPrint(IDS_SYNC_INVALID_ACCESS_CODE_LABEL);

+  TestStringStillOkForCloudPrint(IDS_SYNC_ENTER_ACCESS_CODE_LABEL);

+  TestStringStillOkForCloudPrint(IDS_SYNC_ACCESS_CODE_HELP_LABEL);

+  TestStringStillOkForCloudPrint(IDS_SYNC_GET_ACCESS_CODE_URL);

+  TestStringStillOkForCloudPrint(IDS_SYNC_SUCCESS);

+  TestStringStillOkForCloudPrint(IDS_SYNC_SETUP_OK_BUTTON_LABEL);

+}

diff --git a/chrome/browser/printing/cloud_print/cloud_print_url.cc b/chrome/browser/printing/cloud_print/cloud_print_url.cc
index 5ce98550..1001f5f 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_url.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_url.cc
@@ -13,6 +13,10 @@
 #include "googleurl/src/gurl.h"
 
 const char kDefaultCloudPrintServiceURL[] = "https://www.google.com/cloudprint";
+const char kLearnMoreURL[] =
+    "http://www.google.com/support/cloudprint";
+const char kTestPageURL[] =
+    "http://www.google.com/landing/cloudprint/enable.html?print=true";
 
 void CloudPrintURL::RegisterPreferences() {
   DCHECK(profile_);
@@ -59,3 +63,13 @@
       replacements);
   return cloud_print_manage_url;
 }
+
+GURL CloudPrintURL::GetCloudPrintLearnMoreURL() {
+  GURL cloud_print_learn_more_url(kLearnMoreURL);
+  return cloud_print_learn_more_url;
+}
+
+GURL CloudPrintURL::GetCloudPrintTestPageURL() {
+  GURL cloud_print_learn_more_url(kTestPageURL);
+  return cloud_print_learn_more_url;
+}
diff --git a/chrome/browser/printing/cloud_print/cloud_print_url.h b/chrome/browser/printing/cloud_print/cloud_print_url.h
index 157951b..55780b2 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_url.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_url.h
@@ -18,6 +18,11 @@
   GURL GetCloudPrintServiceDialogURL();
   GURL GetCloudPrintServiceManageURL();
 
+  // These aren't derived from the service, but it makes sense to keep all the
+  // URLs together, and this gives the unit tests access for testing.
+  static GURL GetCloudPrintLearnMoreURL();
+  static GURL GetCloudPrintTestPageURL();
+
  private:
   void RegisterPreferences();
 
diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.css b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.css
new file mode 100644
index 0000000..6f7b0834
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.css
@@ -0,0 +1,44 @@
+body {

+  background: #FFFFFF;

+  margin: 10px 15px;

+  -webkit-user-select: none;

+}

+

+.cloudprint-success-header {

+  font-size: 1.4em;

+  font-weight: bold;

+}

+

+.cloudprint-success-image {

+  text-align: center;

+  margin: 20px;

+}

+

+#message {

+  font-weight: bold;

+}

+

+.cloudprint-success-footer {

+  position: fixed;

+  font-size: 1.2em;

+  right: 0px;

+  bottom: 0px;

+  margin-right: 10px;

+  margin-bottom: 10px;

+}

+

+html[dir='rtl'] .cloudprint-success-footer {

+  text-align: left;

+  left: 0px;

+  bottom: 0px;

+  margin-left: 20px;

+}

+

+.button {

+  min-width: 87px;

+  min-height: 26px;

+}

+

+html[os='mac'].button {

+  font-size: 12pt;

+}

diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.html b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.html
new file mode 100644
index 0000000..f692552
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<title></title>
+<link rel="stylesheet" type="text/css" href="cloud_print_setup_done.css" />
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script type="text/javascript" src="cloud_print_setup_done.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize">
+  <div class="cloudprint-success-header" i18n-content="success"></div>
+  <div class="cloudprint-success-image">
+    <img src="../../../sync/resources/success-large.png" />
+  </div>
+  <div id="msgContent"></div>
+  <div class="cloudprint-success-footer">
+    <input type="button" class="button" id="testpage"
+           i18n-values="value:testpage" value="Test"
+           onclick="cloudprint.printTestPage()" />
+    <input type="submit" class="button" id="close" i18n-values="value:okay"
+           onclick="chrome.send('DialogClose', [''])" />
+  </div>
+</body>
+</html>
diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.js b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.js
new file mode 100644
index 0000000..2a47a9c
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_done.js
@@ -0,0 +1,24 @@
+// 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.

+

+cr.define('cloudprint', function() {

+  function printTestPage() {

+    chrome.send('PrintTestPage', ['']);

+    chrome.send('DialogClose', ['']);

+  }

+

+  function setMessage(msg) {

+    $('msgContent').innerHTML = msg;

+  }

+

+  function onPageShown() {

+    $('close').focus();

+  }

+

+  return {

+    printTestPage: printTestPage,

+    setMessage: setMessage,

+    onPageShown: onPageShown

+  };

+});

diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.html b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.html
new file mode 100644
index 0000000..be8a657
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<title></title>
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script type="text/javascript" src="cloud_print_setup_flow.js"></script>
+</head>
+<body style="margin:0; border:0;" onload="cloudprint.showInitialPage();">
+  <iframe id="cloudprintsetup"
+          src="chrome://cloudprintsetup/cloudprintsetup"
+          frameborder="0" width="100%" scrolling="no" height="100%"
+          style="display:none" tabindex="-1"></iframe>
+  <iframe id="setupdone"
+          src="chrome://cloudprintsetup/setupdone"
+          frameborder="0" width="100%" scrolling="no" height="100%"
+          style="display:none" tabindex="-1"></iframe>
+</body>
+</html>
diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.js b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.js
new file mode 100644
index 0000000..be73e387
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_flow.js
@@ -0,0 +1,47 @@
+// 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.

+

+cr.define('cloudprint', function () {

+  function hideAllPages() {

+    var pages = ['cloudprintsetup', 'setupdone'];

+    for (var i = 0; i < pages.length; ++i) {

+      $(pages[i]).style.display = 'none';

+      $(pages[i]).tabIndex = -1;

+    }

+  }

+

+  function showPage(page) {

+    hideAllPages();

+    $(page).style.display = 'block';

+    $(page).tabIndex = 0;

+  }

+

+  function showInitialPage() {

+    var args = JSON.parse(chrome.dialogArguments);

+    showPage(args.pageToShow);

+  }

+

+  function showSetupLogin() {

+    showPage('cloudprintsetup');

+  }

+

+  function showSetupDone(width, height) {

+    hideAllPages();

+    var moveByX = (window.innerWidth - width) / 2;

+    var moveByY = (window.innerHeight - height) / 2;

+    var sizeByX = width - window.innerWidth;

+    var sizeByY = height - window.innerHeight;

+    window.moveBy(moveByX, moveByY);

+    window.resizeBy(sizeByX, sizeByY);

+    showPage('setupdone');

+  }

+

+  return {

+    hideAllPages: hideAllPages,

+    showPage: showPage,

+    showInitialPage: showInitialPage,

+    showSetupLogin: showSetupLogin,

+    showSetupDone: showSetupDone

+  };

+});

diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.css b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.css
new file mode 100644
index 0000000..a456f3f
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.css
@@ -0,0 +1,31 @@
+body {

+  background: #FFFFFF;

+  margin: 10px 15px;

+  -webkit-user-select: none;

+}

+

+.cloudprint-signup {

+  width: 60%;

+}

+

+.cloudprint-login {

+  width: 40%;

+}

+

+.cloudprint-header {

+  font-weight: bold;

+}

+

+.cloudprint-item-header {

+  font-size: 0.9em;

+  font-weight: bold;

+}

+

+.cloudprint-item-explain {

+  font-size: 0.9em;

+}

+

+.cloudprint-item-image {

+  text-align: center;

+  padding: 8px;

+}

diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.html b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.html
new file mode 100644
index 0000000..8ef37f8
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html i18n-values="dir:textdirection;">
+<head>
+<title></title>
+<link rel="stylesheet" type="text/css" href="cloud_print_setup_login.css" />
+<script src="chrome://resources/js/cr.js"></script>
+<script src="chrome://resources/js/util.js"></script>
+<script type="text/javascript" src="cloud_print_setup_login.js"></script>
+</head>
+<body i18n-values=".style.fontFamily:fontfamily;.style.fontSize:fontsize"
+      onload="cloudprint.fixUpTemplateLink();">
+  <table class="cloudprint-contents">
+    <tbody>
+      <tr>
+        <td class="cloudprint-signup">
+          <table class="cloudprint-intro">
+            <tbody>
+              <tr><td><div class="cloudprint-header" id="header"
+                           i18n-content="header"></div></td></tr>
+              <tr><td><div class="cloudprint-explain" id="explain"
+                           i18n-content="explain"></div></td></tr>
+            </tbody>
+          </table>
+          <table class="cloudprint-body">
+            <tbody>
+              <tr>
+                <td class="cloudprint-item-image">
+                  <img src="cell_phone.png" /></td>
+                <td>
+                  <div class="cloudprint-item-header" id="anywhere-header"
+                       i18n-content="anywhereheader"></div>
+                  <div class="cloudprint-item-explain" id="anywhere-explain"
+                       i18n-content="anywhereexplain"></div></td>
+              </tr>
+              <tr>
+                <td class="cloudprint-item-image">
+                  <img src="cloud_printer.png" /></td>
+                <td>
+                  <div class="cloudprint-item-header" id="printer-header"
+                       i18n-content="printerheader"></div>
+                  <div class="cloudprint-item-explain" id="printer-explain"
+                       i18n-content="printerexplain"></div></td>
+              </tr>
+              <tr>
+                <td class="cloudprint-item-image">
+                  <img src="sharing.png" /></td>
+                <td>
+                  <div class="cloudprint-item-header" id="sharing-header"
+                       i18n-content="sharingheader"></div>
+                  <div class="cloudprint-item-explain" id="sharing-explain"
+                       i18n-content="sharingexplain"></div></td>
+              </tr>
+            </tbody>
+          </table>
+        </td>
+        <td class="cloudprint-login">
+          <iframe id="gaialogin" frameborder="0"
+                  width="100%" scrolling="no" height="100%"
+                  src="chrome://cloudprintsetup/gaialogin"></iframe>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+</body>
+</html>
diff --git a/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.js b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.js
new file mode 100644
index 0000000..095df514
--- /dev/null
+++ b/chrome/browser/printing/cloud_print/resources/cloud_print_setup_login.js
@@ -0,0 +1,23 @@
+// 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.

+

+cr.define('cloudprint', function() {

+  function learnMore() {

+    chrome.send('LearnMore', ['']);

+    chrome.send('DialogClose', ['']);

+  }

+

+  function fixUpTemplateLink() {

+    var elm = $('anywhere-explain');

+    if (elm)

+      elm.innerHTML = elm.textContent;

+  }

+

+  return {

+    learnMore: learnMore,

+    fixUpTemplateLink: fixUpTemplateLink

+  };

+});

+

+

diff --git a/chrome/browser/printing/print_dialog_cloud_unittest.cc b/chrome/browser/printing/print_dialog_cloud_unittest.cc
index da516569..ef9fe33 100644
--- a/chrome/browser/printing/print_dialog_cloud_unittest.cc
+++ b/chrome/browser/printing/print_dialog_cloud_unittest.cc
@@ -186,6 +186,22 @@
   EXPECT_THAT(manage_url, Not(HasSubstr("/client/")));
   EXPECT_THAT(manage_url, Not(HasSubstr("cloudprint/cloudprint")));
   EXPECT_THAT(manage_url, HasSubstr("/manage"));
+
+  GURL learn_more_url = CloudPrintURL::GetCloudPrintLearnMoreURL();
+  std::string learn_more_path = learn_more_url.spec();
+  EXPECT_THAT(learn_more_path, HasSubstr("www.google.com"));
+  EXPECT_THAT(learn_more_path, HasSubstr("/support/"));
+  EXPECT_THAT(learn_more_path, HasSubstr("/cloudprint"));
+  EXPECT_TRUE(learn_more_url.has_path());
+  EXPECT_FALSE(learn_more_url.has_query());
+
+  GURL test_page_url = CloudPrintURL::GetCloudPrintTestPageURL();
+  std::string test_page_path = test_page_url.spec();
+  EXPECT_THAT(test_page_path, HasSubstr("www.google.com"));
+  EXPECT_THAT(test_page_path, HasSubstr("/landing/"));
+  EXPECT_THAT(test_page_path, HasSubstr("/cloudprint/"));
+  EXPECT_TRUE(test_page_url.has_path());
+  EXPECT_TRUE(test_page_url.has_query());
 }
 
 // Testing for CloudPrintDataSender needs a mock DOMUI.
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index f57fcf4..8b400501 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2512,6 +2512,8 @@
         'browser/printing/cloud_print/cloud_print_setup_flow.h',
         'browser/printing/cloud_print/cloud_print_setup_message_handler.cc',
         'browser/printing/cloud_print/cloud_print_setup_message_handler.h',
+        'browser/printing/cloud_print/cloud_print_setup_source.cc',
+        'browser/printing/cloud_print/cloud_print_setup_source.h',
         'browser/printing/cloud_print/cloud_print_url.cc',
         'browser/printing/cloud_print/cloud_print_url.h',
         'browser/process_info_snapshot_mac.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 2f5e57aa..bb6f463 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1436,6 +1436,7 @@
         'browser/prefs/pref_set_observer_unittest.cc',
         'browser/prefs/pref_value_store_unittest.cc',
         'browser/prefs/session_startup_pref_unittest.cc',
+        'browser/printing/cloud_print/cloud_print_setup_source_unittest.cc',
         'browser/printing/print_dialog_cloud_unittest.cc',
         'browser/printing/print_job_unittest.cc',
         'browser/printing/print_preview_tab_controller_unittest.cc',
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 0345d6d..6a1c6a2 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -153,6 +153,7 @@
 
 const char kCloudPrintResourcesURL[] = "chrome://cloudprintresources/";
 const char kCloudPrintResourcesHost[] = "cloudprintresources";
+const char kCloudPrintSetupHost[] = "cloudprintsetup";
 
 const char kNetworkViewInternalsURL[] = "chrome://net-internals/";
 const char kNetworkViewCacheURL[] = "chrome://view-http-cache/";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index e617178d..1980b6e 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -148,6 +148,7 @@
 // Cloud Print dialog URL components.
 extern const char kCloudPrintResourcesURL[];
 extern const char kCloudPrintResourcesHost[];
+extern const char kCloudPrintSetupHost[];
 
 // Network related URLs.
 extern const char kNetworkViewCacheURL[];