diff options
-rw-r--r-- | chrome/app/generated_resources.grd | 3 | ||||
-rw-r--r-- | chrome/browser/ui/cocoa/pdf_password_dialog.mm | 142 | ||||
-rw-r--r-- | chrome/browser/ui/pdf/pdf_tab_helper.cc | 37 | ||||
-rw-r--r-- | chrome/browser/ui/pdf/pdf_tab_helper.h | 21 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 1 | ||||
-rw-r--r-- | chrome/common/render_messages.h | 5 | ||||
-rw-r--r-- | chrome/renderer/pepper/ppb_pdf_impl.cc | 23 | ||||
-rw-r--r-- | ppapi/api/private/finish_writing_these/ppb_pdf.idl | 8 | ||||
-rw-r--r-- | ppapi/c/private/ppb_pdf.h | 4 | ||||
-rw-r--r-- | ppapi/cpp/private/pdf.cc | 10 | ||||
-rw-r--r-- | ppapi/cpp/private/pdf.h | 2 |
11 files changed, 255 insertions, 1 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 54d6bb1..d283bf6 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -14191,6 +14191,9 @@ Some features may be unavailable. Please check that the profile exists and you <message name="IDS_PDF_INFOBAR_ALWAYS_USE_READER_BUTTON" desc="The label of the 'always' button on the infobar that asks the user if they want to set Adobe Reader as default."> Always </message> + <message name="IDS_PDF_PASSWORD_DIALOG_TITLE" desc="The title of the dialog requesting a password to open a protected PDF."> + Password required + </message> <!-- Adobe Reader is out of date Blocking Page --> <message name="IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE" desc="The title of the Adobe Reader out of date blocking page."> diff --git a/chrome/browser/ui/cocoa/pdf_password_dialog.mm b/chrome/browser/ui/cocoa/pdf_password_dialog.mm new file mode 100644 index 0000000..a7f75a8 --- /dev/null +++ b/chrome/browser/ui/cocoa/pdf_password_dialog.mm @@ -0,0 +1,142 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/pdf/pdf_tab_helper.h" + +#import <Cocoa/Cocoa.h> + +#include "base/mac/scoped_nsobject.h" +#include "base/memory/scoped_ptr.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_alert.h" +#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h" +#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h" +#import "chrome/browser/ui/cocoa/key_equivalent_constants.h" +#include "grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +@class PDFPasswordDialogMac; + +namespace { + +class PDFPasswordDialogMacBridge : public ConstrainedWindowMacDelegate { + public: + explicit PDFPasswordDialogMacBridge(PDFPasswordDialogMac* dialog); + virtual ~PDFPasswordDialogMacBridge(); + virtual void OnConstrainedWindowClosed(ConstrainedWindowMac* window) OVERRIDE; + + private: + PDFPasswordDialogMac* dialog_; // weak + + DISALLOW_COPY_AND_ASSIGN(PDFPasswordDialogMacBridge); +}; + +} // namespace + +@interface PDFPasswordDialogMac : NSObject { + @private + content::WebContents* webContents_; + base::string16 prompt_; + PasswordDialogClosedCallback callback_; + + base::scoped_nsobject<NSSecureTextField> passwordField_; + + base::scoped_nsobject<ConstrainedWindowAlert> alert_; + scoped_ptr<PDFPasswordDialogMacBridge> bridge_; + scoped_ptr<ConstrainedWindowMac> window_; +} +- (id)initWithWebContents:(content::WebContents*)webContents + prompt:(base::string16)prompt + callback:(PasswordDialogClosedCallback)callback; +- (void)onOKButton:(id)sender; +- (void)onCancelButton:(id)sender; +@end + +namespace { + +PDFPasswordDialogMacBridge::PDFPasswordDialogMacBridge( + PDFPasswordDialogMac* dialog) : dialog_(dialog) { +} + +PDFPasswordDialogMacBridge::~PDFPasswordDialogMacBridge() { +} + +void PDFPasswordDialogMacBridge::OnConstrainedWindowClosed( + ConstrainedWindowMac* window) { + [dialog_ release]; +} + +} // namespace + +@implementation PDFPasswordDialogMac + +- (id)initWithWebContents:(content::WebContents*)webContents + prompt:(base::string16)prompt + callback:(PasswordDialogClosedCallback)callback { + if ((self = [super init])) { + webContents_ = webContents; + prompt_ = prompt; + callback_ = callback; + + alert_.reset([[ConstrainedWindowAlert alloc] init]); + [alert_ setMessageText: + l10n_util::GetNSString(IDS_PDF_PASSWORD_DIALOG_TITLE)]; + [alert_ setInformativeText:base::SysUTF16ToNSString(prompt)]; + [alert_ addButtonWithTitle:l10n_util::GetNSString(IDS_OK) + keyEquivalent:kKeyEquivalentReturn + target:self + action:@selector(onOKButton:)]; + [alert_ addButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL) + keyEquivalent:kKeyEquivalentEscape + target:self + action:@selector(onCancelButton:)]; + [[alert_ closeButton] setTarget:self]; + [[alert_ closeButton] setAction:@selector(onCancelButton:)]; + + passwordField_.reset( + [[NSSecureTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]); + [alert_ setAccessoryView:passwordField_]; + + [alert_ layout]; + + base::scoped_nsobject<CustomConstrainedWindowSheet> sheet( + [[CustomConstrainedWindowSheet alloc] + initWithCustomWindow:[alert_ window]]); + bridge_.reset(new PDFPasswordDialogMacBridge(self)); + window_.reset(new ConstrainedWindowMac(bridge_.get(), webContents_, sheet)); + } + return self; +} + +- (void)dealloc { + if (!callback_.is_null()) { + // This dialog was torn down without either OK or cancel being clicked; be + // considerate and at least do the callback. + callback_.Run(false, base::string16()); + } + [super dealloc]; +} + +- (void)onOKButton:(id)sender { + callback_.Run(true, base::SysNSStringToUTF16([passwordField_ stringValue])); + callback_.Reset(); + window_->CloseWebContentsModalDialog(); +} + +- (void)onCancelButton:(id)sender { + callback_.Run(false, base::string16()); + callback_.Reset(); + window_->CloseWebContentsModalDialog(); +} + +@end + +void ShowPDFPasswordDialog(content::WebContents* web_contents, + const base::string16& prompt, + const PasswordDialogClosedCallback& callback) { + [[PDFPasswordDialogMac alloc] initWithWebContents:web_contents + prompt:prompt + callback:callback]; +} diff --git a/chrome/browser/ui/pdf/pdf_tab_helper.cc b/chrome/browser/ui/pdf/pdf_tab_helper.cc index 126b8a7..b58482e 100644 --- a/chrome/browser/ui/pdf/pdf_tab_helper.cc +++ b/chrome/browser/ui/pdf/pdf_tab_helper.cc @@ -4,7 +4,9 @@ #include "chrome/browser/ui/pdf/pdf_tab_helper.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/download/download_stats.h" +#include "chrome/browser/ui/app_modal_dialogs/javascript_dialog_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" @@ -13,6 +15,7 @@ #include "chrome/browser/ui/pdf/pdf_unsupported_feature.h" #include "chrome/browser/ui/tab_contents/core_tab_helper.h" #include "chrome/common/render_messages.h" +#include "content/public/browser/javascript_dialog_manager.h" #include "content/public/browser/navigation_details.h" DEFINE_WEB_CONTENTS_USER_DATA_KEY(PDFTabHelper); @@ -38,6 +41,8 @@ bool PDFTabHelper::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PDFSaveURLAs, OnSaveURLAs) IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PDFUpdateContentRestrictions, OnUpdateContentRestrictions) + IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_PDFModalPromptForPassword, + OnModalPromptForPassword) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -84,3 +89,35 @@ void PDFTabHelper::OnUpdateContentRestrictions(int content_restrictions) { CoreTabHelper::FromWebContents(web_contents()); core_tab_helper->UpdateContentRestrictions(content_restrictions); } + +void PDFTabHelper::OnModalPromptForPasswordClosed( + IPC::Message* reply_message, + bool success, + const string16& actual_value) { + ChromeViewHostMsg_PDFModalPromptForPassword::WriteReplyParams( + reply_message, UTF16ToUTF8(actual_value)); + Send(reply_message); +} + +void PDFTabHelper::OnModalPromptForPassword(const std::string& prompt, + IPC::Message* reply_message) { + base::Callback<void(bool, const string16&)> callback = + base::Bind(&PDFTabHelper::OnModalPromptForPasswordClosed, + base::Unretained(this), reply_message); +#if defined(OS_MACOSX) + ShowPDFPasswordDialog(web_contents(), base::UTF8ToUTF16(prompt), callback); +#else + // Cheat (for now). + bool did_suppress_message; + GetJavaScriptDialogManagerInstance()->RunJavaScriptDialog( + web_contents(), + GURL(), + std::string(), + content::JAVASCRIPT_MESSAGE_TYPE_PROMPT, + base::UTF8ToUTF16(prompt), + base::string16(), + true, + callback, + &did_suppress_message); +#endif // OS_* +} diff --git a/chrome/browser/ui/pdf/pdf_tab_helper.h b/chrome/browser/ui/pdf/pdf_tab_helper.h index 978c605..45a6e6f 100644 --- a/chrome/browser/ui/pdf/pdf_tab_helper.h +++ b/chrome/browser/ui/pdf/pdf_tab_helper.h @@ -5,9 +5,13 @@ #ifndef CHROME_BROWSER_UI_PDF_PDF_TAB_HELPER_H_ #define CHROME_BROWSER_UI_PDF_PDF_TAB_HELPER_H_ +#include <string> + +#include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" +#include "ipc/ipc_message.h" class OpenPDFInReaderPromptDelegate; @@ -39,12 +43,17 @@ class PDFTabHelper : public content::WebContentsObserver, // Internal helpers ---------------------------------------------------------- void UpdateLocationBar(); + void OnModalPromptForPasswordClosed(IPC::Message* reply_message, + bool success, + const string16& actual_value); // Message handlers. void OnHasUnsupportedFeature(); void OnSaveURLAs(const GURL& url, const content::Referrer& referrer); void OnUpdateContentRestrictions(int content_restrictions); + void OnModalPromptForPassword(const std::string& prompt, + IPC::Message* reply_message); // The model for the confirmation prompt to open a PDF in Adobe Reader. scoped_ptr<OpenPDFInReaderPromptDelegate> open_in_reader_prompt_; @@ -52,4 +61,16 @@ class PDFTabHelper : public content::WebContentsObserver, DISALLOW_COPY_AND_ASSIGN(PDFTabHelper); }; +// TODO(avi): write for other platforms +#if defined(OS_MACOSX) +typedef base::Callback<void(bool /* success */, + const base::string16& /* password */)> + PasswordDialogClosedCallback; + +// Shows a tab-modal dialog to get a password for a PDF document. +void ShowPDFPasswordDialog(content::WebContents* web_contents, + const base::string16& prompt, + const PasswordDialogClosedCallback& callback); +#endif // OS_* + #endif // CHROME_BROWSER_UI_PDF_PDF_TAB_HELPER_H_ diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index be76ad5..ca5da08 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -866,6 +866,7 @@ 'browser/ui/cocoa/panels/panel_utils_cocoa.mm', 'browser/ui/cocoa/panels/panel_window_controller_cocoa.h', 'browser/ui/cocoa/panels/panel_window_controller_cocoa.mm', + 'browser/ui/cocoa/pdf_password_dialog.mm', 'browser/ui/cocoa/presentation_mode_controller.h', 'browser/ui/cocoa/presentation_mode_controller.mm', 'browser/ui/cocoa/profile_menu_controller.h', diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index bf9b30f..90dab6f 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -668,6 +668,11 @@ IPC_MESSAGE_ROUTED2(ChromeViewHostMsg_PDFSaveURLAs, IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_PDFUpdateContentRestrictions, int /* restrictions */) +// Brings up a Password... dialog for protected documents. +IPC_SYNC_MESSAGE_ROUTED1_1(ChromeViewHostMsg_PDFModalPromptForPassword, + std::string /* prompt */, + std::string /* actual_value */) + // This message indicates the error appeared in the frame. IPC_MESSAGE_ROUTED1(ChromeViewHostMsg_FrameLoadingError, int /* error */) diff --git a/chrome/renderer/pepper/ppb_pdf_impl.cc b/chrome/renderer/pepper/ppb_pdf_impl.cc index a49455e..95bca9f 100644 --- a/chrome/renderer/pepper/ppb_pdf_impl.cc +++ b/chrome/renderer/pepper/ppb_pdf_impl.cc @@ -398,6 +398,26 @@ PP_Resource GetResourceImage(PP_Instance instance_id, return GetResourceImageForScale(instance_id, image_id, 1.0f); } +PP_Var ModalPromptForPassword(PP_Instance instance_id, + PP_Var message) { + content::PepperPluginInstance* instance = + content::PepperPluginInstance::Get(instance_id); + if (!instance) + return PP_MakeUndefined(); + + std::string actual_value; + scoped_refptr<ppapi::StringVar> message_string( + ppapi::StringVar::FromPPVar(message)); + + instance->GetRenderView()->Send( + new ChromeViewHostMsg_PDFModalPromptForPassword( + instance->GetRenderView()->GetRoutingID(), + message_string->value(), + &actual_value)); + + return ppapi::StringVar::StringToPPVar(actual_value); +} + const PPB_PDF ppb_pdf = { &GetLocalizedString, &GetResourceImage, @@ -413,7 +433,8 @@ const PPB_PDF ppb_pdf = { &SaveAs, &PPB_PDF_Impl::InvokePrintingForInstance, &IsFeatureEnabled, - &GetResourceImageForScale + &GetResourceImageForScale, + &ModalPromptForPassword, }; } // namespace diff --git a/ppapi/api/private/finish_writing_these/ppb_pdf.idl b/ppapi/api/private/finish_writing_these/ppb_pdf.idl index b428386..3038d92 100644 --- a/ppapi/api/private/finish_writing_these/ppb_pdf.idl +++ b/ppapi/api/private/finish_writing_these/ppb_pdf.idl @@ -138,4 +138,12 @@ interface PPB_PDF_0_1 { /* Notifies the browser that the PDF has an unsupported feature. */ void HasUnsupportedFeature( [in] PP_Instance instance); + + /* Tells the browser to open a dialog box to receive a password from the + * user, masking input characters. Returns the value entered by the user, or + * an empty string if the user cancels instead. + */ + PP_Var ModalPromptForPassword( + [in] PP_Instance instance, + [in] PP_Var message); }; diff --git a/ppapi/c/private/ppb_pdf.h b/ppapi/c/private/ppb_pdf.h index 2e2e73b..fdc5748 100644 --- a/ppapi/c/private/ppb_pdf.h +++ b/ppapi/c/private/ppb_pdf.h @@ -156,6 +156,10 @@ struct PPB_PDF { PP_Resource (*GetResourceImageForScale)(PP_Instance instance, PP_ResourceImage image_id, float scale); + + // Invoke password dialog for plugin. + struct PP_Var (*ModalPromptForPassword)(PP_Instance instance, + struct PP_Var message); }; #endif // PPAPI_C_PRIVATE_PPB_PDF_H_ diff --git a/ppapi/cpp/private/pdf.cc b/ppapi/cpp/private/pdf.cc index 753613c..9d6bd89 100644 --- a/ppapi/cpp/private/pdf.cc +++ b/ppapi/cpp/private/pdf.cc @@ -184,4 +184,14 @@ ImageData PDF::GetResourceImageForScale(const InstanceHandle& instance, return ImageData(); } +Var PDF::ModalPromptForPassword(const InstanceHandle& instance, + Var message) { + if (has_interface<PPB_PDF>()) { + return Var(PASS_REF, + get_interface<PPB_PDF>()->ModalPromptForPassword( + instance.pp_instance(), + message.pp_var())); + } + return Var(); +} } // namespace pp diff --git a/ppapi/cpp/private/pdf.h b/ppapi/cpp/private/pdf.h index 893f9e3..1e89dd0 100644 --- a/ppapi/cpp/private/pdf.h +++ b/ppapi/cpp/private/pdf.h @@ -62,6 +62,8 @@ class PDF { static ImageData GetResourceImageForScale(const InstanceHandle& instance, PP_ResourceImage image_id, float scale); + static Var ModalPromptForPassword(const InstanceHandle& instance, + Var message); }; } // namespace pp |