blob: 052aa9a4cc9fef779cdffc959e81efeb8aa9ed60 [file] [log] [blame]
[email protected]80a8fad2011-01-29 04:02:381// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]73852b8f2010-05-14 00:38:122// 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
[email protected]73852b8f2010-05-14 00:38:128#include "base/base64.h"
[email protected]65c9d89a2011-04-13 21:02:399#include "base/command_line.h"
[email protected]73852b8f2010-05-14 00:38:1210#include "base/file_util.h"
11#include "base/json/json_reader.h"
[email protected]73852b8f2010-05-14 00:38:1212#include "base/values.h"
[email protected]37858e52010-08-26 00:22:0213#include "chrome/browser/debugger/devtools_manager.h"
[email protected]ea161da2010-11-02 21:57:3514#include "chrome/browser/prefs/pref_service.h"
[email protected]2283eead2010-09-29 23:17:3015#include "chrome/browser/printing/cloud_print/cloud_print_url.h"
[email protected]8ecad5e2010-12-02 21:18:3316#include "chrome/browser/profiles/profile.h"
[email protected]e39027a2011-01-24 21:41:5417#include "chrome/browser/profiles/profile_manager.h"
[email protected]eb2d7902011-02-02 18:19:5618#include "chrome/browser/ui/browser_dialogs.h"
[email protected]6768ac02011-04-06 17:41:0419#include "chrome/browser/ui/browser_list.h"
[email protected]65c9d89a2011-04-13 21:02:3920#include "chrome/common/chrome_switches.h"
[email protected]ea161da2010-11-02 21:57:3521#include "chrome/common/pref_names.h"
[email protected]1375e3ab2011-03-24 17:07:2222#include "chrome/common/print_messages.h"
[email protected]73852b8f2010-05-14 00:38:1223#include "chrome/common/url_constants.h"
[email protected]5f945a0e2011-03-01 17:47:5324#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"
[email protected]67fc0392011-02-25 02:56:5728#include "content/browser/webui/web_ui.h"
[email protected]ebbbb9f2011-03-09 13:16:1429#include "content/common/notification_registrar.h"
30#include "content/common/notification_source.h"
31#include "content/common/notification_type.h"
[email protected]c051a1b2011-01-21 23:30:1732#include "ui/base/l10n/l10n_util.h"
[email protected]939856a2010-08-24 20:29:0233#include "webkit/glue/webpreferences.h"
[email protected]73852b8f2010-05-14 00:38:1234
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
[email protected]a984bdf2011-03-15 20:17:1641// generated print data to the dialog contents for uploading to the
[email protected]73852b8f2010-05-14 00:38:1242// cloud print service.
43
44// Currently, the flow between these classes is as follows:
45
[email protected]a984bdf2011-03-15 20:17:1646// PrintDialogCloud::CreatePrintDialogForFile is called from
[email protected]73852b8f2010-05-14 00:38:1247// resource_message_filter_gtk.cc once the renderer has informed the
[email protected]a984bdf2011-03-15 20:17:1648// renderer host that print data generation into the renderer host provided
[email protected]032682b2011-01-12 22:05:0249// temp file has been completed. That call is on the FILE thread.
[email protected]73852b8f2010-05-14 00:38:1250// 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
[email protected]80a8fad2011-01-29 04:02:3857// recognized by the GetWebUIFactoryFunction as a signal to create an
[email protected]73852b8f2010-05-14 00:38:1258// ExternalHtmlDialogUI.
59
60// CloudPrintHtmlDialogDelegate also temporarily owns a
61// CloudPrintFlowHandler, a class which is responsible for the actual
[email protected]a984bdf2011-03-15 20:17:1662// interactions with the dialog contents, including handing in the
[email protected]73852b8f2010-05-14 00:38:1263// 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
[email protected]c39f9bf2011-02-12 00:43:5566// WebUI::RenderViewCreated). That routine, in turn, calls the
[email protected]36e12172011-02-08 23:46:0267// delegate's GetWebUIMessageHandlers routine, at which point the
[email protected]73852b8f2010-05-14 00:38:1268// 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
[email protected]c39f9bf2011-02-12 00:43:5572// The WebUI continues dialog bring-up, calling
[email protected]73852b8f2010-05-14 00:38:1273// 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
[email protected]a984bdf2011-03-15 20:17:1680// is currently used to send the data to the dialog contents.
[email protected]73852b8f2010-05-14 00:38:1281
[email protected]a984bdf2011-03-15 20:17:1682// In order to send the data to the dialog contents, the flow
[email protected]73852b8f2010-05-14 00:38:1283// handler uses a CloudPrintDataSender. It creates one, letting it
[email protected]a984bdf2011-03-15 20:17:1684// know the name of the temporary file containing the data, and
[email protected]73852b8f2010-05-14 00:38:1285// 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
[email protected]a984bdf2011-03-15 20:17:1697// high-level flow (where the data is generated before even
[email protected]73852b8f2010-05-14 00:38:1298// bringing up the dialog) isn't what we want.
99
[email protected]73852b8f2010-05-14 00:38:12100namespace internal_cloud_print_helpers {
101
[email protected]73852b8f2010-05-14 00:38:12102// From the JSON parsed value, get the entries for the page setup
103// parameters.
104bool GetPageSetupParameters(const std::string& json,
[email protected]1375e3ab2011-03-24 17:07:22105 PrintMsg_Print_Params& parameters) {
[email protected]73852b8f2010-05-14 00:38:12106 scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
107 DLOG_IF(ERROR, (!parsed_value.get() ||
108 !parsed_value->IsType(Value::TYPE_DICTIONARY)))
109 << "PageSetup call didn't have expected contents";
110 if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
111 return false;
112
113 bool result = true;
114 DictionaryValue* params = static_cast<DictionaryValue*>(parsed_value.get());
[email protected]05c7da62011-05-05 17:23:56115 result &= params->GetDouble("dpi", &parameters.dpi);
116 result &= params->GetDouble("min_shrink", &parameters.min_shrink);
117 result &= params->GetDouble("max_shrink", &parameters.max_shrink);
[email protected]a65175d2010-08-17 04:00:57118 result &= params->GetBoolean("selection_only", &parameters.selection_only);
[email protected]73852b8f2010-05-14 00:38:12119 return result;
120}
121
122void CloudPrintDataSenderHelper::CallJavascriptFunction(
123 const std::wstring& function_name) {
[email protected]adcf8492011-03-09 22:41:39124 web_ui_->CallJavascriptFunction(WideToASCII(function_name));
[email protected]73852b8f2010-05-14 00:38:12125}
126
127void CloudPrintDataSenderHelper::CallJavascriptFunction(
128 const std::wstring& function_name, const Value& arg) {
[email protected]adcf8492011-03-09 22:41:39129 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg);
[email protected]73852b8f2010-05-14 00:38:12130}
131
132void CloudPrintDataSenderHelper::CallJavascriptFunction(
133 const std::wstring& function_name, const Value& arg1, const Value& arg2) {
[email protected]adcf8492011-03-09 22:41:39134 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg1, arg2);
[email protected]73852b8f2010-05-14 00:38:12135}
136
137// Clears out the pointer we're using to communicate. Either routine is
138// potentially expensive enough that stopping whatever is in progress
139// is worth it.
140void CloudPrintDataSender::CancelPrintDataFile() {
[email protected]20305ec2011-01-21 04:55:52141 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12142 // We don't own helper, it was passed in to us, so no need to
143 // delete, just let it go.
144 helper_ = NULL;
145}
146
[email protected]38e08982010-10-22 17:28:43147CloudPrintDataSender::CloudPrintDataSender(CloudPrintDataSenderHelper* helper,
[email protected]a984bdf2011-03-15 20:17:16148 const string16& print_job_title,
149 const std::string& file_type)
[email protected]38e08982010-10-22 17:28:43150 : helper_(helper),
[email protected]a984bdf2011-03-15 20:17:16151 print_job_title_(print_job_title),
152 file_type_(file_type) {
[email protected]38e08982010-10-22 17:28:43153}
154
155CloudPrintDataSender::~CloudPrintDataSender() {}
156
[email protected]a984bdf2011-03-15 20:17:16157// Grab the raw file contents and massage them into shape for
[email protected]73852b8f2010-05-14 00:38:12158// sending to the dialog contents (and up to the cloud print server)
159// by encoding it and prefixing it with the appropriate mime type.
160// Once that is done, kick off the next part of the task on the IO
161// thread.
[email protected]a984bdf2011-03-15 20:17:16162void CloudPrintDataSender::ReadPrintDataFile(const FilePath& path_to_file) {
[email protected]ba4f1132010-10-09 02:02:35163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]73852b8f2010-05-14 00:38:12164 int64 file_size = 0;
[email protected]a984bdf2011-03-15 20:17:16165 if (file_util::GetFileSize(path_to_file, &file_size) && file_size != 0) {
[email protected]73852b8f2010-05-14 00:38:12166 std::string file_data;
167 if (file_size < kuint32max) {
168 file_data.reserve(static_cast<unsigned int>(file_size));
169 } else {
170 DLOG(WARNING) << " print data file too large to reserve space";
171 }
[email protected]a984bdf2011-03-15 20:17:16172 if (helper_ && file_util::ReadFileToString(path_to_file, &file_data)) {
[email protected]73852b8f2010-05-14 00:38:12173 std::string base64_data;
174 base::Base64Encode(file_data, &base64_data);
[email protected]a984bdf2011-03-15 20:17:16175 std::string header("data:");
176 header.append(file_type_);
177 header.append(";base64,");
[email protected]73852b8f2010-05-14 00:38:12178 base64_data.insert(0, header);
179 scoped_ptr<StringValue> new_data(new StringValue(base64_data));
180 print_data_.swap(new_data);
[email protected]ba4f1132010-10-09 02:02:35181 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
182 NewRunnableMethod(
183 this,
184 &CloudPrintDataSender::SendPrintDataFile));
[email protected]73852b8f2010-05-14 00:38:12185 }
186 }
187}
188
189// We have the data in hand that needs to be pushed into the dialog
190// contents; do so from the IO thread.
191
192// TODO(scottbyer): If the print data ends up being larger than the
193// upload limit (currently 10MB), what we need to do is upload that
194// large data to google docs and set the URL in the printing
195// JavaScript to that location, and make sure it gets deleted when not
196// needed. - 4/1/2010
197void CloudPrintDataSender::SendPrintDataFile() {
[email protected]ba4f1132010-10-09 02:02:35198 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20305ec2011-01-21 04:55:52199 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12200 if (helper_ && print_data_.get()) {
[email protected]9848c7e2010-06-03 16:06:56201 StringValue title(print_job_title_);
[email protected]73852b8f2010-05-14 00:38:12202
203 // Send the print data to the dialog contents. The JavaScript
204 // function is a preliminary API for prototyping purposes and is
205 // subject to change.
206 const_cast<CloudPrintDataSenderHelper*>(helper_)->CallJavascriptFunction(
207 L"printApp._printDataUrl", *print_data_, title);
208 }
209}
210
211
[email protected]a984bdf2011-03-15 20:17:16212CloudPrintFlowHandler::CloudPrintFlowHandler(const FilePath& path_to_file,
213 const string16& print_job_title,
214 const std::string& file_type)
215 : path_to_file_(path_to_file),
216 print_job_title_(print_job_title),
217 file_type_(file_type) {
[email protected]38e08982010-10-22 17:28:43218}
219
220CloudPrintFlowHandler::~CloudPrintFlowHandler() {
221 // This will also cancel any task in flight.
222 CancelAnyRunningTask();
223}
224
225
[email protected]73852b8f2010-05-14 00:38:12226void CloudPrintFlowHandler::SetDialogDelegate(
227 CloudPrintHtmlDialogDelegate* delegate) {
[email protected]7b748982011-02-14 19:28:23228 // Even if setting a new WebUI, it means any previous task needs
[email protected]73852b8f2010-05-14 00:38:12229 // to be cancelled, it's now invalid.
[email protected]ba4f1132010-10-09 02:02:35230 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12231 CancelAnyRunningTask();
232 dialog_delegate_ = delegate;
233}
234
235// Cancels any print data sender we have in flight and removes our
236// reference to it, so when the task that is calling it finishes and
237// removes it's reference, it goes away.
238void CloudPrintFlowHandler::CancelAnyRunningTask() {
[email protected]ba4f1132010-10-09 02:02:35239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12240 if (print_data_sender_.get()) {
241 print_data_sender_->CancelPrintDataFile();
242 print_data_sender_ = NULL;
243 }
244}
245
[email protected]73852b8f2010-05-14 00:38:12246void CloudPrintFlowHandler::RegisterMessages() {
[email protected]7b748982011-02-14 19:28:23247 if (!web_ui_)
[email protected]73852b8f2010-05-14 00:38:12248 return;
249
250 // TODO(scottbyer) - This is where we will register messages for the
251 // UI JS to use. Needed: Call to update page setup parameters.
[email protected]7b748982011-02-14 19:28:23252 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12253 "ShowDebugger",
254 NewCallback(this, &CloudPrintFlowHandler::HandleShowDebugger));
[email protected]7b748982011-02-14 19:28:23255 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12256 "SendPrintData",
257 NewCallback(this, &CloudPrintFlowHandler::HandleSendPrintData));
[email protected]7b748982011-02-14 19:28:23258 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12259 "SetPageParameters",
260 NewCallback(this, &CloudPrintFlowHandler::HandleSetPageParameters));
261
[email protected]7b748982011-02-14 19:28:23262 if (web_ui_->tab_contents()) {
[email protected]73852b8f2010-05-14 00:38:12263 // Also, take the opportunity to set some (minimal) additional
264 // script permissions required for the web UI.
265
266 // TODO(scottbyer): learn how to make sure we're talking to the
267 // right web site first.
[email protected]7b748982011-02-14 19:28:23268 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
[email protected]73852b8f2010-05-14 00:38:12269 if (rvh && rvh->delegate()) {
270 WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
271 webkit_prefs.allow_scripts_to_close_windows = true;
272 rvh->UpdateWebPreferences(webkit_prefs);
273 }
274
275 // Register for appropriate notifications, and re-direct the URL
276 // to the real server URL, now that we've gotten an HTML dialog
277 // going.
[email protected]7b748982011-02-14 19:28:23278 NavigationController* controller = &web_ui_->tab_contents()->controller();
[email protected]73852b8f2010-05-14 00:38:12279 NavigationEntry* pending_entry = controller->pending_entry();
280 if (pending_entry)
[email protected]2283eead2010-09-29 23:17:30281 pending_entry->set_url(CloudPrintURL(
[email protected]7b748982011-02-14 19:28:23282 web_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
[email protected]73852b8f2010-05-14 00:38:12283 registrar_.Add(this, NotificationType::LOAD_STOP,
284 Source<NavigationController>(controller));
285 }
286}
287
288void CloudPrintFlowHandler::Observe(NotificationType type,
289 const NotificationSource& source,
290 const NotificationDetails& details) {
291 if (type == NotificationType::LOAD_STOP) {
292 // Choose one or the other. If you need to debug, bring up the
293 // debugger. You can then use the various chrome.send()
294 // registrations above to kick of the various function calls,
295 // including chrome.send("SendPrintData") in the javaScript
296 // console and watch things happen with:
297 // HandleShowDebugger(NULL);
298 HandleSendPrintData(NULL);
299 }
300}
301
[email protected]88942a22010-08-19 20:34:43302void CloudPrintFlowHandler::HandleShowDebugger(const ListValue* args) {
[email protected]73852b8f2010-05-14 00:38:12303 ShowDebugger();
304}
305
306void CloudPrintFlowHandler::ShowDebugger() {
[email protected]7b748982011-02-14 19:28:23307 if (web_ui_) {
308 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
[email protected]73852b8f2010-05-14 00:38:12309 if (rvh)
310 DevToolsManager::GetInstance()->OpenDevToolsWindow(rvh);
311 }
312}
313
314scoped_refptr<CloudPrintDataSender>
315CloudPrintFlowHandler::CreateCloudPrintDataSender() {
[email protected]7b748982011-02-14 19:28:23316 DCHECK(web_ui_);
317 print_data_helper_.reset(new CloudPrintDataSenderHelper(web_ui_));
[email protected]a984bdf2011-03-15 20:17:16318 return new CloudPrintDataSender(print_data_helper_.get(),
319 print_job_title_,
320 file_type_);
[email protected]73852b8f2010-05-14 00:38:12321}
322
[email protected]88942a22010-08-19 20:34:43323void CloudPrintFlowHandler::HandleSendPrintData(const ListValue* args) {
[email protected]ba4f1132010-10-09 02:02:35324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12325 // This will cancel any ReadPrintDataFile() or SendPrintDataFile()
326 // requests in flight (this is anticipation of when setting page
327 // setup parameters becomes asynchronous and may be set while some
328 // data is in flight). Then we can clear out the print data.
329 CancelAnyRunningTask();
[email protected]7b748982011-02-14 19:28:23330 if (web_ui_) {
[email protected]73852b8f2010-05-14 00:38:12331 print_data_sender_ = CreateCloudPrintDataSender();
[email protected]ba4f1132010-10-09 02:02:35332 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
333 NewRunnableMethod(
334 print_data_sender_.get(),
335 &CloudPrintDataSender::ReadPrintDataFile,
[email protected]a984bdf2011-03-15 20:17:16336 path_to_file_));
[email protected]73852b8f2010-05-14 00:38:12337 }
338}
339
[email protected]88942a22010-08-19 20:34:43340void CloudPrintFlowHandler::HandleSetPageParameters(const ListValue* args) {
[email protected]036056a32011-03-03 21:05:01341 std::string json;
342 args->GetString(0, &json);
343 if (json.empty()) {
344 NOTREACHED() << "Empty json string";
[email protected]73852b8f2010-05-14 00:38:12345 return;
[email protected]036056a32011-03-03 21:05:01346 }
[email protected]73852b8f2010-05-14 00:38:12347
348 // These are backstop default values - 72 dpi to match the screen,
349 // 8.5x11 inch paper with margins subtracted (1/4 inch top, left,
350 // right and 0.56 bottom), and the min page shrink and max page
351 // shrink values appear all over the place with no explanation.
352
353 // TODO(scottbyer): Get a Linux/ChromeOS edge for PrintSettings
354 // working so that we can get the default values from there. Fix up
355 // PrintWebViewHelper to do the same.
356 const int kDPI = 72;
357 const int kWidth = static_cast<int>((8.5-0.25-0.25)*kDPI);
358 const int kHeight = static_cast<int>((11-0.25-0.56)*kDPI);
359 const double kMinPageShrink = 1.25;
360 const double kMaxPageShrink = 2.0;
361
[email protected]1375e3ab2011-03-24 17:07:22362 PrintMsg_Print_Params default_settings;
[email protected]73852b8f2010-05-14 00:38:12363 default_settings.printable_size = gfx::Size(kWidth, kHeight);
364 default_settings.dpi = kDPI;
365 default_settings.min_shrink = kMinPageShrink;
366 default_settings.max_shrink = kMaxPageShrink;
367 default_settings.desired_dpi = kDPI;
368 default_settings.document_cookie = 0;
369 default_settings.selection_only = false;
370
371 if (!GetPageSetupParameters(json, default_settings)) {
372 NOTREACHED();
373 return;
374 }
375
376 // TODO(scottbyer) - Here is where we would kick the originating
377 // renderer thread with these new parameters in order to get it to
[email protected]a984bdf2011-03-15 20:17:16378 // re-generate the PDF data and hand it back to us. window.print() is
[email protected]73852b8f2010-05-14 00:38:12379 // currently synchronous, so there's a lot of work to do to get to
380 // that point.
381}
382
[email protected]ea161da2010-11-02 21:57:35383void CloudPrintFlowHandler::StoreDialogClientSize() const {
[email protected]7b748982011-02-14 19:28:23384 if (web_ui_ && web_ui_->tab_contents() && web_ui_->tab_contents()->view()) {
385 gfx::Size size = web_ui_->tab_contents()->view()->GetContainerSize();
386 web_ui_->GetProfile()->GetPrefs()->SetInteger(
[email protected]ea161da2010-11-02 21:57:35387 prefs::kCloudPrintDialogWidth, size.width());
[email protected]7b748982011-02-14 19:28:23388 web_ui_->GetProfile()->GetPrefs()->SetInteger(
[email protected]ea161da2010-11-02 21:57:35389 prefs::kCloudPrintDialogHeight, size.height());
390 }
391}
392
[email protected]73852b8f2010-05-14 00:38:12393CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16394 const FilePath& path_to_file,
[email protected]73852b8f2010-05-14 00:38:12395 int width, int height,
[email protected]9848c7e2010-06-03 16:06:56396 const std::string& json_arguments,
[email protected]e39027a2011-01-24 21:41:54397 const string16& print_job_title,
[email protected]a984bdf2011-03-15 20:17:16398 const std::string& file_type,
[email protected]e39027a2011-01-24 21:41:54399 bool modal)
[email protected]a984bdf2011-03-15 20:17:16400 : flow_handler_(new CloudPrintFlowHandler(path_to_file,
401 print_job_title,
402 file_type)),
[email protected]e39027a2011-01-24 21:41:54403 modal_(modal),
[email protected]6ddda232011-04-22 15:41:47404 owns_flow_handler_(true),
405 path_to_file_(path_to_file) {
[email protected]73852b8f2010-05-14 00:38:12406 Init(width, height, json_arguments);
407}
408
[email protected]05acb55472011-02-03 00:11:07409// For unit testing.
[email protected]73852b8f2010-05-14 00:38:12410CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
411 CloudPrintFlowHandler* flow_handler,
412 int width, int height,
[email protected]e39027a2011-01-24 21:41:54413 const std::string& json_arguments,
414 bool modal)
[email protected]73852b8f2010-05-14 00:38:12415 : flow_handler_(flow_handler),
[email protected]e39027a2011-01-24 21:41:54416 modal_(modal),
[email protected]18137e02010-05-25 21:10:35417 owns_flow_handler_(true) {
[email protected]73852b8f2010-05-14 00:38:12418 Init(width, height, json_arguments);
419}
420
[email protected]05acb55472011-02-03 00:11:07421void CloudPrintHtmlDialogDelegate::Init(int width, int height,
422 const std::string& json_arguments) {
[email protected]73852b8f2010-05-14 00:38:12423 // This information is needed to show the dialog HTML content.
[email protected]ba4f1132010-10-09 02:02:35424 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]05acb55472011-02-03 00:11:07425 params_.url = GURL(chrome::kCloudPrintResourcesURL);
[email protected]73852b8f2010-05-14 00:38:12426 params_.height = height;
427 params_.width = width;
428 params_.json_input = json_arguments;
429
430 flow_handler_->SetDialogDelegate(this);
[email protected]e39027a2011-01-24 21:41:54431 // If we're not modal we can show the dialog with no browser.
432 // We need this to keep Chrome alive while our dialog is up.
433 if (!modal_)
434 BrowserList::StartKeepAlive();
[email protected]73852b8f2010-05-14 00:38:12435}
436
437CloudPrintHtmlDialogDelegate::~CloudPrintHtmlDialogDelegate() {
438 // If the flow_handler_ is about to outlive us because we don't own
439 // it anymore, we need to have it remove it's reference to us.
[email protected]ba4f1132010-10-09 02:02:35440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12441 flow_handler_->SetDialogDelegate(NULL);
442 if (owns_flow_handler_) {
443 delete flow_handler_;
444 }
445}
446
447bool CloudPrintHtmlDialogDelegate::IsDialogModal() const {
[email protected]e39027a2011-01-24 21:41:54448 return modal_;
[email protected]73852b8f2010-05-14 00:38:12449}
450
451std::wstring CloudPrintHtmlDialogDelegate::GetDialogTitle() const {
[email protected]be559e442010-11-02 20:37:32452 return std::wstring();
[email protected]73852b8f2010-05-14 00:38:12453}
454
455GURL CloudPrintHtmlDialogDelegate::GetDialogContentURL() const {
456 return params_.url;
457}
458
[email protected]36e12172011-02-08 23:46:02459void CloudPrintHtmlDialogDelegate::GetWebUIMessageHandlers(
460 std::vector<WebUIMessageHandler*>* handlers) const {
[email protected]73852b8f2010-05-14 00:38:12461 handlers->push_back(flow_handler_);
462 // We don't own flow_handler_ anymore, but it sticks around until at
463 // least right after OnDialogClosed() is called (and this object is
464 // destroyed).
465 owns_flow_handler_ = false;
466}
467
468void CloudPrintHtmlDialogDelegate::GetDialogSize(gfx::Size* size) const {
469 size->set_width(params_.width);
470 size->set_height(params_.height);
471}
472
473std::string CloudPrintHtmlDialogDelegate::GetDialogArgs() const {
474 return params_.json_input;
475}
476
477void CloudPrintHtmlDialogDelegate::OnDialogClosed(
478 const std::string& json_retval) {
[email protected]ea161da2010-11-02 21:57:35479 // Get the final dialog size and store it.
480 flow_handler_->StoreDialogClientSize();
[email protected]6ddda232011-04-22 15:41:47481
482 if (CommandLine::ForCurrentProcess()->HasSwitch(
483 switches::kCloudPrintDeleteFile)) {
484 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
485 NewRunnableFunction(&internal_cloud_print_helpers::Delete,
486 path_to_file_));
487 }
488
[email protected]e39027a2011-01-24 21:41:54489 // If we're modal we can show the dialog with no browser.
490 // End the keep-alive so that Chrome can exit.
491 if (!modal_)
492 BrowserList::EndKeepAlive();
[email protected]73852b8f2010-05-14 00:38:12493 delete this;
494}
495
[email protected]18137e02010-05-25 21:10:35496void CloudPrintHtmlDialogDelegate::OnCloseContents(TabContents* source,
497 bool* out_close_dialog) {
498 if (out_close_dialog)
499 *out_close_dialog = true;
500}
501
[email protected]ea161da2010-11-02 21:57:35502bool CloudPrintHtmlDialogDelegate::ShouldShowDialogTitle() const {
503 return false;
504}
505
[email protected]34478212011-04-19 01:35:46506bool CloudPrintHtmlDialogDelegate::HandleContextMenu(
507 const ContextMenuParams& params) {
508 return true;
509}
510
[email protected]6085c70d2011-03-22 22:51:07511// Called from the UI thread, starts up the dialog.
512void CreateDialogImpl(const FilePath& path_to_file,
513 const string16& print_job_title,
514 const std::string& file_type,
515 bool modal) {
[email protected]ba4f1132010-10-09 02:02:35516 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]6085c70d2011-03-22 22:51:07517 Browser* browser = BrowserList::GetLastActive();
[email protected]73852b8f2010-05-14 00:38:12518
[email protected]ea161da2010-11-02 21:57:35519 const int kDefaultWidth = 497;
520 const int kDefaultHeight = 332;
[email protected]05acb55472011-02-03 00:11:07521 string16 job_title = print_job_title;
[email protected]e39027a2011-01-24 21:41:54522 Profile* profile = NULL;
[email protected]05acb55472011-02-03 00:11:07523 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07524 DCHECK(browser);
525 if (job_title.empty() && browser->GetSelectedTabContents())
526 job_title = browser->GetSelectedTabContents()->GetTitle();
527 profile = browser->GetProfile();
[email protected]e39027a2011-01-24 21:41:54528 } else {
529 profile = ProfileManager::GetDefaultProfile();
530 }
531 DCHECK(profile);
[email protected]05acb55472011-02-03 00:11:07532 PrefService* pref_service = profile->GetPrefs();
[email protected]ea161da2010-11-02 21:57:35533 DCHECK(pref_service);
534 if (!pref_service->FindPreference(prefs::kCloudPrintDialogWidth)) {
535 pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogWidth,
[email protected]d36f941b2011-05-09 06:19:16536 kDefaultWidth,
537 PrefService::UNSYNCABLE_PREF);
[email protected]ea161da2010-11-02 21:57:35538 }
539 if (!pref_service->FindPreference(prefs::kCloudPrintDialogHeight)) {
540 pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogHeight,
[email protected]d36f941b2011-05-09 06:19:16541 kDefaultHeight,
542 PrefService::UNSYNCABLE_PREF);
[email protected]ea161da2010-11-02 21:57:35543 }
544
545 int width = pref_service->GetInteger(prefs::kCloudPrintDialogWidth);
546 int height = pref_service->GetInteger(prefs::kCloudPrintDialogHeight);
[email protected]e39027a2011-01-24 21:41:54547
[email protected]73852b8f2010-05-14 00:38:12548 HtmlDialogUIDelegate* dialog_delegate =
549 new internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16550 path_to_file, width, height, std::string(), job_title, file_type,
551 modal);
[email protected]05acb55472011-02-03 00:11:07552 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07553 DCHECK(browser);
554 browser->BrowserShowHtmlDialog(dialog_delegate, NULL);
[email protected]e39027a2011-01-24 21:41:54555 } else {
[email protected]eb2d7902011-02-02 18:19:56556 browser::ShowHtmlDialog(NULL, profile, dialog_delegate);
[email protected]e39027a2011-01-24 21:41:54557 }
[email protected]73852b8f2010-05-14 00:38:12558}
[email protected]6085c70d2011-03-22 22:51:07559
[email protected]6ddda232011-04-22 15:41:47560// Provides a runnable function to delete a file.
561void Delete(const FilePath& file_path) {
562 file_util::Delete(file_path, false);
563}
564
[email protected]6085c70d2011-03-22 22:51:07565} // namespace internal_cloud_print_helpers
566
567namespace print_dialog_cloud {
568
569// Called on the FILE or UI thread. This is the main entry point into creating
570// the dialog.
571
572// TODO(scottbyer): The signature here will need to change as the
573// workflow through the printing code changes to allow for dynamically
574// changing page setup parameters while the dialog is active.
575void CreatePrintDialogForFile(const FilePath& path_to_file,
576 const string16& print_job_title,
577 const std::string& file_type,
578 bool modal) {
579 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE) ||
580 BrowserThread::CurrentlyOn(BrowserThread::UI));
581
582 BrowserThread::PostTask(
583 BrowserThread::UI, FROM_HERE,
584 NewRunnableFunction(&internal_cloud_print_helpers::CreateDialogImpl,
585 path_to_file,
586 print_job_title,
587 file_type,
588 modal));
589}
590
[email protected]65c9d89a2011-04-13 21:02:39591bool CreatePrintDialogFromCommandLine(const CommandLine& command_line) {
592 if (!command_line.GetSwitchValuePath(switches::kCloudPrintFile).empty()) {
593 FilePath cloud_print_file;
594 cloud_print_file =
595 command_line.GetSwitchValuePath(switches::kCloudPrintFile);
596 if (!cloud_print_file.empty()) {
597 string16 print_job_title;
598 if (command_line.HasSwitch(switches::kCloudPrintJobTitle)) {
599#ifdef OS_WIN
600 CommandLine::StringType native_job_title;
601 native_job_title = command_line.GetSwitchValueNative(
602 switches::kCloudPrintJobTitle);
603 print_job_title = string16(native_job_title);
604#elif defined(OS_POSIX)
605 // TODO([email protected]) Implement this for OS_POSIX
606 // Command line string types are different
607#endif
608 }
609 std::string file_type = "application/pdf";
610 if (command_line.HasSwitch(switches::kCloudPrintFileType)) {
611 file_type = command_line.GetSwitchValueASCII(
612 switches::kCloudPrintFileType);
613 }
614 print_dialog_cloud::CreatePrintDialogForFile(cloud_print_file,
615 print_job_title,
616 file_type,
617 false);
618 return true;
619 }
620 }
621 return false;
622}
623
[email protected]6085c70d2011-03-22 22:51:07624} // end namespace