Index: chrome/browser/ui/webui/print_preview/print_preview_handler.cc |
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc |
index b4ceb816e49a79177a1e882ae57422e66f952db4..0b4026f3e877846b7b8abade6890c03b48f80be7 100644 |
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc |
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc |
@@ -202,15 +202,10 @@ const char kLocalPdfPrinterId[] = "Save as PDF"; |
// Timeout for searching for privet printers, in seconds. |
const int kPrivetTimeoutSec = 5; |
-// Get the print job settings dictionary from |args|. The caller takes |
-// ownership of the returned DictionaryValue. Returns NULL on failure. |
+// Get the print job settings dictionary from |json_str|. Returns NULL on |
+// failure. |
std::unique_ptr<base::DictionaryValue> GetSettingsDictionary( |
- const base::ListValue* args) { |
- std::string json_str; |
- if (!args->GetString(0, &json_str)) { |
- NOTREACHED() << "Could not read JSON argument"; |
- return NULL; |
- } |
+ const std::string& json_str) { |
if (json_str.empty()) { |
NOTREACHED() << "Empty print job settings"; |
return NULL; |
@@ -688,8 +683,8 @@ void PrintPreviewHandler::HandleGetPrivetPrinters(const base::ListValue* args) { |
using local_discovery::ServiceDiscoverySharedClient; |
scoped_refptr<ServiceDiscoverySharedClient> service_discovery = |
ServiceDiscoverySharedClient::GetInstance(); |
- DCHECK(privet_callback_id_.empty()); |
- privet_callback_id_ = callback_id; |
+ DCHECK(privet_search_callback_id_.empty()); |
+ privet_search_callback_id_ = callback_id; |
StartPrivetLister(service_discovery); |
#endif |
} |
@@ -700,8 +695,9 @@ void PrintPreviewHandler::StopPrivetLister() { |
if (PrivetPrintingEnabled() && printer_lister_) { |
printer_lister_->Stop(); |
} |
- ResolveJavascriptCallback(base::Value(privet_callback_id_), base::Value()); |
- privet_callback_id_ = ""; |
+ ResolveJavascriptCallback(base::Value(privet_search_callback_id_), |
+ base::Value()); |
+ privet_search_callback_id_.clear(); |
#endif |
} |
@@ -776,7 +772,11 @@ void PrintPreviewHandler::HandleGetExtensionPrinterCapabilities( |
void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) { |
DCHECK_EQ(2U, args->GetSize()); |
- std::unique_ptr<base::DictionaryValue> settings = GetSettingsDictionary(args); |
+ std::string json_str; |
+ if (!args->GetString(0, &json_str)) |
+ return; |
+ std::unique_ptr<base::DictionaryValue> settings = |
+ GetSettingsDictionary(json_str); |
if (!settings) |
return; |
int request_id = -1; |
@@ -862,9 +862,19 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
UMA_HISTOGRAM_COUNTS("PrintPreview.RegeneratePreviewRequest.BeforePrint", |
regenerate_preview_request_count_); |
- std::unique_ptr<base::DictionaryValue> settings = GetSettingsDictionary(args); |
+ AllowJavascript(); |
+ |
+ std::string callback_id; |
+ CHECK(args->GetString(0, &callback_id)); |
+ CHECK(!callback_id.empty()); |
+ std::string json_str; |
+ if (!args->GetString(1, &json_str)) |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); |
Lei Zhang
2017/07/11 05:11:10
Wait, don't we need to return after a failure like
rbpotter
2017/07/11 16:35:50
Yes for the case below. Should probably just crash
|
+ |
+ std::unique_ptr<base::DictionaryValue> settings = |
+ GetSettingsDictionary(json_str); |
if (!settings) |
- return; |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); |
ReportPrintSettingsStats(*settings); |
@@ -896,6 +906,8 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
if (print_to_pdf) { |
UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPDF", page_count); |
ReportUserActionHistogram(PRINT_TO_PDF); |
+ DCHECK(pdf_callback_id_.empty()); |
+ pdf_callback_id_ = callback_id; |
PrintToPdf(); |
return; |
} |
@@ -917,12 +929,14 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
!settings->GetInteger(printing::kSettingPageHeight, &height) || |
width <= 0 || height <= 0) { |
NOTREACHED(); |
- FireWebUIListener("print-failed", base::Value(-1)); |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value(-1)); |
return; |
} |
- PrintToPrivetPrinter( |
- printer_name, print_ticket, capabilities, gfx::Size(width, height)); |
+ DCHECK(privet_print_callback_id_.empty()); |
+ privet_print_callback_id_ = callback_id; |
+ PrintToPrivetPrinter(callback_id, printer_name, print_ticket, capabilities, |
+ gfx::Size(width, height)); |
return; |
} |
#endif |
@@ -944,7 +958,7 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
!settings->GetInteger(printing::kSettingPageHeight, &height) || |
width <= 0 || height <= 0) { |
NOTREACHED(); |
- OnExtensionPrintResult(false, "FAILED"); |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value("FAILED")); |
return; |
} |
@@ -952,7 +966,8 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
scoped_refptr<base::RefCountedBytes> data; |
if (!GetPreviewDataAndTitle(&data, &title)) { |
LOG(ERROR) << "Nothing to print; no preview available."; |
- OnExtensionPrintResult(false, "NO_DATA"); |
+ RejectJavascriptCallback(base::Value(callback_id), |
+ base::Value("NO_DATA")); |
return; |
} |
@@ -961,7 +976,7 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
destination_id, capabilities, title, print_ticket, |
gfx::Size(width, height), data, |
base::Bind(&PrintPreviewHandler::OnExtensionPrintResult, |
- weak_factory_.GetWeakPtr())); |
+ weak_factory_.GetWeakPtr(), callback_id)); |
return; |
} |
@@ -969,6 +984,7 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
base::string16 title; |
if (!GetPreviewDataAndTitle(&data, &title)) { |
// Nothing to print, no preview available. |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value()); |
return; |
} |
@@ -976,7 +992,7 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToCloudPrint", |
page_count); |
ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT); |
- SendCloudPrintJob(data.get()); |
+ SendCloudPrintJob(callback_id, data.get()); |
return; |
} |
@@ -991,13 +1007,6 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
ReportUserActionHistogram(PRINT_TO_PRINTER); |
} |
- // This tries to activate the initiator as well, so do not clear the |
- // association with the initiator yet. |
- print_preview_ui()->OnHidePreviewDialog(); |
- |
- // Grab the current initiator before calling ClearInitiatorDetails() below. |
- // Otherwise calling GetInitiator() later will return the wrong WebContents. |
- // https://crbug.com/407080 |
WebContents* initiator = GetInitiator(); |
if (initiator) { |
// Save initiator IDs. PrintMsg_PrintForPrintPreview below should cause |
@@ -1010,24 +1019,24 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
main_render_frame->GetRoutingID()); |
} |
- // Do this so the initiator can open a new print preview dialog, while the |
- // current print preview dialog is still handling its print job. |
- ClearInitiatorDetails(); |
- |
// Set ID to know whether printing is for preview. |
settings->SetInteger(printing::kPreviewUIID, |
print_preview_ui()->GetIDForPrintPreviewUI()); |
RenderFrameHost* rfh = preview_web_contents()->GetMainFrame(); |
rfh->Send(new PrintMsg_PrintForPrintPreview(rfh->GetRoutingID(), *settings)); |
- // For all other cases above, the preview dialog will stay open until the |
- // printing has finished. Then the dialog closes and PrintPreviewDone() gets |
- // called. In the case below, since the preview dialog will be hidden and |
- // not closed, we need to make this call. |
- if (initiator) { |
- auto* print_view_manager = PrintViewManager::FromWebContents(initiator); |
- print_view_manager->PrintPreviewDone(); |
- } |
+ // Set this so when print preview sends "hidePreviewDialog" we clear the |
+ // initiator and call PrintPreviewDone(). In the cases above, the preview |
+ // dialog stays open until printing is finished and we do this when the |
+ // dialog is closed. In this case, we set this so that these tasks are |
+ // done in HandleHidePreview(). |
+ printing_started_ = true; |
+ |
+ // This will ultimately try to activate the initiator as well, so do not |
+ // clear the association with the initiator until "hidePreviewDialog" is |
+ // received from JS. |
+ ResolveJavascriptCallback(base::Value(callback_id), base::Value()); |
+ |
#else |
NOTREACHED(); |
#endif // BUILDFLAG(ENABLE_BASIC_PRINTING) |
@@ -1036,6 +1045,8 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) { |
void PrintPreviewHandler::PrintToPdf() { |
if (!print_to_pdf_path_.empty()) { |
// User has already selected a path, no need to show the dialog again. |
+ ResolveJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); |
+ pdf_callback_id_.clear(); |
PostPrintToPdfTask(); |
} else if (!select_file_dialog_.get() || |
!select_file_dialog_->IsRunning(platform_util::GetTopLevel( |
@@ -1063,6 +1074,24 @@ void PrintPreviewHandler::PrintToPdf() { |
} |
void PrintPreviewHandler::HandleHidePreview(const base::ListValue* /*args*/) { |
+ if (printing_started_) { |
+ // Printing has started, so clear the initiator so that it can open a new |
+ // print preview dialog, while the current print preview dialog is still |
+ // handling its print job. |
+ WebContents* initiator = GetInitiator(); |
+ ClearInitiatorDetails(); |
+ |
+ // Since the preview dialog will be hidden and not closed, we need to make |
+ // this call. |
+ if (initiator) { |
+ auto* print_view_manager = PrintViewManager::FromWebContents(initiator); |
+ print_view_manager->PrintPreviewDone(); |
+ } |
+ |
+ // Since the initiator is cleared, only want to do this once. |
+ printing_started_ = false; |
+ } |
+ |
print_preview_ui()->OnHidePreviewDialog(); |
} |
@@ -1394,15 +1423,15 @@ void PrintPreviewHandler::SendCloudPrintEnabled() { |
} |
} |
-void PrintPreviewHandler::SendCloudPrintJob(const base::RefCountedBytes* data) { |
+void PrintPreviewHandler::SendCloudPrintJob(const std::string& callback_id, |
+ const base::RefCountedBytes* data) { |
// BASE64 encode the job data. |
const base::StringPiece raw_data(reinterpret_cast<const char*>(data->front()), |
data->size()); |
std::string base64_data; |
base::Base64Encode(raw_data, &base64_data); |
- base::Value data_value(base64_data); |
- web_ui()->CallJavascriptFunctionUnsafe("printToCloud", data_value); |
+ ResolveJavascriptCallback(base::Value(callback_id), base::Value(base64_data)); |
} |
WebContents* PrintPreviewHandler::GetInitiator() const { |
@@ -1425,7 +1454,9 @@ void PrintPreviewHandler::SelectFile(const base::FilePath& default_filename, |
ChromeSelectFilePolicy policy(GetInitiator()); |
if (!policy.CanOpenSelectFileDialog()) { |
policy.SelectFileDenied(); |
- return ClosePreviewDialog(); |
+ RejectJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); |
+ pdf_callback_id_.clear(); |
+ return; |
} |
} |
@@ -1494,7 +1525,8 @@ void PrintPreviewHandler::FileSelected(const base::FilePath& path, |
sticky_settings->SaveInPrefs( |
Profile::FromBrowserContext(preview_web_contents()->GetBrowserContext()) |
->GetPrefs()); |
- web_ui()->CallJavascriptFunctionUnsafe("fileSelectionCompleted"); |
+ ResolveJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); |
+ pdf_callback_id_.clear(); |
print_to_pdf_path_ = path; |
PostPrintToPdfTask(); |
} |
@@ -1516,7 +1548,8 @@ void PrintPreviewHandler::PostPrintToPdfTask() { |
} |
void PrintPreviewHandler::FileSelectionCanceled(void* params) { |
- print_preview_ui()->OnFileSelectionCancelled(); |
+ RejectJavascriptCallback(base::Value(pdf_callback_id_), base::Value()); |
+ pdf_callback_id_.clear(); |
} |
void PrintPreviewHandler::ClearInitiatorDetails() { |
@@ -1604,13 +1637,10 @@ bool PrintPreviewHandler::PrivetUpdateClient( |
const std::string& callback_id, |
std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { |
if (!http_client) { |
- if (callback_id.empty()) { |
- // This was an attempt to print to a privet printer and has failed. |
- FireWebUIListener("print-failed", base::Value(-1)); |
- } else { // Capabilities update failed |
- RejectJavascriptCallback(base::Value(callback_id), base::Value()); |
- } |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value()); |
privet_http_resolution_.reset(); |
+ if (callback_id == privet_print_callback_id_) |
+ privet_print_callback_id_.clear(); |
return false; |
} |
@@ -1625,11 +1655,12 @@ bool PrintPreviewHandler::PrivetUpdateClient( |
} |
void PrintPreviewHandler::PrivetLocalPrintUpdateClient( |
+ const std::string& callback_id, |
std::string print_ticket, |
std::string capabilities, |
gfx::Size page_size, |
std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { |
- if (!PrivetUpdateClient("", std::move(http_client))) |
+ if (!PrivetUpdateClient(callback_id, std::move(http_client))) |
return; |
StartPrivetLocalPrint(print_ticket, capabilities, page_size); |
@@ -1648,7 +1679,9 @@ void PrintPreviewHandler::StartPrivetLocalPrint(const std::string& print_ticket, |
base::string16 title; |
if (!GetPreviewDataAndTitle(&data, &title)) { |
- FireWebUIListener("print-failed", base::Value(-1)); |
+ RejectJavascriptCallback(base::Value(privet_print_callback_id_), |
+ base::Value(-1)); |
+ privet_print_callback_id_.clear(); |
return; |
} |
@@ -1701,16 +1734,19 @@ void PrintPreviewHandler::OnPrivetCapabilities( |
privet_capabilities_operation_.reset(); |
} |
-void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& device_name, |
+void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& callback_id, |
+ const std::string& device_name, |
const std::string& ticket, |
const std::string& capabilities, |
const gfx::Size& page_size) { |
if (!CreatePrivetHTTP( |
device_name, |
base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient, |
- weak_factory_.GetWeakPtr(), ticket, capabilities, |
- page_size))) { |
- FireWebUIListener("print-failed", base::Value(-1)); |
+ weak_factory_.GetWeakPtr(), callback_id, ticket, |
+ capabilities, page_size))) { |
+ RejectJavascriptCallback(base::Value(privet_print_callback_id_), |
+ base::Value(-1)); |
+ privet_print_callback_id_.clear(); |
} |
} |
@@ -1735,13 +1771,17 @@ bool PrintPreviewHandler::CreatePrivetHTTP( |
void PrintPreviewHandler::OnPrivetPrintingDone( |
const cloud_print::PrivetLocalPrintOperation* print_operation) { |
- ClosePreviewDialog(); |
+ ResolveJavascriptCallback(base::Value(privet_print_callback_id_), |
+ base::Value()); |
+ privet_print_callback_id_.clear(); |
} |
void PrintPreviewHandler::OnPrivetPrintingError( |
const cloud_print::PrivetLocalPrintOperation* print_operation, |
int http_code) { |
- FireWebUIListener("print-failed", base::Value(http_code)); |
+ RejectJavascriptCallback(base::Value(privet_print_callback_id_), |
+ base::Value(http_code)); |
+ privet_print_callback_id_.clear(); |
} |
void PrintPreviewHandler::FillPrinterDescription( |
@@ -1805,13 +1845,14 @@ void PrintPreviewHandler::OnGotExtensionPrinterCapabilities( |
ResolveJavascriptCallback(base::Value(callback_id), capabilities); |
} |
-void PrintPreviewHandler::OnExtensionPrintResult(bool success, |
+void PrintPreviewHandler::OnExtensionPrintResult(const std::string& callback_id, |
+ bool success, |
const std::string& status) { |
if (success) { |
- ClosePreviewDialog(); |
+ ResolveJavascriptCallback(base::Value(callback_id), base::Value()); |
return; |
} |
- FireWebUIListener("print-failed", base::Value(status)); |
+ RejectJavascriptCallback(base::Value(callback_id), base::Value(status)); |
} |
void PrintPreviewHandler::RegisterForGaiaCookieChanges() { |