blob: ad3e7a56328cadc74a35fffe98cb5d8cfbd9dd94 [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]fb534c92011-02-01 01:02:07102bool GetDoubleOrInt(const DictionaryValue& dictionary,
103 const std::string& path,
104 double* out_value) {
105 if (!dictionary.GetDouble(path, out_value)) {
[email protected]73852b8f2010-05-14 00:38:12106 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.
116bool GetPageSetupParameters(const std::string& json,
[email protected]1375e3ab2011-03-24 17:07:22117 PrintMsg_Print_Params& parameters) {
[email protected]73852b8f2010-05-14 00:38:12118 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());
[email protected]fb534c92011-02-01 01:02:07127 result &= GetDoubleOrInt(*params, "dpi", &parameters.dpi);
128 result &= GetDoubleOrInt(*params, "min_shrink", &parameters.min_shrink);
129 result &= GetDoubleOrInt(*params, "max_shrink", &parameters.max_shrink);
[email protected]a65175d2010-08-17 04:00:57130 result &= params->GetBoolean("selection_only", &parameters.selection_only);
[email protected]73852b8f2010-05-14 00:38:12131 return result;
132}
133
134void CloudPrintDataSenderHelper::CallJavascriptFunction(
135 const std::wstring& function_name) {
[email protected]adcf8492011-03-09 22:41:39136 web_ui_->CallJavascriptFunction(WideToASCII(function_name));
[email protected]73852b8f2010-05-14 00:38:12137}
138
139void CloudPrintDataSenderHelper::CallJavascriptFunction(
140 const std::wstring& function_name, const Value& arg) {
[email protected]adcf8492011-03-09 22:41:39141 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg);
[email protected]73852b8f2010-05-14 00:38:12142}
143
144void CloudPrintDataSenderHelper::CallJavascriptFunction(
145 const std::wstring& function_name, const Value& arg1, const Value& arg2) {
[email protected]adcf8492011-03-09 22:41:39146 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg1, arg2);
[email protected]73852b8f2010-05-14 00:38:12147}
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.
152void CloudPrintDataSender::CancelPrintDataFile() {
[email protected]20305ec2011-01-21 04:55:52153 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12154 // 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
[email protected]38e08982010-10-22 17:28:43159CloudPrintDataSender::CloudPrintDataSender(CloudPrintDataSenderHelper* helper,
[email protected]a984bdf2011-03-15 20:17:16160 const string16& print_job_title,
161 const std::string& file_type)
[email protected]38e08982010-10-22 17:28:43162 : helper_(helper),
[email protected]a984bdf2011-03-15 20:17:16163 print_job_title_(print_job_title),
164 file_type_(file_type) {
[email protected]38e08982010-10-22 17:28:43165}
166
167CloudPrintDataSender::~CloudPrintDataSender() {}
168
[email protected]a984bdf2011-03-15 20:17:16169// Grab the raw file contents and massage them into shape for
[email protected]73852b8f2010-05-14 00:38:12170// 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.
[email protected]a984bdf2011-03-15 20:17:16174void CloudPrintDataSender::ReadPrintDataFile(const FilePath& path_to_file) {
[email protected]ba4f1132010-10-09 02:02:35175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]73852b8f2010-05-14 00:38:12176 int64 file_size = 0;
[email protected]a984bdf2011-03-15 20:17:16177 if (file_util::GetFileSize(path_to_file, &file_size) && file_size != 0) {
[email protected]73852b8f2010-05-14 00:38:12178 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 }
[email protected]a984bdf2011-03-15 20:17:16184 if (helper_ && file_util::ReadFileToString(path_to_file, &file_data)) {
[email protected]73852b8f2010-05-14 00:38:12185 std::string base64_data;
186 base::Base64Encode(file_data, &base64_data);
[email protected]a984bdf2011-03-15 20:17:16187 std::string header("data:");
188 header.append(file_type_);
189 header.append(";base64,");
[email protected]73852b8f2010-05-14 00:38:12190 base64_data.insert(0, header);
191 scoped_ptr<StringValue> new_data(new StringValue(base64_data));
192 print_data_.swap(new_data);
[email protected]ba4f1132010-10-09 02:02:35193 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
194 NewRunnableMethod(
195 this,
196 &CloudPrintDataSender::SendPrintDataFile));
[email protected]73852b8f2010-05-14 00:38:12197 }
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
209void CloudPrintDataSender::SendPrintDataFile() {
[email protected]ba4f1132010-10-09 02:02:35210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20305ec2011-01-21 04:55:52211 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12212 if (helper_ && print_data_.get()) {
[email protected]9848c7e2010-06-03 16:06:56213 StringValue title(print_job_title_);
[email protected]73852b8f2010-05-14 00:38:12214
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
[email protected]a984bdf2011-03-15 20:17:16224CloudPrintFlowHandler::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) {
[email protected]38e08982010-10-22 17:28:43230}
231
232CloudPrintFlowHandler::~CloudPrintFlowHandler() {
233 // This will also cancel any task in flight.
234 CancelAnyRunningTask();
235}
236
237
[email protected]73852b8f2010-05-14 00:38:12238void CloudPrintFlowHandler::SetDialogDelegate(
239 CloudPrintHtmlDialogDelegate* delegate) {
[email protected]7b748982011-02-14 19:28:23240 // Even if setting a new WebUI, it means any previous task needs
[email protected]73852b8f2010-05-14 00:38:12241 // to be cancelled, it's now invalid.
[email protected]ba4f1132010-10-09 02:02:35242 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12243 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.
250void CloudPrintFlowHandler::CancelAnyRunningTask() {
[email protected]ba4f1132010-10-09 02:02:35251 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12252 if (print_data_sender_.get()) {
253 print_data_sender_->CancelPrintDataFile();
254 print_data_sender_ = NULL;
255 }
256}
257
[email protected]73852b8f2010-05-14 00:38:12258void CloudPrintFlowHandler::RegisterMessages() {
[email protected]7b748982011-02-14 19:28:23259 if (!web_ui_)
[email protected]73852b8f2010-05-14 00:38:12260 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.
[email protected]7b748982011-02-14 19:28:23264 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12265 "ShowDebugger",
266 NewCallback(this, &CloudPrintFlowHandler::HandleShowDebugger));
[email protected]7b748982011-02-14 19:28:23267 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12268 "SendPrintData",
269 NewCallback(this, &CloudPrintFlowHandler::HandleSendPrintData));
[email protected]7b748982011-02-14 19:28:23270 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12271 "SetPageParameters",
272 NewCallback(this, &CloudPrintFlowHandler::HandleSetPageParameters));
273
[email protected]7b748982011-02-14 19:28:23274 if (web_ui_->tab_contents()) {
[email protected]73852b8f2010-05-14 00:38:12275 // 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.
[email protected]7b748982011-02-14 19:28:23280 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
[email protected]73852b8f2010-05-14 00:38:12281 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.
[email protected]7b748982011-02-14 19:28:23290 NavigationController* controller = &web_ui_->tab_contents()->controller();
[email protected]73852b8f2010-05-14 00:38:12291 NavigationEntry* pending_entry = controller->pending_entry();
292 if (pending_entry)
[email protected]2283eead2010-09-29 23:17:30293 pending_entry->set_url(CloudPrintURL(
[email protected]7b748982011-02-14 19:28:23294 web_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
[email protected]73852b8f2010-05-14 00:38:12295 registrar_.Add(this, NotificationType::LOAD_STOP,
296 Source<NavigationController>(controller));
297 }
298}
299
300void 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
[email protected]88942a22010-08-19 20:34:43314void CloudPrintFlowHandler::HandleShowDebugger(const ListValue* args) {
[email protected]73852b8f2010-05-14 00:38:12315 ShowDebugger();
316}
317
318void CloudPrintFlowHandler::ShowDebugger() {
[email protected]7b748982011-02-14 19:28:23319 if (web_ui_) {
320 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
[email protected]73852b8f2010-05-14 00:38:12321 if (rvh)
322 DevToolsManager::GetInstance()->OpenDevToolsWindow(rvh);
323 }
324}
325
326scoped_refptr<CloudPrintDataSender>
327CloudPrintFlowHandler::CreateCloudPrintDataSender() {
[email protected]7b748982011-02-14 19:28:23328 DCHECK(web_ui_);
329 print_data_helper_.reset(new CloudPrintDataSenderHelper(web_ui_));
[email protected]a984bdf2011-03-15 20:17:16330 return new CloudPrintDataSender(print_data_helper_.get(),
331 print_job_title_,
332 file_type_);
[email protected]73852b8f2010-05-14 00:38:12333}
334
[email protected]88942a22010-08-19 20:34:43335void CloudPrintFlowHandler::HandleSendPrintData(const ListValue* args) {
[email protected]ba4f1132010-10-09 02:02:35336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12337 // 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();
[email protected]7b748982011-02-14 19:28:23342 if (web_ui_) {
[email protected]73852b8f2010-05-14 00:38:12343 print_data_sender_ = CreateCloudPrintDataSender();
[email protected]ba4f1132010-10-09 02:02:35344 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
345 NewRunnableMethod(
346 print_data_sender_.get(),
347 &CloudPrintDataSender::ReadPrintDataFile,
[email protected]a984bdf2011-03-15 20:17:16348 path_to_file_));
[email protected]73852b8f2010-05-14 00:38:12349 }
350}
351
[email protected]88942a22010-08-19 20:34:43352void CloudPrintFlowHandler::HandleSetPageParameters(const ListValue* args) {
[email protected]036056a32011-03-03 21:05:01353 std::string json;
354 args->GetString(0, &json);
355 if (json.empty()) {
356 NOTREACHED() << "Empty json string";
[email protected]73852b8f2010-05-14 00:38:12357 return;
[email protected]036056a32011-03-03 21:05:01358 }
[email protected]73852b8f2010-05-14 00:38:12359
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
[email protected]1375e3ab2011-03-24 17:07:22374 PrintMsg_Print_Params default_settings;
[email protected]73852b8f2010-05-14 00:38:12375 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
[email protected]a984bdf2011-03-15 20:17:16390 // re-generate the PDF data and hand it back to us. window.print() is
[email protected]73852b8f2010-05-14 00:38:12391 // currently synchronous, so there's a lot of work to do to get to
392 // that point.
393}
394
[email protected]ea161da2010-11-02 21:57:35395void CloudPrintFlowHandler::StoreDialogClientSize() const {
[email protected]7b748982011-02-14 19:28:23396 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(
[email protected]ea161da2010-11-02 21:57:35399 prefs::kCloudPrintDialogWidth, size.width());
[email protected]7b748982011-02-14 19:28:23400 web_ui_->GetProfile()->GetPrefs()->SetInteger(
[email protected]ea161da2010-11-02 21:57:35401 prefs::kCloudPrintDialogHeight, size.height());
402 }
403}
404
[email protected]73852b8f2010-05-14 00:38:12405CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16406 const FilePath& path_to_file,
[email protected]73852b8f2010-05-14 00:38:12407 int width, int height,
[email protected]9848c7e2010-06-03 16:06:56408 const std::string& json_arguments,
[email protected]e39027a2011-01-24 21:41:54409 const string16& print_job_title,
[email protected]a984bdf2011-03-15 20:17:16410 const std::string& file_type,
[email protected]e39027a2011-01-24 21:41:54411 bool modal)
[email protected]a984bdf2011-03-15 20:17:16412 : flow_handler_(new CloudPrintFlowHandler(path_to_file,
413 print_job_title,
414 file_type)),
[email protected]e39027a2011-01-24 21:41:54415 modal_(modal),
[email protected]73852b8f2010-05-14 00:38:12416 owns_flow_handler_(true) {
417 Init(width, height, json_arguments);
418}
419
[email protected]05acb55472011-02-03 00:11:07420// For unit testing.
[email protected]73852b8f2010-05-14 00:38:12421CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
422 CloudPrintFlowHandler* flow_handler,
423 int width, int height,
[email protected]e39027a2011-01-24 21:41:54424 const std::string& json_arguments,
425 bool modal)
[email protected]73852b8f2010-05-14 00:38:12426 : flow_handler_(flow_handler),
[email protected]e39027a2011-01-24 21:41:54427 modal_(modal),
[email protected]18137e02010-05-25 21:10:35428 owns_flow_handler_(true) {
[email protected]73852b8f2010-05-14 00:38:12429 Init(width, height, json_arguments);
430}
431
[email protected]05acb55472011-02-03 00:11:07432void CloudPrintHtmlDialogDelegate::Init(int width, int height,
433 const std::string& json_arguments) {
[email protected]73852b8f2010-05-14 00:38:12434 // This information is needed to show the dialog HTML content.
[email protected]ba4f1132010-10-09 02:02:35435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]05acb55472011-02-03 00:11:07436 params_.url = GURL(chrome::kCloudPrintResourcesURL);
[email protected]73852b8f2010-05-14 00:38:12437 params_.height = height;
438 params_.width = width;
439 params_.json_input = json_arguments;
440
441 flow_handler_->SetDialogDelegate(this);
[email protected]e39027a2011-01-24 21:41:54442 // 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();
[email protected]73852b8f2010-05-14 00:38:12446}
447
448CloudPrintHtmlDialogDelegate::~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.
[email protected]ba4f1132010-10-09 02:02:35451 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12452 flow_handler_->SetDialogDelegate(NULL);
453 if (owns_flow_handler_) {
454 delete flow_handler_;
455 }
456}
457
458bool CloudPrintHtmlDialogDelegate::IsDialogModal() const {
[email protected]e39027a2011-01-24 21:41:54459 return modal_;
[email protected]73852b8f2010-05-14 00:38:12460}
461
462std::wstring CloudPrintHtmlDialogDelegate::GetDialogTitle() const {
[email protected]be559e442010-11-02 20:37:32463 return std::wstring();
[email protected]73852b8f2010-05-14 00:38:12464}
465
466GURL CloudPrintHtmlDialogDelegate::GetDialogContentURL() const {
467 return params_.url;
468}
469
[email protected]36e12172011-02-08 23:46:02470void CloudPrintHtmlDialogDelegate::GetWebUIMessageHandlers(
471 std::vector<WebUIMessageHandler*>* handlers) const {
[email protected]73852b8f2010-05-14 00:38:12472 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
479void CloudPrintHtmlDialogDelegate::GetDialogSize(gfx::Size* size) const {
480 size->set_width(params_.width);
481 size->set_height(params_.height);
482}
483
484std::string CloudPrintHtmlDialogDelegate::GetDialogArgs() const {
485 return params_.json_input;
486}
487
488void CloudPrintHtmlDialogDelegate::OnDialogClosed(
489 const std::string& json_retval) {
[email protected]ea161da2010-11-02 21:57:35490 // Get the final dialog size and store it.
491 flow_handler_->StoreDialogClientSize();
[email protected]e39027a2011-01-24 21:41:54492 // 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();
[email protected]73852b8f2010-05-14 00:38:12496 delete this;
497}
498
[email protected]18137e02010-05-25 21:10:35499void CloudPrintHtmlDialogDelegate::OnCloseContents(TabContents* source,
500 bool* out_close_dialog) {
501 if (out_close_dialog)
502 *out_close_dialog = true;
503}
504
[email protected]ea161da2010-11-02 21:57:35505bool CloudPrintHtmlDialogDelegate::ShouldShowDialogTitle() const {
506 return false;
507}
508
[email protected]34478212011-04-19 01:35:46509bool CloudPrintHtmlDialogDelegate::HandleContextMenu(
510 const ContextMenuParams& params) {
511 return true;
512}
513
[email protected]6085c70d2011-03-22 22:51:07514// Called from the UI thread, starts up the dialog.
515void CreateDialogImpl(const FilePath& path_to_file,
516 const string16& print_job_title,
517 const std::string& file_type,
518 bool modal) {
[email protected]ba4f1132010-10-09 02:02:35519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]6085c70d2011-03-22 22:51:07520 Browser* browser = BrowserList::GetLastActive();
[email protected]73852b8f2010-05-14 00:38:12521
[email protected]ea161da2010-11-02 21:57:35522 const int kDefaultWidth = 497;
523 const int kDefaultHeight = 332;
[email protected]05acb55472011-02-03 00:11:07524 string16 job_title = print_job_title;
[email protected]e39027a2011-01-24 21:41:54525 Profile* profile = NULL;
[email protected]05acb55472011-02-03 00:11:07526 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07527 DCHECK(browser);
528 if (job_title.empty() && browser->GetSelectedTabContents())
529 job_title = browser->GetSelectedTabContents()->GetTitle();
530 profile = browser->GetProfile();
[email protected]e39027a2011-01-24 21:41:54531 } else {
532 profile = ProfileManager::GetDefaultProfile();
533 }
534 DCHECK(profile);
[email protected]05acb55472011-02-03 00:11:07535 PrefService* pref_service = profile->GetPrefs();
[email protected]ea161da2010-11-02 21:57:35536 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);
[email protected]e39027a2011-01-24 21:41:54548
[email protected]73852b8f2010-05-14 00:38:12549 HtmlDialogUIDelegate* dialog_delegate =
550 new internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16551 path_to_file, width, height, std::string(), job_title, file_type,
552 modal);
[email protected]05acb55472011-02-03 00:11:07553 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07554 DCHECK(browser);
555 browser->BrowserShowHtmlDialog(dialog_delegate, NULL);
[email protected]e39027a2011-01-24 21:41:54556 } else {
[email protected]eb2d7902011-02-02 18:19:56557 browser::ShowHtmlDialog(NULL, profile, dialog_delegate);
[email protected]e39027a2011-01-24 21:41:54558 }
[email protected]73852b8f2010-05-14 00:38:12559}
[email protected]6085c70d2011-03-22 22:51:07560
561} // namespace internal_cloud_print_helpers
562
563namespace 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.
571void 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
[email protected]65c9d89a2011-04-13 21:02:39587bool 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([email protected]) 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
[email protected]6085c70d2011-03-22 22:51:07620} // end namespace