• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/printing/print_dialog_cloud.h"
6 #include "chrome/browser/printing/print_dialog_cloud_internal.h"
7 
8 #include "base/base64.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/json/json_reader.h"
12 #include "base/values.h"
13 #include "chrome/browser/debugger/devtools_manager.h"
14 #include "chrome/browser/prefs/pref_service.h"
15 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/ui/browser_dialogs.h"
19 #include "chrome/browser/ui/browser_list.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/print_messages.h"
23 #include "chrome/common/url_constants.h"
24 #include "content/browser/browser_thread.h"
25 #include "content/browser/renderer_host/render_view_host.h"
26 #include "content/browser/tab_contents/tab_contents.h"
27 #include "content/browser/tab_contents/tab_contents_view.h"
28 #include "content/browser/webui/web_ui.h"
29 #include "content/common/notification_registrar.h"
30 #include "content/common/notification_source.h"
31 #include "content/common/notification_type.h"
32 #include "ui/base/l10n/l10n_util.h"
33 #include "webkit/glue/webpreferences.h"
34 
35 #include "grit/generated_resources.h"
36 
37 // This module implements the UI support in Chrome for cloud printing.
38 // This means hosting a dialog containing HTML/JavaScript and using
39 // the published cloud print user interface integration APIs to get
40 // page setup settings from the dialog contents and provide the
41 // generated print data to the dialog contents for uploading to the
42 // cloud print service.
43 
44 // Currently, the flow between these classes is as follows:
45 
46 // PrintDialogCloud::CreatePrintDialogForFile is called from
47 // resource_message_filter_gtk.cc once the renderer has informed the
48 // renderer host that print data generation into the renderer host provided
49 // temp file has been completed.  That call is on the FILE thread.
50 // That, in turn, hops over to the UI thread to create an instance of
51 // PrintDialogCloud.
52 
53 // The constructor for PrintDialogCloud creates a
54 // CloudPrintHtmlDialogDelegate and asks the current active browser to
55 // show an HTML dialog using that class as the delegate. That class
56 // hands in the kCloudPrintResourcesURL as the URL to visit.  That is
57 // recognized by the GetWebUIFactoryFunction as a signal to create an
58 // ExternalHtmlDialogUI.
59 
60 // CloudPrintHtmlDialogDelegate also temporarily owns a
61 // CloudPrintFlowHandler, a class which is responsible for the actual
62 // interactions with the dialog contents, including handing in the
63 // print data and getting any page setup parameters that the dialog
64 // contents provides.  As part of bringing up the dialog,
65 // HtmlDialogUI::RenderViewCreated is called (an override of
66 // WebUI::RenderViewCreated).  That routine, in turn, calls the
67 // delegate's GetWebUIMessageHandlers routine, at which point the
68 // ownership of the CloudPrintFlowHandler is handed over.  A pointer
69 // to the flow handler is kept to facilitate communication back and
70 // forth between the two classes.
71 
72 // The WebUI continues dialog bring-up, calling
73 // CloudPrintFlowHandler::RegisterMessages.  This is where the
74 // additional object model capabilities are registered for the dialog
75 // contents to use.  It is also at this time that capabilities for the
76 // dialog contents are adjusted to allow the dialog contents to close
77 // the window.  In addition, the pending URL is redirected to the
78 // actual cloud print service URL.  The flow controller also registers
79 // for notification of when the dialog contents finish loading, which
80 // is currently used to send the data to the dialog contents.
81 
82 // In order to send the data to the dialog contents, the flow
83 // handler uses a CloudPrintDataSender.  It creates one, letting it
84 // know the name of the temporary file containing the data, and
85 // posts the task of reading the file
86 // (CloudPrintDataSender::ReadPrintDataFile) to the file thread.  That
87 // routine reads in the file, and then hops over to the IO thread to
88 // send that data to the dialog contents.
89 
90 // When the dialog contents are finished (by either being cancelled or
91 // hitting the print button), the delegate is notified, and responds
92 // that the dialog should be closed, at which point things are torn
93 // down and released.
94 
95 // TODO(scottbyer):
96 // http://code.google.com/p/chromium/issues/detail?id=44093 The
97 // high-level flow (where the data is generated before even
98 // bringing up the dialog) isn't what we want.
99 
100 namespace internal_cloud_print_helpers {
101 
GetDoubleOrInt(const DictionaryValue & dictionary,const std::string & path,double * out_value)102 bool GetDoubleOrInt(const DictionaryValue& dictionary,
103                     const std::string& path,
104                     double* out_value) {
105   if (!dictionary.GetDouble(path, out_value)) {
106     int int_value = 0;
107     if (!dictionary.GetInteger(path, &int_value))
108       return false;
109     *out_value = int_value;
110   }
111   return true;
112 }
113 
114 // From the JSON parsed value, get the entries for the page setup
115 // parameters.
GetPageSetupParameters(const std::string & json,PrintMsg_Print_Params & parameters)116 bool GetPageSetupParameters(const std::string& json,
117                             PrintMsg_Print_Params& parameters) {
118   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
119   DLOG_IF(ERROR, (!parsed_value.get() ||
120                   !parsed_value->IsType(Value::TYPE_DICTIONARY)))
121       << "PageSetup call didn't have expected contents";
122   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
123     return false;
124 
125   bool result = true;
126   DictionaryValue* params = static_cast<DictionaryValue*>(parsed_value.get());
127   result &= GetDoubleOrInt(*params, "dpi", &parameters.dpi);
128   result &= GetDoubleOrInt(*params, "min_shrink", &parameters.min_shrink);
129   result &= GetDoubleOrInt(*params, "max_shrink", &parameters.max_shrink);
130   result &= params->GetBoolean("selection_only", &parameters.selection_only);
131   return result;
132 }
133 
CallJavascriptFunction(const std::wstring & function_name)134 void CloudPrintDataSenderHelper::CallJavascriptFunction(
135     const std::wstring& function_name) {
136   web_ui_->CallJavascriptFunction(WideToASCII(function_name));
137 }
138 
CallJavascriptFunction(const std::wstring & function_name,const Value & arg)139 void CloudPrintDataSenderHelper::CallJavascriptFunction(
140     const std::wstring& function_name, const Value& arg) {
141   web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg);
142 }
143 
CallJavascriptFunction(const std::wstring & function_name,const Value & arg1,const Value & arg2)144 void CloudPrintDataSenderHelper::CallJavascriptFunction(
145     const std::wstring& function_name, const Value& arg1, const Value& arg2) {
146   web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg1, arg2);
147 }
148 
149 // Clears out the pointer we're using to communicate.  Either routine is
150 // potentially expensive enough that stopping whatever is in progress
151 // is worth it.
CancelPrintDataFile()152 void CloudPrintDataSender::CancelPrintDataFile() {
153   base::AutoLock lock(lock_);
154   // We don't own helper, it was passed in to us, so no need to
155   // delete, just let it go.
156   helper_ = NULL;
157 }
158 
CloudPrintDataSender(CloudPrintDataSenderHelper * helper,const string16 & print_job_title,const std::string & file_type)159 CloudPrintDataSender::CloudPrintDataSender(CloudPrintDataSenderHelper* helper,
160                                            const string16& print_job_title,
161                                            const std::string& file_type)
162     : helper_(helper),
163       print_job_title_(print_job_title),
164       file_type_(file_type) {
165 }
166 
~CloudPrintDataSender()167 CloudPrintDataSender::~CloudPrintDataSender() {}
168 
169 // Grab the raw file contents and massage them into shape for
170 // sending to the dialog contents (and up to the cloud print server)
171 // by encoding it and prefixing it with the appropriate mime type.
172 // Once that is done, kick off the next part of the task on the IO
173 // thread.
ReadPrintDataFile(const FilePath & path_to_file)174 void CloudPrintDataSender::ReadPrintDataFile(const FilePath& path_to_file) {
175   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
176   int64 file_size = 0;
177   if (file_util::GetFileSize(path_to_file, &file_size) && file_size != 0) {
178     std::string file_data;
179     if (file_size < kuint32max) {
180       file_data.reserve(static_cast<unsigned int>(file_size));
181     } else {
182       DLOG(WARNING) << " print data file too large to reserve space";
183     }
184     if (helper_ && file_util::ReadFileToString(path_to_file, &file_data)) {
185       std::string base64_data;
186       base::Base64Encode(file_data, &base64_data);
187       std::string header("data:");
188       header.append(file_type_);
189       header.append(";base64,");
190       base64_data.insert(0, header);
191       scoped_ptr<StringValue> new_data(new StringValue(base64_data));
192       print_data_.swap(new_data);
193       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
194                               NewRunnableMethod(
195                                   this,
196                                   &CloudPrintDataSender::SendPrintDataFile));
197     }
198   }
199 }
200 
201 // We have the data in hand that needs to be pushed into the dialog
202 // contents; do so from the IO thread.
203 
204 // TODO(scottbyer): If the print data ends up being larger than the
205 // upload limit (currently 10MB), what we need to do is upload that
206 // large data to google docs and set the URL in the printing
207 // JavaScript to that location, and make sure it gets deleted when not
208 // needed. - 4/1/2010
SendPrintDataFile()209 void CloudPrintDataSender::SendPrintDataFile() {
210   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
211   base::AutoLock lock(lock_);
212   if (helper_ && print_data_.get()) {
213     StringValue title(print_job_title_);
214 
215     // Send the print data to the dialog contents.  The JavaScript
216     // function is a preliminary API for prototyping purposes and is
217     // subject to change.
218     const_cast<CloudPrintDataSenderHelper*>(helper_)->CallJavascriptFunction(
219         L"printApp._printDataUrl", *print_data_, title);
220   }
221 }
222 
223 
CloudPrintFlowHandler(const FilePath & path_to_file,const string16 & print_job_title,const std::string & file_type)224 CloudPrintFlowHandler::CloudPrintFlowHandler(const FilePath& path_to_file,
225                                              const string16& print_job_title,
226                                              const std::string& file_type)
227     : path_to_file_(path_to_file),
228       print_job_title_(print_job_title),
229       file_type_(file_type) {
230 }
231 
~CloudPrintFlowHandler()232 CloudPrintFlowHandler::~CloudPrintFlowHandler() {
233   // This will also cancel any task in flight.
234   CancelAnyRunningTask();
235 }
236 
237 
SetDialogDelegate(CloudPrintHtmlDialogDelegate * delegate)238 void CloudPrintFlowHandler::SetDialogDelegate(
239     CloudPrintHtmlDialogDelegate* delegate) {
240   // Even if setting a new WebUI, it means any previous task needs
241   // to be cancelled, it's now invalid.
242   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
243   CancelAnyRunningTask();
244   dialog_delegate_ = delegate;
245 }
246 
247 // Cancels any print data sender we have in flight and removes our
248 // reference to it, so when the task that is calling it finishes and
249 // removes it's reference, it goes away.
CancelAnyRunningTask()250 void CloudPrintFlowHandler::CancelAnyRunningTask() {
251   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
252   if (print_data_sender_.get()) {
253     print_data_sender_->CancelPrintDataFile();
254     print_data_sender_ = NULL;
255   }
256 }
257 
RegisterMessages()258 void CloudPrintFlowHandler::RegisterMessages() {
259   if (!web_ui_)
260     return;
261 
262   // TODO(scottbyer) - This is where we will register messages for the
263   // UI JS to use.  Needed: Call to update page setup parameters.
264   web_ui_->RegisterMessageCallback(
265       "ShowDebugger",
266       NewCallback(this, &CloudPrintFlowHandler::HandleShowDebugger));
267   web_ui_->RegisterMessageCallback(
268       "SendPrintData",
269       NewCallback(this, &CloudPrintFlowHandler::HandleSendPrintData));
270   web_ui_->RegisterMessageCallback(
271       "SetPageParameters",
272       NewCallback(this, &CloudPrintFlowHandler::HandleSetPageParameters));
273 
274   if (web_ui_->tab_contents()) {
275     // Also, take the opportunity to set some (minimal) additional
276     // script permissions required for the web UI.
277 
278     // TODO(scottbyer): learn how to make sure we're talking to the
279     // right web site first.
280     RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
281     if (rvh && rvh->delegate()) {
282       WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
283       webkit_prefs.allow_scripts_to_close_windows = true;
284       rvh->UpdateWebPreferences(webkit_prefs);
285     }
286 
287     // Register for appropriate notifications, and re-direct the URL
288     // to the real server URL, now that we've gotten an HTML dialog
289     // going.
290     NavigationController* controller = &web_ui_->tab_contents()->controller();
291     NavigationEntry* pending_entry = controller->pending_entry();
292     if (pending_entry)
293       pending_entry->set_url(CloudPrintURL(
294           web_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
295     registrar_.Add(this, NotificationType::LOAD_STOP,
296                    Source<NavigationController>(controller));
297   }
298 }
299 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)300 void CloudPrintFlowHandler::Observe(NotificationType type,
301                                     const NotificationSource& source,
302                                     const NotificationDetails& details) {
303   if (type == NotificationType::LOAD_STOP) {
304     // Choose one or the other.  If you need to debug, bring up the
305     // debugger.  You can then use the various chrome.send()
306     // registrations above to kick of the various function calls,
307     // including chrome.send("SendPrintData") in the javaScript
308     // console and watch things happen with:
309     // HandleShowDebugger(NULL);
310     HandleSendPrintData(NULL);
311   }
312 }
313 
HandleShowDebugger(const ListValue * args)314 void CloudPrintFlowHandler::HandleShowDebugger(const ListValue* args) {
315   ShowDebugger();
316 }
317 
ShowDebugger()318 void CloudPrintFlowHandler::ShowDebugger() {
319   if (web_ui_) {
320     RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
321     if (rvh)
322       DevToolsManager::GetInstance()->OpenDevToolsWindow(rvh);
323   }
324 }
325 
326 scoped_refptr<CloudPrintDataSender>
CreateCloudPrintDataSender()327 CloudPrintFlowHandler::CreateCloudPrintDataSender() {
328   DCHECK(web_ui_);
329   print_data_helper_.reset(new CloudPrintDataSenderHelper(web_ui_));
330   return new CloudPrintDataSender(print_data_helper_.get(),
331                                   print_job_title_,
332                                   file_type_);
333 }
334 
HandleSendPrintData(const ListValue * args)335 void CloudPrintFlowHandler::HandleSendPrintData(const ListValue* args) {
336   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
337   // This will cancel any ReadPrintDataFile() or SendPrintDataFile()
338   // requests in flight (this is anticipation of when setting page
339   // setup parameters becomes asynchronous and may be set while some
340   // data is in flight).  Then we can clear out the print data.
341   CancelAnyRunningTask();
342   if (web_ui_) {
343     print_data_sender_ = CreateCloudPrintDataSender();
344     BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
345                             NewRunnableMethod(
346                                 print_data_sender_.get(),
347                                 &CloudPrintDataSender::ReadPrintDataFile,
348                                 path_to_file_));
349   }
350 }
351 
HandleSetPageParameters(const ListValue * args)352 void CloudPrintFlowHandler::HandleSetPageParameters(const ListValue* args) {
353   std::string json;
354   args->GetString(0, &json);
355   if (json.empty()) {
356     NOTREACHED() << "Empty json string";
357     return;
358   }
359 
360   // These are backstop default values - 72 dpi to match the screen,
361   // 8.5x11 inch paper with margins subtracted (1/4 inch top, left,
362   // right and 0.56 bottom), and the min page shrink and max page
363   // shrink values appear all over the place with no explanation.
364 
365   // TODO(scottbyer): Get a Linux/ChromeOS edge for PrintSettings
366   // working so that we can get the default values from there.  Fix up
367   // PrintWebViewHelper to do the same.
368   const int kDPI = 72;
369   const int kWidth = static_cast<int>((8.5-0.25-0.25)*kDPI);
370   const int kHeight = static_cast<int>((11-0.25-0.56)*kDPI);
371   const double kMinPageShrink = 1.25;
372   const double kMaxPageShrink = 2.0;
373 
374   PrintMsg_Print_Params default_settings;
375   default_settings.printable_size = gfx::Size(kWidth, kHeight);
376   default_settings.dpi = kDPI;
377   default_settings.min_shrink = kMinPageShrink;
378   default_settings.max_shrink = kMaxPageShrink;
379   default_settings.desired_dpi = kDPI;
380   default_settings.document_cookie = 0;
381   default_settings.selection_only = false;
382 
383   if (!GetPageSetupParameters(json, default_settings)) {
384     NOTREACHED();
385     return;
386   }
387 
388   // TODO(scottbyer) - Here is where we would kick the originating
389   // renderer thread with these new parameters in order to get it to
390   // re-generate the PDF data and hand it back to us.  window.print() is
391   // currently synchronous, so there's a lot of work to do to get to
392   // that point.
393 }
394 
StoreDialogClientSize() const395 void CloudPrintFlowHandler::StoreDialogClientSize() const {
396   if (web_ui_ && web_ui_->tab_contents() && web_ui_->tab_contents()->view()) {
397     gfx::Size size = web_ui_->tab_contents()->view()->GetContainerSize();
398     web_ui_->GetProfile()->GetPrefs()->SetInteger(
399         prefs::kCloudPrintDialogWidth, size.width());
400     web_ui_->GetProfile()->GetPrefs()->SetInteger(
401         prefs::kCloudPrintDialogHeight, size.height());
402   }
403 }
404 
CloudPrintHtmlDialogDelegate(const FilePath & path_to_file,int width,int height,const std::string & json_arguments,const string16 & print_job_title,const std::string & file_type,bool modal)405 CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
406     const FilePath& path_to_file,
407     int width, int height,
408     const std::string& json_arguments,
409     const string16& print_job_title,
410     const std::string& file_type,
411     bool modal)
412     : flow_handler_(new CloudPrintFlowHandler(path_to_file,
413                                               print_job_title,
414                                               file_type)),
415       modal_(modal),
416       owns_flow_handler_(true) {
417   Init(width, height, json_arguments);
418 }
419 
420 // For unit testing.
CloudPrintHtmlDialogDelegate(CloudPrintFlowHandler * flow_handler,int width,int height,const std::string & json_arguments,bool modal)421 CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
422     CloudPrintFlowHandler* flow_handler,
423     int width, int height,
424     const std::string& json_arguments,
425     bool modal)
426     : flow_handler_(flow_handler),
427       modal_(modal),
428       owns_flow_handler_(true) {
429   Init(width, height, json_arguments);
430 }
431 
Init(int width,int height,const std::string & json_arguments)432 void CloudPrintHtmlDialogDelegate::Init(int width, int height,
433                                         const std::string& json_arguments) {
434   // This information is needed to show the dialog HTML content.
435   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
436   params_.url = GURL(chrome::kCloudPrintResourcesURL);
437   params_.height = height;
438   params_.width = width;
439   params_.json_input = json_arguments;
440 
441   flow_handler_->SetDialogDelegate(this);
442   // If we're not modal we can show the dialog with no browser.
443   // We need this to keep Chrome alive while our dialog is up.
444   if (!modal_)
445     BrowserList::StartKeepAlive();
446 }
447 
~CloudPrintHtmlDialogDelegate()448 CloudPrintHtmlDialogDelegate::~CloudPrintHtmlDialogDelegate() {
449   // If the flow_handler_ is about to outlive us because we don't own
450   // it anymore, we need to have it remove it's reference to us.
451   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
452   flow_handler_->SetDialogDelegate(NULL);
453   if (owns_flow_handler_) {
454     delete flow_handler_;
455   }
456 }
457 
IsDialogModal() const458 bool CloudPrintHtmlDialogDelegate::IsDialogModal() const {
459     return modal_;
460 }
461 
GetDialogTitle() const462 std::wstring CloudPrintHtmlDialogDelegate::GetDialogTitle() const {
463   return std::wstring();
464 }
465 
GetDialogContentURL() const466 GURL CloudPrintHtmlDialogDelegate::GetDialogContentURL() const {
467   return params_.url;
468 }
469 
GetWebUIMessageHandlers(std::vector<WebUIMessageHandler * > * handlers) const470 void CloudPrintHtmlDialogDelegate::GetWebUIMessageHandlers(
471     std::vector<WebUIMessageHandler*>* handlers) const {
472   handlers->push_back(flow_handler_);
473   // We don't own flow_handler_ anymore, but it sticks around until at
474   // least right after OnDialogClosed() is called (and this object is
475   // destroyed).
476   owns_flow_handler_ = false;
477 }
478 
GetDialogSize(gfx::Size * size) const479 void CloudPrintHtmlDialogDelegate::GetDialogSize(gfx::Size* size) const {
480   size->set_width(params_.width);
481   size->set_height(params_.height);
482 }
483 
GetDialogArgs() const484 std::string CloudPrintHtmlDialogDelegate::GetDialogArgs() const {
485   return params_.json_input;
486 }
487 
OnDialogClosed(const std::string & json_retval)488 void CloudPrintHtmlDialogDelegate::OnDialogClosed(
489     const std::string& json_retval) {
490   // Get the final dialog size and store it.
491   flow_handler_->StoreDialogClientSize();
492   // If we're modal we can show the dialog with no browser.
493   // End the keep-alive so that Chrome can exit.
494   if (!modal_)
495     BrowserList::EndKeepAlive();
496   delete this;
497 }
498 
OnCloseContents(TabContents * source,bool * out_close_dialog)499 void CloudPrintHtmlDialogDelegate::OnCloseContents(TabContents* source,
500                                                    bool* out_close_dialog) {
501   if (out_close_dialog)
502     *out_close_dialog = true;
503 }
504 
ShouldShowDialogTitle() const505 bool CloudPrintHtmlDialogDelegate::ShouldShowDialogTitle() const {
506   return false;
507 }
508 
HandleContextMenu(const ContextMenuParams & params)509 bool CloudPrintHtmlDialogDelegate::HandleContextMenu(
510     const ContextMenuParams& params) {
511   return true;
512 }
513 
514 // Called from the UI thread, starts up the dialog.
CreateDialogImpl(const FilePath & path_to_file,const string16 & print_job_title,const std::string & file_type,bool modal)515 void CreateDialogImpl(const FilePath& path_to_file,
516                       const string16& print_job_title,
517                       const std::string& file_type,
518                       bool modal) {
519   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
520   Browser* browser = BrowserList::GetLastActive();
521 
522   const int kDefaultWidth = 497;
523   const int kDefaultHeight = 332;
524   string16 job_title = print_job_title;
525   Profile* profile = NULL;
526   if (modal) {
527     DCHECK(browser);
528     if (job_title.empty() && browser->GetSelectedTabContents())
529       job_title = browser->GetSelectedTabContents()->GetTitle();
530     profile = browser->GetProfile();
531   } else {
532     profile = ProfileManager::GetDefaultProfile();
533   }
534   DCHECK(profile);
535   PrefService* pref_service = profile->GetPrefs();
536   DCHECK(pref_service);
537   if (!pref_service->FindPreference(prefs::kCloudPrintDialogWidth)) {
538     pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogWidth,
539                                       kDefaultWidth);
540   }
541   if (!pref_service->FindPreference(prefs::kCloudPrintDialogHeight)) {
542     pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogHeight,
543                                       kDefaultHeight);
544   }
545 
546   int width = pref_service->GetInteger(prefs::kCloudPrintDialogWidth);
547   int height = pref_service->GetInteger(prefs::kCloudPrintDialogHeight);
548 
549   HtmlDialogUIDelegate* dialog_delegate =
550       new internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate(
551           path_to_file, width, height, std::string(), job_title, file_type,
552           modal);
553   if (modal) {
554     DCHECK(browser);
555     browser->BrowserShowHtmlDialog(dialog_delegate, NULL);
556   } else {
557     browser::ShowHtmlDialog(NULL, profile, dialog_delegate);
558   }
559 }
560 
561 }  // namespace internal_cloud_print_helpers
562 
563 namespace print_dialog_cloud {
564 
565 // Called on the FILE or UI thread.  This is the main entry point into creating
566 // the dialog.
567 
568 // TODO(scottbyer): The signature here will need to change as the
569 // workflow through the printing code changes to allow for dynamically
570 // changing page setup parameters while the dialog is active.
CreatePrintDialogForFile(const FilePath & path_to_file,const string16 & print_job_title,const std::string & file_type,bool modal)571 void CreatePrintDialogForFile(const FilePath& path_to_file,
572                               const string16& print_job_title,
573                               const std::string& file_type,
574                               bool modal) {
575   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE) ||
576          BrowserThread::CurrentlyOn(BrowserThread::UI));
577 
578   BrowserThread::PostTask(
579       BrowserThread::UI, FROM_HERE,
580       NewRunnableFunction(&internal_cloud_print_helpers::CreateDialogImpl,
581                           path_to_file,
582                           print_job_title,
583                           file_type,
584                           modal));
585 }
586 
CreatePrintDialogFromCommandLine(const CommandLine & command_line)587 bool CreatePrintDialogFromCommandLine(const CommandLine& command_line) {
588   if (!command_line.GetSwitchValuePath(switches::kCloudPrintFile).empty()) {
589     FilePath cloud_print_file;
590     cloud_print_file =
591         command_line.GetSwitchValuePath(switches::kCloudPrintFile);
592     if (!cloud_print_file.empty()) {
593       string16 print_job_title;
594       if (command_line.HasSwitch(switches::kCloudPrintJobTitle)) {
595 #ifdef OS_WIN
596         CommandLine::StringType native_job_title;
597         native_job_title = command_line.GetSwitchValueNative(
598             switches::kCloudPrintJobTitle);
599         print_job_title = string16(native_job_title);
600 #elif defined(OS_POSIX)
601         // TODO(abodenha@chromium.org) Implement this for OS_POSIX
602         // Command line string types are different
603 #endif
604       }
605       std::string file_type = "application/pdf";
606       if (command_line.HasSwitch(switches::kCloudPrintFileType)) {
607         file_type = command_line.GetSwitchValueASCII(
608             switches::kCloudPrintFileType);
609       }
610       print_dialog_cloud::CreatePrintDialogForFile(cloud_print_file,
611                                                    print_job_title,
612                                                    file_type,
613                                                    false);
614       return true;
615     }
616   }
617   return false;
618 }
619 
620 }  // end namespace
621