blob: d82a155f813f85f152cb01e966fc5fbf02939a73 [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]4b8852a2011-06-10 17:24:4612#include "base/utf_string_conversions.h"
[email protected]73852b8f2010-05-14 00:38:1213#include "base/values.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"
[email protected]b46442d7e2011-06-29 02:16:0625#include "content/browser/debugger/devtools_manager.h"
[email protected]5f945a0e2011-03-01 17:47:5326#include "content/browser/renderer_host/render_view_host.h"
27#include "content/browser/tab_contents/tab_contents.h"
28#include "content/browser/tab_contents/tab_contents_view.h"
[email protected]67fc0392011-02-25 02:56:5729#include "content/browser/webui/web_ui.h"
[email protected]ebbbb9f2011-03-09 13:16:1430#include "content/common/notification_registrar.h"
31#include "content/common/notification_source.h"
32#include "content/common/notification_type.h"
[email protected]216813952011-05-19 22:21:2633#include "content/common/view_messages.h"
[email protected]c051a1b2011-01-21 23:30:1734#include "ui/base/l10n/l10n_util.h"
[email protected]939856a2010-08-24 20:29:0235#include "webkit/glue/webpreferences.h"
[email protected]73852b8f2010-05-14 00:38:1236
37#include "grit/generated_resources.h"
38
39// This module implements the UI support in Chrome for cloud printing.
40// This means hosting a dialog containing HTML/JavaScript and using
41// the published cloud print user interface integration APIs to get
42// page setup settings from the dialog contents and provide the
[email protected]a984bdf2011-03-15 20:17:1643// generated print data to the dialog contents for uploading to the
[email protected]73852b8f2010-05-14 00:38:1244// cloud print service.
45
46// Currently, the flow between these classes is as follows:
47
[email protected]a984bdf2011-03-15 20:17:1648// PrintDialogCloud::CreatePrintDialogForFile is called from
[email protected]73852b8f2010-05-14 00:38:1249// resource_message_filter_gtk.cc once the renderer has informed the
[email protected]a984bdf2011-03-15 20:17:1650// renderer host that print data generation into the renderer host provided
[email protected]032682b2011-01-12 22:05:0251// temp file has been completed. That call is on the FILE thread.
[email protected]73852b8f2010-05-14 00:38:1252// That, in turn, hops over to the UI thread to create an instance of
53// PrintDialogCloud.
54
55// The constructor for PrintDialogCloud creates a
56// CloudPrintHtmlDialogDelegate and asks the current active browser to
57// show an HTML dialog using that class as the delegate. That class
[email protected]89f550b2011-06-08 18:34:0358// hands in the kChromeUICloudPrintResourcesURL as the URL to visit. That is
[email protected]80a8fad2011-01-29 04:02:3859// recognized by the GetWebUIFactoryFunction as a signal to create an
[email protected]73852b8f2010-05-14 00:38:1260// ExternalHtmlDialogUI.
61
62// CloudPrintHtmlDialogDelegate also temporarily owns a
63// CloudPrintFlowHandler, a class which is responsible for the actual
[email protected]a984bdf2011-03-15 20:17:1664// interactions with the dialog contents, including handing in the
[email protected]73852b8f2010-05-14 00:38:1265// print data and getting any page setup parameters that the dialog
66// contents provides. As part of bringing up the dialog,
67// HtmlDialogUI::RenderViewCreated is called (an override of
[email protected]c39f9bf2011-02-12 00:43:5568// WebUI::RenderViewCreated). That routine, in turn, calls the
[email protected]36e12172011-02-08 23:46:0269// delegate's GetWebUIMessageHandlers routine, at which point the
[email protected]73852b8f2010-05-14 00:38:1270// ownership of the CloudPrintFlowHandler is handed over. A pointer
71// to the flow handler is kept to facilitate communication back and
72// forth between the two classes.
73
[email protected]c39f9bf2011-02-12 00:43:5574// The WebUI continues dialog bring-up, calling
[email protected]73852b8f2010-05-14 00:38:1275// CloudPrintFlowHandler::RegisterMessages. This is where the
76// additional object model capabilities are registered for the dialog
77// contents to use. It is also at this time that capabilities for the
78// dialog contents are adjusted to allow the dialog contents to close
79// the window. In addition, the pending URL is redirected to the
80// actual cloud print service URL. The flow controller also registers
81// for notification of when the dialog contents finish loading, which
[email protected]a984bdf2011-03-15 20:17:1682// is currently used to send the data to the dialog contents.
[email protected]73852b8f2010-05-14 00:38:1283
[email protected]a984bdf2011-03-15 20:17:1684// In order to send the data to the dialog contents, the flow
[email protected]73852b8f2010-05-14 00:38:1285// handler uses a CloudPrintDataSender. It creates one, letting it
[email protected]a984bdf2011-03-15 20:17:1686// know the name of the temporary file containing the data, and
[email protected]73852b8f2010-05-14 00:38:1287// posts the task of reading the file
88// (CloudPrintDataSender::ReadPrintDataFile) to the file thread. That
89// routine reads in the file, and then hops over to the IO thread to
90// send that data to the dialog contents.
91
92// When the dialog contents are finished (by either being cancelled or
93// hitting the print button), the delegate is notified, and responds
94// that the dialog should be closed, at which point things are torn
95// down and released.
96
97// TODO(scottbyer):
98// http://code.google.com/p/chromium/issues/detail?id=44093 The
[email protected]a984bdf2011-03-15 20:17:1699// high-level flow (where the data is generated before even
[email protected]73852b8f2010-05-14 00:38:12100// bringing up the dialog) isn't what we want.
101
[email protected]73852b8f2010-05-14 00:38:12102namespace internal_cloud_print_helpers {
103
[email protected]73852b8f2010-05-14 00:38:12104// From the JSON parsed value, get the entries for the page setup
105// parameters.
106bool GetPageSetupParameters(const std::string& json,
[email protected]1375e3ab2011-03-24 17:07:22107 PrintMsg_Print_Params& parameters) {
[email protected]73852b8f2010-05-14 00:38:12108 scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
109 DLOG_IF(ERROR, (!parsed_value.get() ||
110 !parsed_value->IsType(Value::TYPE_DICTIONARY)))
111 << "PageSetup call didn't have expected contents";
112 if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
113 return false;
114
115 bool result = true;
116 DictionaryValue* params = static_cast<DictionaryValue*>(parsed_value.get());
[email protected]05c7da62011-05-05 17:23:56117 result &= params->GetDouble("dpi", &parameters.dpi);
118 result &= params->GetDouble("min_shrink", &parameters.min_shrink);
119 result &= params->GetDouble("max_shrink", &parameters.max_shrink);
[email protected]a65175d2010-08-17 04:00:57120 result &= params->GetBoolean("selection_only", &parameters.selection_only);
[email protected]73852b8f2010-05-14 00:38:12121 return result;
122}
123
124void CloudPrintDataSenderHelper::CallJavascriptFunction(
125 const std::wstring& function_name) {
[email protected]adcf8492011-03-09 22:41:39126 web_ui_->CallJavascriptFunction(WideToASCII(function_name));
[email protected]73852b8f2010-05-14 00:38:12127}
128
129void CloudPrintDataSenderHelper::CallJavascriptFunction(
130 const std::wstring& function_name, const Value& arg) {
[email protected]adcf8492011-03-09 22:41:39131 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg);
[email protected]73852b8f2010-05-14 00:38:12132}
133
134void CloudPrintDataSenderHelper::CallJavascriptFunction(
135 const std::wstring& function_name, const Value& arg1, const Value& arg2) {
[email protected]adcf8492011-03-09 22:41:39136 web_ui_->CallJavascriptFunction(WideToASCII(function_name), arg1, arg2);
[email protected]73852b8f2010-05-14 00:38:12137}
138
139// Clears out the pointer we're using to communicate. Either routine is
140// potentially expensive enough that stopping whatever is in progress
141// is worth it.
142void CloudPrintDataSender::CancelPrintDataFile() {
[email protected]20305ec2011-01-21 04:55:52143 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12144 // We don't own helper, it was passed in to us, so no need to
145 // delete, just let it go.
146 helper_ = NULL;
147}
148
[email protected]38e08982010-10-22 17:28:43149CloudPrintDataSender::CloudPrintDataSender(CloudPrintDataSenderHelper* helper,
[email protected]a984bdf2011-03-15 20:17:16150 const string16& print_job_title,
151 const std::string& file_type)
[email protected]38e08982010-10-22 17:28:43152 : helper_(helper),
[email protected]a984bdf2011-03-15 20:17:16153 print_job_title_(print_job_title),
154 file_type_(file_type) {
[email protected]38e08982010-10-22 17:28:43155}
156
157CloudPrintDataSender::~CloudPrintDataSender() {}
158
[email protected]a984bdf2011-03-15 20:17:16159// Grab the raw file contents and massage them into shape for
[email protected]73852b8f2010-05-14 00:38:12160// sending to the dialog contents (and up to the cloud print server)
161// by encoding it and prefixing it with the appropriate mime type.
162// Once that is done, kick off the next part of the task on the IO
163// thread.
[email protected]a984bdf2011-03-15 20:17:16164void CloudPrintDataSender::ReadPrintDataFile(const FilePath& path_to_file) {
[email protected]ba4f1132010-10-09 02:02:35165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
[email protected]73852b8f2010-05-14 00:38:12166 int64 file_size = 0;
[email protected]a984bdf2011-03-15 20:17:16167 if (file_util::GetFileSize(path_to_file, &file_size) && file_size != 0) {
[email protected]73852b8f2010-05-14 00:38:12168 std::string file_data;
169 if (file_size < kuint32max) {
170 file_data.reserve(static_cast<unsigned int>(file_size));
171 } else {
172 DLOG(WARNING) << " print data file too large to reserve space";
173 }
[email protected]a984bdf2011-03-15 20:17:16174 if (helper_ && file_util::ReadFileToString(path_to_file, &file_data)) {
[email protected]73852b8f2010-05-14 00:38:12175 std::string base64_data;
176 base::Base64Encode(file_data, &base64_data);
[email protected]a984bdf2011-03-15 20:17:16177 std::string header("data:");
178 header.append(file_type_);
179 header.append(";base64,");
[email protected]73852b8f2010-05-14 00:38:12180 base64_data.insert(0, header);
181 scoped_ptr<StringValue> new_data(new StringValue(base64_data));
182 print_data_.swap(new_data);
[email protected]ba4f1132010-10-09 02:02:35183 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
184 NewRunnableMethod(
185 this,
186 &CloudPrintDataSender::SendPrintDataFile));
[email protected]73852b8f2010-05-14 00:38:12187 }
188 }
189}
190
191// We have the data in hand that needs to be pushed into the dialog
192// contents; do so from the IO thread.
193
194// TODO(scottbyer): If the print data ends up being larger than the
195// upload limit (currently 10MB), what we need to do is upload that
196// large data to google docs and set the URL in the printing
197// JavaScript to that location, and make sure it gets deleted when not
198// needed. - 4/1/2010
199void CloudPrintDataSender::SendPrintDataFile() {
[email protected]ba4f1132010-10-09 02:02:35200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
[email protected]20305ec2011-01-21 04:55:52201 base::AutoLock lock(lock_);
[email protected]73852b8f2010-05-14 00:38:12202 if (helper_ && print_data_.get()) {
[email protected]9848c7e2010-06-03 16:06:56203 StringValue title(print_job_title_);
[email protected]73852b8f2010-05-14 00:38:12204
205 // Send the print data to the dialog contents. The JavaScript
206 // function is a preliminary API for prototyping purposes and is
207 // subject to change.
208 const_cast<CloudPrintDataSenderHelper*>(helper_)->CallJavascriptFunction(
209 L"printApp._printDataUrl", *print_data_, title);
210 }
211}
212
213
[email protected]a984bdf2011-03-15 20:17:16214CloudPrintFlowHandler::CloudPrintFlowHandler(const FilePath& path_to_file,
215 const string16& print_job_title,
216 const std::string& file_type)
217 : path_to_file_(path_to_file),
218 print_job_title_(print_job_title),
219 file_type_(file_type) {
[email protected]38e08982010-10-22 17:28:43220}
221
222CloudPrintFlowHandler::~CloudPrintFlowHandler() {
223 // This will also cancel any task in flight.
224 CancelAnyRunningTask();
225}
226
227
[email protected]73852b8f2010-05-14 00:38:12228void CloudPrintFlowHandler::SetDialogDelegate(
229 CloudPrintHtmlDialogDelegate* delegate) {
[email protected]7b748982011-02-14 19:28:23230 // Even if setting a new WebUI, it means any previous task needs
[email protected]73852b8f2010-05-14 00:38:12231 // to be cancelled, it's now invalid.
[email protected]ba4f1132010-10-09 02:02:35232 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12233 CancelAnyRunningTask();
234 dialog_delegate_ = delegate;
235}
236
237// Cancels any print data sender we have in flight and removes our
238// reference to it, so when the task that is calling it finishes and
239// removes it's reference, it goes away.
240void CloudPrintFlowHandler::CancelAnyRunningTask() {
[email protected]ba4f1132010-10-09 02:02:35241 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12242 if (print_data_sender_.get()) {
243 print_data_sender_->CancelPrintDataFile();
244 print_data_sender_ = NULL;
245 }
246}
247
[email protected]73852b8f2010-05-14 00:38:12248void CloudPrintFlowHandler::RegisterMessages() {
[email protected]7b748982011-02-14 19:28:23249 if (!web_ui_)
[email protected]73852b8f2010-05-14 00:38:12250 return;
251
252 // TODO(scottbyer) - This is where we will register messages for the
253 // UI JS to use. Needed: Call to update page setup parameters.
[email protected]7b748982011-02-14 19:28:23254 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12255 "ShowDebugger",
256 NewCallback(this, &CloudPrintFlowHandler::HandleShowDebugger));
[email protected]7b748982011-02-14 19:28:23257 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12258 "SendPrintData",
259 NewCallback(this, &CloudPrintFlowHandler::HandleSendPrintData));
[email protected]7b748982011-02-14 19:28:23260 web_ui_->RegisterMessageCallback(
[email protected]73852b8f2010-05-14 00:38:12261 "SetPageParameters",
262 NewCallback(this, &CloudPrintFlowHandler::HandleSetPageParameters));
263
[email protected]7b748982011-02-14 19:28:23264 if (web_ui_->tab_contents()) {
[email protected]73852b8f2010-05-14 00:38:12265 // Register for appropriate notifications, and re-direct the URL
266 // to the real server URL, now that we've gotten an HTML dialog
267 // going.
[email protected]7b748982011-02-14 19:28:23268 NavigationController* controller = &web_ui_->tab_contents()->controller();
[email protected]73852b8f2010-05-14 00:38:12269 NavigationEntry* pending_entry = controller->pending_entry();
270 if (pending_entry)
[email protected]2283eead2010-09-29 23:17:30271 pending_entry->set_url(CloudPrintURL(
[email protected]7b748982011-02-14 19:28:23272 web_ui_->GetProfile()).GetCloudPrintServiceDialogURL());
[email protected]73852b8f2010-05-14 00:38:12273 registrar_.Add(this, NotificationType::LOAD_STOP,
274 Source<NavigationController>(controller));
275 }
276}
277
278void CloudPrintFlowHandler::Observe(NotificationType type,
279 const NotificationSource& source,
280 const NotificationDetails& details) {
[email protected]20c52d22011-06-20 22:42:42281 if (type.value == NotificationType::LOAD_STOP) {
282 // Take the opportunity to set some (minimal) additional
283 // script permissions required for the web UI.
284 GURL url = web_ui_->tab_contents()->GetURL();
285 GURL dialog_url = CloudPrintURL(
286 web_ui_->GetProfile()).GetCloudPrintServiceDialogURL();
287 if (url.host() == dialog_url.host() &&
288 url.path() == dialog_url.path() &&
289 url.scheme() == dialog_url.scheme()) {
290 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
291 if (rvh && rvh->delegate()) {
292 WebPreferences webkit_prefs = rvh->delegate()->GetWebkitPrefs();
293 webkit_prefs.allow_scripts_to_close_windows = true;
294 rvh->Send(new ViewMsg_UpdateWebPreferences(
295 rvh->routing_id(), webkit_prefs));
296 } else {
297 DCHECK(false);
298 }
299 }
300
[email protected]73852b8f2010-05-14 00:38:12301 // Choose one or the other. If you need to debug, bring up the
302 // debugger. You can then use the various chrome.send()
303 // registrations above to kick of the various function calls,
304 // including chrome.send("SendPrintData") in the javaScript
305 // console and watch things happen with:
306 // HandleShowDebugger(NULL);
307 HandleSendPrintData(NULL);
308 }
309}
310
[email protected]88942a22010-08-19 20:34:43311void CloudPrintFlowHandler::HandleShowDebugger(const ListValue* args) {
[email protected]73852b8f2010-05-14 00:38:12312 ShowDebugger();
313}
314
315void CloudPrintFlowHandler::ShowDebugger() {
[email protected]7b748982011-02-14 19:28:23316 if (web_ui_) {
317 RenderViewHost* rvh = web_ui_->tab_contents()->render_view_host();
[email protected]73852b8f2010-05-14 00:38:12318 if (rvh)
319 DevToolsManager::GetInstance()->OpenDevToolsWindow(rvh);
320 }
321}
322
323scoped_refptr<CloudPrintDataSender>
324CloudPrintFlowHandler::CreateCloudPrintDataSender() {
[email protected]7b748982011-02-14 19:28:23325 DCHECK(web_ui_);
326 print_data_helper_.reset(new CloudPrintDataSenderHelper(web_ui_));
[email protected]a984bdf2011-03-15 20:17:16327 return new CloudPrintDataSender(print_data_helper_.get(),
328 print_job_title_,
329 file_type_);
[email protected]73852b8f2010-05-14 00:38:12330}
331
[email protected]88942a22010-08-19 20:34:43332void CloudPrintFlowHandler::HandleSendPrintData(const ListValue* args) {
[email protected]ba4f1132010-10-09 02:02:35333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12334 // This will cancel any ReadPrintDataFile() or SendPrintDataFile()
335 // requests in flight (this is anticipation of when setting page
336 // setup parameters becomes asynchronous and may be set while some
337 // data is in flight). Then we can clear out the print data.
338 CancelAnyRunningTask();
[email protected]7b748982011-02-14 19:28:23339 if (web_ui_) {
[email protected]73852b8f2010-05-14 00:38:12340 print_data_sender_ = CreateCloudPrintDataSender();
[email protected]ba4f1132010-10-09 02:02:35341 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
342 NewRunnableMethod(
343 print_data_sender_.get(),
344 &CloudPrintDataSender::ReadPrintDataFile,
[email protected]a984bdf2011-03-15 20:17:16345 path_to_file_));
[email protected]73852b8f2010-05-14 00:38:12346 }
347}
348
[email protected]88942a22010-08-19 20:34:43349void CloudPrintFlowHandler::HandleSetPageParameters(const ListValue* args) {
[email protected]036056a32011-03-03 21:05:01350 std::string json;
[email protected]e675f7b2011-06-22 17:32:12351 bool ret = args->GetString(0, &json);
352 if (!ret || json.empty()) {
[email protected]036056a32011-03-03 21:05:01353 NOTREACHED() << "Empty json string";
[email protected]73852b8f2010-05-14 00:38:12354 return;
[email protected]036056a32011-03-03 21:05:01355 }
[email protected]73852b8f2010-05-14 00:38:12356
357 // These are backstop default values - 72 dpi to match the screen,
358 // 8.5x11 inch paper with margins subtracted (1/4 inch top, left,
359 // right and 0.56 bottom), and the min page shrink and max page
360 // shrink values appear all over the place with no explanation.
361
362 // TODO(scottbyer): Get a Linux/ChromeOS edge for PrintSettings
363 // working so that we can get the default values from there. Fix up
364 // PrintWebViewHelper to do the same.
365 const int kDPI = 72;
366 const int kWidth = static_cast<int>((8.5-0.25-0.25)*kDPI);
367 const int kHeight = static_cast<int>((11-0.25-0.56)*kDPI);
368 const double kMinPageShrink = 1.25;
369 const double kMaxPageShrink = 2.0;
370
[email protected]1375e3ab2011-03-24 17:07:22371 PrintMsg_Print_Params default_settings;
[email protected]73852b8f2010-05-14 00:38:12372 default_settings.printable_size = gfx::Size(kWidth, kHeight);
373 default_settings.dpi = kDPI;
374 default_settings.min_shrink = kMinPageShrink;
375 default_settings.max_shrink = kMaxPageShrink;
376 default_settings.desired_dpi = kDPI;
377 default_settings.document_cookie = 0;
378 default_settings.selection_only = false;
379
380 if (!GetPageSetupParameters(json, default_settings)) {
381 NOTREACHED();
382 return;
383 }
384
385 // TODO(scottbyer) - Here is where we would kick the originating
386 // renderer thread with these new parameters in order to get it to
[email protected]a984bdf2011-03-15 20:17:16387 // re-generate the PDF data and hand it back to us. window.print() is
[email protected]73852b8f2010-05-14 00:38:12388 // currently synchronous, so there's a lot of work to do to get to
389 // that point.
390}
391
[email protected]ea161da2010-11-02 21:57:35392void CloudPrintFlowHandler::StoreDialogClientSize() const {
[email protected]7b748982011-02-14 19:28:23393 if (web_ui_ && web_ui_->tab_contents() && web_ui_->tab_contents()->view()) {
394 gfx::Size size = web_ui_->tab_contents()->view()->GetContainerSize();
395 web_ui_->GetProfile()->GetPrefs()->SetInteger(
[email protected]ea161da2010-11-02 21:57:35396 prefs::kCloudPrintDialogWidth, size.width());
[email protected]7b748982011-02-14 19:28:23397 web_ui_->GetProfile()->GetPrefs()->SetInteger(
[email protected]ea161da2010-11-02 21:57:35398 prefs::kCloudPrintDialogHeight, size.height());
399 }
400}
401
[email protected]73852b8f2010-05-14 00:38:12402CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16403 const FilePath& path_to_file,
[email protected]73852b8f2010-05-14 00:38:12404 int width, int height,
[email protected]9848c7e2010-06-03 16:06:56405 const std::string& json_arguments,
[email protected]e39027a2011-01-24 21:41:54406 const string16& print_job_title,
[email protected]a984bdf2011-03-15 20:17:16407 const std::string& file_type,
[email protected]e39027a2011-01-24 21:41:54408 bool modal)
[email protected]a984bdf2011-03-15 20:17:16409 : flow_handler_(new CloudPrintFlowHandler(path_to_file,
410 print_job_title,
411 file_type)),
[email protected]e39027a2011-01-24 21:41:54412 modal_(modal),
[email protected]6ddda232011-04-22 15:41:47413 owns_flow_handler_(true),
414 path_to_file_(path_to_file) {
[email protected]73852b8f2010-05-14 00:38:12415 Init(width, height, json_arguments);
416}
417
[email protected]05acb55472011-02-03 00:11:07418// For unit testing.
[email protected]73852b8f2010-05-14 00:38:12419CloudPrintHtmlDialogDelegate::CloudPrintHtmlDialogDelegate(
420 CloudPrintFlowHandler* flow_handler,
421 int width, int height,
[email protected]e39027a2011-01-24 21:41:54422 const std::string& json_arguments,
423 bool modal)
[email protected]73852b8f2010-05-14 00:38:12424 : flow_handler_(flow_handler),
[email protected]e39027a2011-01-24 21:41:54425 modal_(modal),
[email protected]18137e02010-05-25 21:10:35426 owns_flow_handler_(true) {
[email protected]73852b8f2010-05-14 00:38:12427 Init(width, height, json_arguments);
428}
429
[email protected]05acb55472011-02-03 00:11:07430void CloudPrintHtmlDialogDelegate::Init(int width, int height,
431 const std::string& json_arguments) {
[email protected]73852b8f2010-05-14 00:38:12432 // This information is needed to show the dialog HTML content.
[email protected]ba4f1132010-10-09 02:02:35433 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]89f550b2011-06-08 18:34:03434 params_.url = GURL(chrome::kChromeUICloudPrintResourcesURL);
[email protected]73852b8f2010-05-14 00:38:12435 params_.height = height;
436 params_.width = width;
437 params_.json_input = json_arguments;
438
439 flow_handler_->SetDialogDelegate(this);
[email protected]e39027a2011-01-24 21:41:54440 // If we're not modal we can show the dialog with no browser.
441 // We need this to keep Chrome alive while our dialog is up.
442 if (!modal_)
443 BrowserList::StartKeepAlive();
[email protected]73852b8f2010-05-14 00:38:12444}
445
446CloudPrintHtmlDialogDelegate::~CloudPrintHtmlDialogDelegate() {
447 // If the flow_handler_ is about to outlive us because we don't own
448 // it anymore, we need to have it remove it's reference to us.
[email protected]ba4f1132010-10-09 02:02:35449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]73852b8f2010-05-14 00:38:12450 flow_handler_->SetDialogDelegate(NULL);
451 if (owns_flow_handler_) {
452 delete flow_handler_;
453 }
454}
455
456bool CloudPrintHtmlDialogDelegate::IsDialogModal() const {
[email protected]e39027a2011-01-24 21:41:54457 return modal_;
[email protected]73852b8f2010-05-14 00:38:12458}
459
460std::wstring CloudPrintHtmlDialogDelegate::GetDialogTitle() const {
[email protected]be559e442010-11-02 20:37:32461 return std::wstring();
[email protected]73852b8f2010-05-14 00:38:12462}
463
464GURL CloudPrintHtmlDialogDelegate::GetDialogContentURL() const {
465 return params_.url;
466}
467
[email protected]36e12172011-02-08 23:46:02468void CloudPrintHtmlDialogDelegate::GetWebUIMessageHandlers(
469 std::vector<WebUIMessageHandler*>* handlers) const {
[email protected]73852b8f2010-05-14 00:38:12470 handlers->push_back(flow_handler_);
471 // We don't own flow_handler_ anymore, but it sticks around until at
472 // least right after OnDialogClosed() is called (and this object is
473 // destroyed).
474 owns_flow_handler_ = false;
475}
476
477void CloudPrintHtmlDialogDelegate::GetDialogSize(gfx::Size* size) const {
478 size->set_width(params_.width);
479 size->set_height(params_.height);
480}
481
482std::string CloudPrintHtmlDialogDelegate::GetDialogArgs() const {
483 return params_.json_input;
484}
485
486void CloudPrintHtmlDialogDelegate::OnDialogClosed(
487 const std::string& json_retval) {
[email protected]ea161da2010-11-02 21:57:35488 // Get the final dialog size and store it.
489 flow_handler_->StoreDialogClientSize();
[email protected]6ddda232011-04-22 15:41:47490
491 if (CommandLine::ForCurrentProcess()->HasSwitch(
492 switches::kCloudPrintDeleteFile)) {
493 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
494 NewRunnableFunction(&internal_cloud_print_helpers::Delete,
495 path_to_file_));
496 }
497
[email protected]e39027a2011-01-24 21:41:54498 // If we're modal we can show the dialog with no browser.
499 // End the keep-alive so that Chrome can exit.
500 if (!modal_)
501 BrowserList::EndKeepAlive();
[email protected]73852b8f2010-05-14 00:38:12502 delete this;
503}
504
[email protected]18137e02010-05-25 21:10:35505void CloudPrintHtmlDialogDelegate::OnCloseContents(TabContents* source,
506 bool* out_close_dialog) {
507 if (out_close_dialog)
508 *out_close_dialog = true;
509}
510
[email protected]ea161da2010-11-02 21:57:35511bool CloudPrintHtmlDialogDelegate::ShouldShowDialogTitle() const {
512 return false;
513}
514
[email protected]34478212011-04-19 01:35:46515bool CloudPrintHtmlDialogDelegate::HandleContextMenu(
516 const ContextMenuParams& params) {
517 return true;
518}
519
[email protected]6085c70d2011-03-22 22:51:07520// Called from the UI thread, starts up the dialog.
521void CreateDialogImpl(const FilePath& path_to_file,
522 const string16& print_job_title,
523 const std::string& file_type,
524 bool modal) {
[email protected]ba4f1132010-10-09 02:02:35525 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
[email protected]6085c70d2011-03-22 22:51:07526 Browser* browser = BrowserList::GetLastActive();
[email protected]73852b8f2010-05-14 00:38:12527
[email protected]ea161da2010-11-02 21:57:35528 const int kDefaultWidth = 497;
529 const int kDefaultHeight = 332;
[email protected]05acb55472011-02-03 00:11:07530 string16 job_title = print_job_title;
[email protected]e39027a2011-01-24 21:41:54531 Profile* profile = NULL;
[email protected]05acb55472011-02-03 00:11:07532 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07533 DCHECK(browser);
534 if (job_title.empty() && browser->GetSelectedTabContents())
535 job_title = browser->GetSelectedTabContents()->GetTitle();
536 profile = browser->GetProfile();
[email protected]e39027a2011-01-24 21:41:54537 } else {
538 profile = ProfileManager::GetDefaultProfile();
539 }
540 DCHECK(profile);
[email protected]05acb55472011-02-03 00:11:07541 PrefService* pref_service = profile->GetPrefs();
[email protected]ea161da2010-11-02 21:57:35542 DCHECK(pref_service);
543 if (!pref_service->FindPreference(prefs::kCloudPrintDialogWidth)) {
544 pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogWidth,
[email protected]d36f941b2011-05-09 06:19:16545 kDefaultWidth,
546 PrefService::UNSYNCABLE_PREF);
[email protected]ea161da2010-11-02 21:57:35547 }
548 if (!pref_service->FindPreference(prefs::kCloudPrintDialogHeight)) {
549 pref_service->RegisterIntegerPref(prefs::kCloudPrintDialogHeight,
[email protected]d36f941b2011-05-09 06:19:16550 kDefaultHeight,
551 PrefService::UNSYNCABLE_PREF);
[email protected]ea161da2010-11-02 21:57:35552 }
553
554 int width = pref_service->GetInteger(prefs::kCloudPrintDialogWidth);
555 int height = pref_service->GetInteger(prefs::kCloudPrintDialogHeight);
[email protected]e39027a2011-01-24 21:41:54556
[email protected]73852b8f2010-05-14 00:38:12557 HtmlDialogUIDelegate* dialog_delegate =
558 new internal_cloud_print_helpers::CloudPrintHtmlDialogDelegate(
[email protected]a984bdf2011-03-15 20:17:16559 path_to_file, width, height, std::string(), job_title, file_type,
560 modal);
[email protected]05acb55472011-02-03 00:11:07561 if (modal) {
[email protected]6085c70d2011-03-22 22:51:07562 DCHECK(browser);
563 browser->BrowserShowHtmlDialog(dialog_delegate, NULL);
[email protected]e39027a2011-01-24 21:41:54564 } else {
[email protected]eb2d7902011-02-02 18:19:56565 browser::ShowHtmlDialog(NULL, profile, dialog_delegate);
[email protected]e39027a2011-01-24 21:41:54566 }
[email protected]73852b8f2010-05-14 00:38:12567}
[email protected]6085c70d2011-03-22 22:51:07568
[email protected]6ddda232011-04-22 15:41:47569// Provides a runnable function to delete a file.
570void Delete(const FilePath& file_path) {
571 file_util::Delete(file_path, false);
572}
573
[email protected]6085c70d2011-03-22 22:51:07574} // namespace internal_cloud_print_helpers
575
576namespace print_dialog_cloud {
577
578// Called on the FILE or UI thread. This is the main entry point into creating
579// the dialog.
580
581// TODO(scottbyer): The signature here will need to change as the
582// workflow through the printing code changes to allow for dynamically
583// changing page setup parameters while the dialog is active.
584void CreatePrintDialogForFile(const FilePath& path_to_file,
585 const string16& print_job_title,
586 const std::string& file_type,
587 bool modal) {
588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE) ||
589 BrowserThread::CurrentlyOn(BrowserThread::UI));
590
591 BrowserThread::PostTask(
592 BrowserThread::UI, FROM_HERE,
593 NewRunnableFunction(&internal_cloud_print_helpers::CreateDialogImpl,
594 path_to_file,
595 print_job_title,
596 file_type,
597 modal));
598}
599
[email protected]65c9d89a2011-04-13 21:02:39600bool CreatePrintDialogFromCommandLine(const CommandLine& command_line) {
601 if (!command_line.GetSwitchValuePath(switches::kCloudPrintFile).empty()) {
602 FilePath cloud_print_file;
603 cloud_print_file =
604 command_line.GetSwitchValuePath(switches::kCloudPrintFile);
605 if (!cloud_print_file.empty()) {
606 string16 print_job_title;
607 if (command_line.HasSwitch(switches::kCloudPrintJobTitle)) {
608#ifdef OS_WIN
609 CommandLine::StringType native_job_title;
610 native_job_title = command_line.GetSwitchValueNative(
611 switches::kCloudPrintJobTitle);
612 print_job_title = string16(native_job_title);
613#elif defined(OS_POSIX)
[email protected]4b8852a2011-06-10 17:24:46614 // POSIX Command line string types are different.
615 CommandLine::StringType native_job_title;
616 native_job_title = command_line.GetSwitchValueASCII(
617 switches::kCloudPrintJobTitle);
618 // Convert the ASCII string to UTF16 to prepare to pass.
619 print_job_title = string16(ASCIIToUTF16(native_job_title));
[email protected]65c9d89a2011-04-13 21:02:39620#endif
621 }
622 std::string file_type = "application/pdf";
623 if (command_line.HasSwitch(switches::kCloudPrintFileType)) {
624 file_type = command_line.GetSwitchValueASCII(
625 switches::kCloudPrintFileType);
626 }
627 print_dialog_cloud::CreatePrintDialogForFile(cloud_print_file,
628 print_job_title,
629 file_type,
630 false);
631 return true;
632 }
633 }
634 return false;
635}
636
[email protected]6085c70d2011-03-22 22:51:07637} // end namespace