| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" | 5 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" |
| 6 | 6 |
| 7 #include <ctype.h> | 7 #include <ctype.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 | 9 |
| 10 #include <map> | 10 #include <map> |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 #include "chrome/browser/profiles/profile.h" | 43 #include "chrome/browser/profiles/profile.h" |
| 44 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" | 44 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" |
| 45 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" | 45 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" |
| 46 #include "chrome/browser/signin/signin_manager_factory.h" | 46 #include "chrome/browser/signin/signin_manager_factory.h" |
| 47 #include "chrome/browser/ui/browser_finder.h" | 47 #include "chrome/browser/ui/browser_finder.h" |
| 48 #include "chrome/browser/ui/browser_tabstrip.h" | 48 #include "chrome/browser/ui/browser_tabstrip.h" |
| 49 #include "chrome/browser/ui/chrome_select_file_policy.h" | 49 #include "chrome/browser/ui/chrome_select_file_policy.h" |
| 50 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" | 50 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" |
| 51 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" | 51 #include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" |
| 52 #include "chrome/browser/ui/webui/print_preview/printer_backend_proxy.h" | 52 #include "chrome/browser/ui/webui/print_preview/printer_backend_proxy.h" |
| 53 #include "chrome/browser/ui/webui/print_preview/printer_capabilities.h" |
| 53 #include "chrome/browser/ui/webui/print_preview/printer_handler.h" | 54 #include "chrome/browser/ui/webui/print_preview/printer_handler.h" |
| 54 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h" | 55 #include "chrome/browser/ui/webui/print_preview/sticky_settings.h" |
| 55 #include "chrome/common/chrome_switches.h" | 56 #include "chrome/common/chrome_switches.h" |
| 56 #include "chrome/common/cloud_print/cloud_print_cdd_conversion.h" | 57 #include "chrome/common/cloud_print/cloud_print_cdd_conversion.h" |
| 57 #include "chrome/common/cloud_print/cloud_print_constants.h" | 58 #include "chrome/common/cloud_print/cloud_print_constants.h" |
| 58 #include "chrome/common/crash_keys.h" | 59 #include "chrome/common/crash_keys.h" |
| 59 #include "chrome/common/features.h" | 60 #include "chrome/common/features.h" |
| 60 #include "chrome/common/pref_names.h" | 61 #include "chrome/common/pref_names.h" |
| 61 #include "components/cloud_devices/common/cloud_device_description.h" | 62 #include "components/cloud_devices/common/cloud_device_description.h" |
| 62 #include "components/cloud_devices/common/cloud_devices_urls.h" | 63 #include "components/cloud_devices/common/cloud_devices_urls.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 80 #include "printing/backend/print_backend.h" | 81 #include "printing/backend/print_backend.h" |
| 81 #include "printing/backend/print_backend_consts.h" | 82 #include "printing/backend/print_backend_consts.h" |
| 82 #include "printing/features/features.h" | 83 #include "printing/features/features.h" |
| 83 #include "printing/pdf_render_settings.h" | 84 #include "printing/pdf_render_settings.h" |
| 84 #include "printing/print_settings.h" | 85 #include "printing/print_settings.h" |
| 85 #include "printing/printing_context.h" | 86 #include "printing/printing_context.h" |
| 86 #include "printing/units.h" | 87 #include "printing/units.h" |
| 87 #include "third_party/icu/source/i18n/unicode/ulocdata.h" | 88 #include "third_party/icu/source/i18n/unicode/ulocdata.h" |
| 88 | 89 |
| 89 #if defined(OS_CHROMEOS) | 90 #if defined(OS_CHROMEOS) |
| 91 #include "chrome/browser/chromeos/printing/printer_pref_manager.h" |
| 92 #include "chrome/browser/chromeos/printing/printer_pref_manager_factory.h" |
| 90 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" | 93 #include "chrome/browser/chromeos/settings/device_oauth2_token_service.h" |
| 91 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
" | 94 #include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h
" |
| 92 #include "chrome/common/url_constants.h" | 95 #include "chrome/common/url_constants.h" |
| 96 #include "chromeos/printing/printer_configuration.h" |
| 93 #endif | 97 #endif |
| 94 | 98 |
| 95 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) | 99 #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) |
| 96 #include "chrome/browser/printing/cloud_print/privet_constants.h" | 100 #include "chrome/browser/printing/cloud_print/privet_constants.h" |
| 97 #endif | 101 #endif |
| 98 | 102 |
| 99 using content::BrowserThread; | 103 using content::BrowserThread; |
| 100 using content::RenderViewHost; | 104 using content::RenderViewHost; |
| 101 using content::WebContents; | 105 using content::WebContents; |
| 102 | 106 |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 const char kCloudPrintUrl[] = "cloudPrintUrl"; | 172 const char kCloudPrintUrl[] = "cloudPrintUrl"; |
| 169 // Name of a dictionary field holding the state of selection for document. | 173 // Name of a dictionary field holding the state of selection for document. |
| 170 const char kDocumentHasSelection[] = "documentHasSelection"; | 174 const char kDocumentHasSelection[] = "documentHasSelection"; |
| 171 // Dictionary field holding the default destination selection rules. | 175 // Dictionary field holding the default destination selection rules. |
| 172 const char kDefaultDestinationSelectionRules[] = | 176 const char kDefaultDestinationSelectionRules[] = |
| 173 "defaultDestinationSelectionRules"; | 177 "defaultDestinationSelectionRules"; |
| 174 | 178 |
| 175 // Id of the predefined PDF printer. | 179 // Id of the predefined PDF printer. |
| 176 const char kLocalPdfPrinterId[] = "Save as PDF"; | 180 const char kLocalPdfPrinterId[] = "Save as PDF"; |
| 177 | 181 |
| 178 // Additional printer capability setting keys. | |
| 179 const char kPrinterId[] = "printerId"; | |
| 180 const char kPrinterCapabilities[] = "capabilities"; | |
| 181 | |
| 182 // Get the print job settings dictionary from |args|. The caller takes | 182 // Get the print job settings dictionary from |args|. The caller takes |
| 183 // ownership of the returned DictionaryValue. Returns NULL on failure. | 183 // ownership of the returned DictionaryValue. Returns NULL on failure. |
| 184 std::unique_ptr<base::DictionaryValue> GetSettingsDictionary( | 184 std::unique_ptr<base::DictionaryValue> GetSettingsDictionary( |
| 185 const base::ListValue* args) { | 185 const base::ListValue* args) { |
| 186 std::string json_str; | 186 std::string json_str; |
| 187 if (!args->GetString(0, &json_str)) { | 187 if (!args->GetString(0, &json_str)) { |
| 188 NOTREACHED() << "Could not read JSON argument"; | 188 NOTREACHED() << "Could not read JSON argument"; |
| 189 return NULL; | 189 return NULL; |
| 190 } | 190 } |
| 191 if (json_str.empty()) { | 191 if (json_str.empty()) { |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 for (size_t i = 0; i < arraysize(kPdfMedia); ++i) { | 366 for (size_t i = 0; i < arraysize(kPdfMedia); ++i) { |
| 367 Media media_option(kPdfMedia[i]); | 367 Media media_option(kPdfMedia[i]); |
| 368 media.AddDefaultOption(media_option, | 368 media.AddDefaultOption(media_option, |
| 369 default_media.type == media_option.type); | 369 default_media.type == media_option.type); |
| 370 } | 370 } |
| 371 media.SaveTo(&description); | 371 media.SaveTo(&description); |
| 372 | 372 |
| 373 return std::unique_ptr<base::DictionaryValue>(description.root().DeepCopy()); | 373 return std::unique_ptr<base::DictionaryValue>(description.root().DeepCopy()); |
| 374 } | 374 } |
| 375 | 375 |
| 376 std::pair<std::string, std::string> GetPrinterNameAndDescription( | |
| 377 const printing::PrinterBasicInfo& printer) { | |
| 378 #if defined(OS_MACOSX) || defined(OS_CHROMEOS) | |
| 379 // On Mac, |printer.printer_description| specifies the printer name and | |
| 380 // |printer.printer_name| specifies the device name / printer queue name. | |
| 381 // Chrome OS emulates the Mac behavior. | |
| 382 const std::string& real_name = printer.printer_description; | |
| 383 std::string real_description; | |
| 384 const auto it = printer.options.find(kDriverNameTagName); | |
| 385 if (it != printer.options.end()) | |
| 386 real_description = it->second; | |
| 387 return std::make_pair(real_name, real_description); | |
| 388 #else | |
| 389 return std::make_pair(printer.printer_name, printer.printer_description); | |
| 390 #endif | |
| 391 } | |
| 392 | |
| 393 void PrintersToValues(const printing::PrinterList& printer_list, | 376 void PrintersToValues(const printing::PrinterList& printer_list, |
| 394 base::ListValue* printers) { | 377 base::ListValue* printers) { |
| 395 for (const printing::PrinterBasicInfo& printer : printer_list) { | 378 for (const printing::PrinterBasicInfo& printer : printer_list) { |
| 396 std::unique_ptr<base::DictionaryValue> printer_info( | 379 std::unique_ptr<base::DictionaryValue> printer_info = |
| 397 new base::DictionaryValue); | 380 base::MakeUnique<base::DictionaryValue>(); |
| 398 const auto printer_name_description = GetPrinterNameAndDescription(printer); | 381 printer_info->SetString(printing::kSettingDeviceName, printer.printer_name); |
| 382 |
| 383 const auto printer_name_description = |
| 384 printing::GetPrinterNameAndDescription(printer); |
| 399 const std::string& printer_name = printer_name_description.first; | 385 const std::string& printer_name = printer_name_description.first; |
| 400 const std::string& printer_description = printer_name_description.second; | 386 const std::string& printer_description = printer_name_description.second; |
| 401 printer_info->SetString(printing::kSettingDeviceName, printer.printer_name); | |
| 402 printer_info->SetString(printing::kSettingPrinterName, printer_name); | 387 printer_info->SetString(printing::kSettingPrinterName, printer_name); |
| 403 printer_info->SetString(printing::kSettingPrinterDescription, | 388 printer_info->SetString(printing::kSettingPrinterDescription, |
| 404 printer_description); | 389 printer_description); |
| 405 | 390 |
| 406 base::DictionaryValue* options = new base::DictionaryValue; | 391 auto options = base::MakeUnique<base::DictionaryValue>(); |
| 407 printer_info->Set(printing::kSettingPrinterOptions, options); | |
| 408 for (const auto opt_it : printer.options) | 392 for (const auto opt_it : printer.options) |
| 409 options->SetString(opt_it.first, opt_it.second); | 393 options->SetString(opt_it.first, opt_it.second); |
| 410 | 394 |
| 395 printer_info->Set(printing::kSettingPrinterOptions, std::move(options)); |
| 396 |
| 411 printers->Append(std::move(printer_info)); | 397 printers->Append(std::move(printer_info)); |
| 412 | 398 |
| 413 VLOG(1) << "Found printer " << printer_name << " with device name " | 399 VLOG(1) << "Found printer " << printer_name << " with device name " |
| 414 << printer.printer_name; | 400 << printer.printer_name; |
| 415 } | 401 } |
| 416 } | 402 } |
| 417 | 403 |
| 418 void EnumeratePrinters(Profile* profile, base::ListValue* printers) { | 404 void EnumeratePrinters(Profile* profile, base::ListValue* printers) { |
| 419 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | 405 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 420 | 406 |
| 421 VLOG(1) << "Enumerate printers start"; | 407 VLOG(1) << "Enumerate printers start"; |
| 422 printing::PrinterList printer_list = | 408 printing::PrinterList printer_list = |
| 423 printing::EnumeratePrintersOnBlockingPoolThread(profile); | 409 printing::EnumeratePrintersOnBlockingPoolThread(profile); |
| 424 PrintersToValues(printer_list, printers); | 410 PrintersToValues(printer_list, printers); |
| 425 VLOG(1) << "Enumerate printers finished, found " << printers->GetSize() | 411 VLOG(1) << "Enumerate printers finished, found " << printers->GetSize() |
| 426 << " printers"; | 412 << " printers"; |
| 427 } | 413 } |
| 428 | 414 |
| 429 std::unique_ptr<base::DictionaryValue> | |
| 430 GetPrinterCapabilitiesOnBlockingPoolThread(const std::string& device_name) { | |
| 431 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); | |
| 432 DCHECK(!device_name.empty()); | |
| 433 | |
| 434 scoped_refptr<printing::PrintBackend> print_backend( | |
| 435 printing::PrintBackend::CreateInstance(nullptr)); | |
| 436 | |
| 437 VLOG(1) << "Get printer capabilities start for " << device_name; | |
| 438 crash_keys::ScopedPrinterInfo crash_key( | |
| 439 print_backend->GetPrinterDriverInfo(device_name)); | |
| 440 | |
| 441 std::unique_ptr<base::DictionaryValue> printer_info; | |
| 442 if (!print_backend->IsValidPrinter(device_name)) { | |
| 443 LOG(WARNING) << "Invalid printer " << device_name; | |
| 444 return printer_info; | |
| 445 } | |
| 446 | |
| 447 printing::PrinterSemanticCapsAndDefaults info; | |
| 448 if (!print_backend->GetPrinterSemanticCapsAndDefaults(device_name, &info)) { | |
| 449 LOG(WARNING) << "Failed to get capabilities for " << device_name; | |
| 450 return printer_info; | |
| 451 } | |
| 452 | |
| 453 std::unique_ptr<base::DictionaryValue> printer_capabilities = | |
| 454 cloud_print::PrinterSemanticCapsAndDefaultsToCdd(info); | |
| 455 if (!printer_capabilities) { | |
| 456 LOG(WARNING) << "Failed to convert capabilities for " << device_name; | |
| 457 return printer_info; | |
| 458 } | |
| 459 | |
| 460 printing::PrinterBasicInfo basic_info; | |
| 461 if (!print_backend->GetPrinterBasicInfo(device_name, &basic_info)) | |
| 462 return printer_info; | |
| 463 | |
| 464 const auto printer_name_description = | |
| 465 GetPrinterNameAndDescription(basic_info); | |
| 466 const std::string& printer_name = printer_name_description.first; | |
| 467 const std::string& printer_description = printer_name_description.second; | |
| 468 | |
| 469 printer_info.reset(new base::DictionaryValue); | |
| 470 printer_info->SetString(kPrinterId, device_name); | |
| 471 printer_info->SetString(printing::kSettingPrinterName, printer_name); | |
| 472 printer_info->SetString(printing::kSettingPrinterDescription, | |
| 473 printer_description); | |
| 474 printer_info->Set(kPrinterCapabilities, printer_capabilities.release()); | |
| 475 return printer_info; | |
| 476 } | |
| 477 | |
| 478 base::LazyInstance<printing::StickySettings> g_sticky_settings = | 415 base::LazyInstance<printing::StickySettings> g_sticky_settings = |
| 479 LAZY_INSTANCE_INITIALIZER; | 416 LAZY_INSTANCE_INITIALIZER; |
| 480 | 417 |
| 481 printing::StickySettings* GetStickySettings() { | 418 printing::StickySettings* GetStickySettings() { |
| 482 return g_sticky_settings.Pointer(); | 419 return g_sticky_settings.Pointer(); |
| 483 } | 420 } |
| 484 | 421 |
| 485 // Returns a unique path for |path|, just like with downloads. | 422 // Returns a unique path for |path|, just like with downloads. |
| 486 base::FilePath GetUniquePath(const base::FilePath& path) { | 423 base::FilePath GetUniquePath(const base::FilePath& path) { |
| 487 base::FilePath unique_path = path; | 424 base::FilePath unique_path = path; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 601 void PrintPreviewHandler::RegisterMessages() { | 538 void PrintPreviewHandler::RegisterMessages() { |
| 602 web_ui()->RegisterMessageCallback("getPrinters", | 539 web_ui()->RegisterMessageCallback("getPrinters", |
| 603 base::Bind(&PrintPreviewHandler::HandleGetPrinters, | 540 base::Bind(&PrintPreviewHandler::HandleGetPrinters, |
| 604 base::Unretained(this))); | 541 base::Unretained(this))); |
| 605 web_ui()->RegisterMessageCallback("getPreview", | 542 web_ui()->RegisterMessageCallback("getPreview", |
| 606 base::Bind(&PrintPreviewHandler::HandleGetPreview, | 543 base::Bind(&PrintPreviewHandler::HandleGetPreview, |
| 607 base::Unretained(this))); | 544 base::Unretained(this))); |
| 608 web_ui()->RegisterMessageCallback("print", | 545 web_ui()->RegisterMessageCallback("print", |
| 609 base::Bind(&PrintPreviewHandler::HandlePrint, | 546 base::Bind(&PrintPreviewHandler::HandlePrint, |
| 610 base::Unretained(this))); | 547 base::Unretained(this))); |
| 611 web_ui()->RegisterMessageCallback("getPrinterCapabilities", | 548 web_ui()->RegisterMessageCallback( |
| 549 "getPrinterCapabilities", |
| 612 base::Bind(&PrintPreviewHandler::HandleGetPrinterCapabilities, | 550 base::Bind(&PrintPreviewHandler::HandleGetPrinterCapabilities, |
| 613 base::Unretained(this))); | 551 base::Unretained(this))); |
| 614 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) | 552 #if BUILDFLAG(ENABLE_BASIC_PRINT_DIALOG) |
| 615 web_ui()->RegisterMessageCallback("showSystemDialog", | 553 web_ui()->RegisterMessageCallback("showSystemDialog", |
| 616 base::Bind(&PrintPreviewHandler::HandleShowSystemDialog, | 554 base::Bind(&PrintPreviewHandler::HandleShowSystemDialog, |
| 617 base::Unretained(this))); | 555 base::Unretained(this))); |
| 618 #endif | 556 #endif |
| 619 web_ui()->RegisterMessageCallback("signIn", | 557 web_ui()->RegisterMessageCallback("signIn", |
| 620 base::Bind(&PrintPreviewHandler::HandleSignin, | 558 base::Bind(&PrintPreviewHandler::HandleSignin, |
| 621 base::Unretained(this))); | 559 base::Unretained(this))); |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1073 void PrintPreviewHandler::HandleGetPrinterCapabilities( | 1011 void PrintPreviewHandler::HandleGetPrinterCapabilities( |
| 1074 const base::ListValue* args) { | 1012 const base::ListValue* args) { |
| 1075 std::string printer_name; | 1013 std::string printer_name; |
| 1076 bool ret = args->GetString(0, &printer_name); | 1014 bool ret = args->GetString(0, &printer_name); |
| 1077 if (!ret || printer_name.empty()) | 1015 if (!ret || printer_name.empty()) |
| 1078 return; | 1016 return; |
| 1079 | 1017 |
| 1080 if (printer_name == kLocalPdfPrinterId) { | 1018 if (printer_name == kLocalPdfPrinterId) { |
| 1081 std::unique_ptr<base::DictionaryValue> printer_info( | 1019 std::unique_ptr<base::DictionaryValue> printer_info( |
| 1082 new base::DictionaryValue); | 1020 new base::DictionaryValue); |
| 1083 printer_info->SetString(kPrinterId, printer_name); | 1021 printer_info->SetString(printing::kPrinterId, printer_name); |
| 1084 printer_info->Set( | 1022 printer_info->Set( |
| 1085 kPrinterCapabilities, | 1023 printing::kPrinterCapabilities, |
| 1086 GetPdfCapabilities(g_browser_process->GetApplicationLocale())); | 1024 GetPdfCapabilities(g_browser_process->GetApplicationLocale())); |
| 1087 SendPrinterCapabilities(printer_name, std::move(printer_info)); | 1025 SendPrinterCapabilities(printer_name, std::move(printer_info)); |
| 1088 return; | 1026 return; |
| 1089 } | 1027 } |
| 1090 | 1028 |
| 1091 base::PostTaskAndReplyWithResult( | 1029 printing::PrinterSetupCallback cb = |
| 1092 BrowserThread::GetBlockingPool(), FROM_HERE, | |
| 1093 base::Bind(&GetPrinterCapabilitiesOnBlockingPoolThread, printer_name), | |
| 1094 base::Bind(&PrintPreviewHandler::SendPrinterCapabilities, | 1030 base::Bind(&PrintPreviewHandler::SendPrinterCapabilities, |
| 1095 weak_factory_.GetWeakPtr(), printer_name)); | 1031 weak_factory_.GetWeakPtr(), printer_name); |
| 1032 |
| 1033 BrowserThread::PostBlockingPoolTask( |
| 1034 FROM_HERE, base::Bind(&printing::ConfigurePrinterAndFetchCapabilities, |
| 1035 base::Unretained(Profile::FromWebUI(web_ui())), |
| 1036 printer_name, cb)); |
| 1096 } | 1037 } |
| 1097 | 1038 |
| 1098 void PrintPreviewHandler::OnSigninComplete() { | 1039 void PrintPreviewHandler::OnSigninComplete() { |
| 1099 if (print_preview_ui()) | 1040 if (print_preview_ui()) |
| 1100 print_preview_ui()->OnReloadPrintersList(); | 1041 print_preview_ui()->OnReloadPrintersList(); |
| 1101 } | 1042 } |
| 1102 | 1043 |
| 1103 void PrintPreviewHandler::HandleSignin(const base::ListValue* args) { | 1044 void PrintPreviewHandler::HandleSignin(const base::ListValue* args) { |
| 1104 bool add_account = false; | 1045 bool add_account = false; |
| 1105 bool success = args->GetBoolean(0, &add_account); | 1046 bool success = args->GetBoolean(0, &add_account); |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 | 1699 |
| 1759 void PrintPreviewHandler::UnregisterForGaiaCookieChanges() { | 1700 void PrintPreviewHandler::UnregisterForGaiaCookieChanges() { |
| 1760 if (gaia_cookie_manager_service_) | 1701 if (gaia_cookie_manager_service_) |
| 1761 gaia_cookie_manager_service_->RemoveObserver(this); | 1702 gaia_cookie_manager_service_->RemoveObserver(this); |
| 1762 } | 1703 } |
| 1763 | 1704 |
| 1764 void PrintPreviewHandler::SetPdfSavedClosureForTesting( | 1705 void PrintPreviewHandler::SetPdfSavedClosureForTesting( |
| 1765 const base::Closure& closure) { | 1706 const base::Closure& closure) { |
| 1766 pdf_file_saved_closure_ = closure; | 1707 pdf_file_saved_closure_ = closure; |
| 1767 } | 1708 } |
| OLD | NEW |