PDFPlugin: Support unlocking encrypted PDFs

https://bugs.webkit.org/show_bug.cgi?id=114938
<rdar://problem/12872888>

Reviewed by Alexey Proskuryakov and Oliver Hunt.

If we try to load an encrypted PDF, we need to provide a sane mechanism
through which the user can provide the password. Add a slightly-below-center
password field to match PDFKit's normal behavior.

* WebKit2.xcodeproj/project.pbxproj: Add PDFPluginPasswordField.{h,mm}
* WebProcess/Plugins/PDF/PDFLayerControllerDetails.h: Add attemptToUnlockWithPassword:
* WebProcess/Plugins/PDF/PDFPlugin.h:
Add createPasswordEntryForm, attemptToUnlockPDF, m_passwordField.
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(annotationStyle): Make #annotationContainer a flexbox that centers its contents.
This won't affect the normal absolutely-positioned form fields, but the inline
password field will be centered vertically and horizontally.

(WebKit::PDFPlugin::pdfDocumentDidLoad):
If the document is locked when loaded, create a password field.

(WebKit::PDFPlugin::createPasswordEntryForm):
Create a PDFPluginPasswordField and attach it to the document.

(WebKit::PDFPlugin::attemptToUnlockPDF):
Try to unlock the PDF with the given password. If this succeeds, remove
the password field and relayout the scroll view.

(WebKit::PDFPlugin::calculateSizes):
Make the document 0x0 if it is locked, preventing scrolling.

(WebKit::PDFPlugin::handleMouseEvent):
Don't pass mouse events to PDFLayerController while it is locked,
as it has no useful events to provide, and will try to present a
dialog asking for the password if we let a click through.

* WebProcess/Plugins/PDF/PDFPluginAnnotation.h:
(WebKit::PDFPluginAnnotation::eventListener): Added.
* WebProcess/Plugins/PDF/PDFPluginAnnotation.mm:
(WebKit::PDFPluginAnnotation::handleEvent):
Move event-handling code here from PDFPluginAnnotationEventListener::handleEvent
so that subclasses can override this instead of having to have their own
event listeners (this is also why we now expose eventListener()).

(WebKit::PDFPluginAnnotation::PDFPluginAnnotationEventListener::handleEvent):
Forward the event to our owning PDFPluginAnnotation.

* WebProcess/Plugins/PDF/PDFPluginPasswordField.h: Added.
(WebKit::PDFPluginPasswordField::PDFPluginPasswordField):
* WebProcess/Plugins/PDF/PDFPluginPasswordField.mm: Added.
(WebKit::PDFPluginPasswordField::create):
(WebKit::PDFPluginPasswordField::~PDFPluginPasswordField):
Unregister for keyup.

(WebKit::PDFPluginPasswordField::createAnnotationElement):
Register for keyup, and set our element's class to "password".

(WebKit::PDFPluginPasswordField::updateGeometry):
Added. Override updateGeometry and do nothing, as the password field
has a geometry defined by CSS instead of by the PDF content.

(WebKit::PDFPluginPasswordField::handleEvent):
If the enter/return key is pressed, attempt to unlock the PDF. Also,
we do not call either of our superclass' implementations of handleEvent,
because blurring the password field should not destroy it, and tabbing
between fields has no relevance when there can only be one field.

* WebProcess/Plugins/PDF/PDFPluginTextAnnotation.h:
(WebKit::PDFPluginTextAnnotation::PDFPluginTextAnnotationEventListener):
Removed. We now share our superclass' event listener.

(WebKit::PDFPluginTextAnnotation::textAnnotation): Const.
* WebProcess/Plugins/PDF/PDFPluginTextAnnotation.mm:
(WebKit::PDFPluginTextAnnotation::~PDFPluginTextAnnotation):
PDFPluginTextAnnotation no longer has its own event listener,
so there's nothing left to clear here. Just make sure to unregister
our event from PDFPluginAnnotation's shared event listener!

(WebKit::PDFPluginTextAnnotation::createAnnotationElement):
Ensure that we can create a PDFPluginTextAnnotation with a null annotation.

(WebKit::PDFPluginTextAnnotation::commit): Use value().
(WebKit::PDFPluginTextAnnotation::value):
Factor retrieving the value of the form control out of commit().

(WebKit::PDFPluginTextAnnotation::handleEvent):
Call up to PDFPluginAnnotation's handler so that defocus destroys the annotation.

Export HTMLNames::typeAttr.

* WebCore.exp.in:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@148912 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 167f4cf2
2013-04-22 Tim Horton <timothy_horton@apple.com>
PDFPlugin: Support unlocking encrypted PDFs
https://bugs.webkit.org/show_bug.cgi?id=114938
<rdar://problem/12872888>
Reviewed by Alexey Proskuryakov.
Export HTMLNames::typeAttr.
* WebCore.exp.in:
2013-04-22 Ryosuke Niwa <rniwa@webkit.org>
Use-after-free in CompositeEditCommand::cloneParagraphUnderNewElement
......@@ -1161,6 +1161,7 @@ __ZN7WebCore9HTMLNames8hrefAttrE
__ZN7WebCore9HTMLNames8inputTagE
__ZN7WebCore9HTMLNames8nameAttrE
__ZN7WebCore9HTMLNames8styleTagE
__ZN7WebCore9HTMLNames8typeAttrE
__ZN7WebCore9HTMLNames8videoTagE
__ZN7WebCore9HTMLNames9appletTagE
__ZN7WebCore9HTMLNames9classAttrE
......
2013-04-22 Tim Horton <timothy_horton@apple.com>
PDFPlugin: Support unlocking encrypted PDFs
https://bugs.webkit.org/show_bug.cgi?id=114938
<rdar://problem/12872888>
Reviewed by Alexey Proskuryakov and Oliver Hunt.
If we try to load an encrypted PDF, we need to provide a sane mechanism
through which the user can provide the password. Add a slightly-below-center
password field to match PDFKit's normal behavior.
* WebKit2.xcodeproj/project.pbxproj: Add PDFPluginPasswordField.{h,mm}
* WebProcess/Plugins/PDF/PDFLayerControllerDetails.h: Add attemptToUnlockWithPassword:
* WebProcess/Plugins/PDF/PDFPlugin.h:
Add createPasswordEntryForm, attemptToUnlockPDF, m_passwordField.
* WebProcess/Plugins/PDF/PDFPlugin.mm:
(annotationStyle): Make #annotationContainer a flexbox that centers its contents.
This won't affect the normal absolutely-positioned form fields, but the inline
password field will be centered vertically and horizontally.
(WebKit::PDFPlugin::pdfDocumentDidLoad):
If the document is locked when loaded, create a password field.
(WebKit::PDFPlugin::createPasswordEntryForm):
Create a PDFPluginPasswordField and attach it to the document.
(WebKit::PDFPlugin::attemptToUnlockPDF):
Try to unlock the PDF with the given password. If this succeeds, remove
the password field and relayout the scroll view.
(WebKit::PDFPlugin::calculateSizes):
Make the document 0x0 if it is locked, preventing scrolling.
(WebKit::PDFPlugin::handleMouseEvent):
Don't pass mouse events to PDFLayerController while it is locked,
as it has no useful events to provide, and will try to present a
dialog asking for the password if we let a click through.
* WebProcess/Plugins/PDF/PDFPluginAnnotation.h:
(WebKit::PDFPluginAnnotation::eventListener): Added.
* WebProcess/Plugins/PDF/PDFPluginAnnotation.mm:
(WebKit::PDFPluginAnnotation::handleEvent):
Move event-handling code here from PDFPluginAnnotationEventListener::handleEvent
so that subclasses can override this instead of having to have their own
event listeners (this is also why we now expose eventListener()).
(WebKit::PDFPluginAnnotation::PDFPluginAnnotationEventListener::handleEvent):
Forward the event to our owning PDFPluginAnnotation.
* WebProcess/Plugins/PDF/PDFPluginPasswordField.h: Added.
(WebKit::PDFPluginPasswordField::PDFPluginPasswordField):
* WebProcess/Plugins/PDF/PDFPluginPasswordField.mm: Added.
(WebKit::PDFPluginPasswordField::create):
(WebKit::PDFPluginPasswordField::~PDFPluginPasswordField):
Unregister for keyup.
(WebKit::PDFPluginPasswordField::createAnnotationElement):
Register for keyup, and set our element's class to "password".
(WebKit::PDFPluginPasswordField::updateGeometry):
Added. Override updateGeometry and do nothing, as the password field
has a geometry defined by CSS instead of by the PDF content.
(WebKit::PDFPluginPasswordField::handleEvent):
If the enter/return key is pressed, attempt to unlock the PDF. Also,
we do not call either of our superclass' implementations of handleEvent,
because blurring the password field should not destroy it, and tabbing
between fields has no relevance when there can only be one field.
* WebProcess/Plugins/PDF/PDFPluginTextAnnotation.h:
(WebKit::PDFPluginTextAnnotation::PDFPluginTextAnnotationEventListener):
Removed. We now share our superclass' event listener.
(WebKit::PDFPluginTextAnnotation::textAnnotation): Const.
* WebProcess/Plugins/PDF/PDFPluginTextAnnotation.mm:
(WebKit::PDFPluginTextAnnotation::~PDFPluginTextAnnotation):
PDFPluginTextAnnotation no longer has its own event listener,
so there's nothing left to clear here. Just make sure to unregister
our event from PDFPluginAnnotation's shared event listener!
(WebKit::PDFPluginTextAnnotation::createAnnotationElement):
Ensure that we can create a PDFPluginTextAnnotation with a null annotation.
(WebKit::PDFPluginTextAnnotation::commit): Use value().
(WebKit::PDFPluginTextAnnotation::value):
Factor retrieving the value of the form control out of commit().
(WebKit::PDFPluginTextAnnotation::handleEvent):
Call up to PDFPluginAnnotation's handler so that defocus destroys the annotation.
2013-04-22 Anders Carlsson <andersca@apple.com>
Slow/beachballing when using the find bar on a page with plug-ins
......@@ -315,6 +315,7 @@
2D2ADF0916362DD500197E47 /* PDFPluginTextAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0616362DC700197E47 /* PDFPluginTextAnnotation.mm */; };
2D2ADF0B16362DDB00197E47 /* PDFPluginAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF031636243500197E47 /* PDFPluginAnnotation.mm */; };
2D2ADF1016364D8200197E47 /* PDFPluginChoiceAnnotation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */; };
2D429BFD1721E2C700EC681F /* PDFPluginPasswordField.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */; };
2D870D1016234FFE000A3F20 /* PDFPlugin.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2D870D0E1622B7F9000A3F20 /* PDFPlugin.mm */; };
31099973146C75A20029DEB9 /* WebNotificationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31099971146C759B0029DEB9 /* WebNotificationClient.cpp */; };
310999C7146C9E3D0029DEB9 /* WebNotificationClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 31099968146C71F50029DEB9 /* WebNotificationClient.h */; };
......@@ -1732,6 +1733,8 @@
2D2ADF0C16363DEC00197E47 /* PDFLayerControllerDetails.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PDFLayerControllerDetails.h; path = PDF/PDFLayerControllerDetails.h; sourceTree = "<group>"; };
2D2ADF0D16364D8200197E47 /* PDFPluginChoiceAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPluginChoiceAnnotation.h; path = PDF/PDFPluginChoiceAnnotation.h; sourceTree = "<group>"; };
2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginChoiceAnnotation.mm; path = PDF/PDFPluginChoiceAnnotation.mm; sourceTree = "<group>"; };
2D429BFA1721E2BA00EC681F /* PDFPluginPasswordField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPluginPasswordField.h; path = PDF/PDFPluginPasswordField.h; sourceTree = "<group>"; };
2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPluginPasswordField.mm; path = PDF/PDFPluginPasswordField.mm; sourceTree = "<group>"; };
2D870D0D1622B7F9000A3F20 /* PDFPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PDFPlugin.h; path = PDF/PDFPlugin.h; sourceTree = "<group>"; };
2D870D0E1622B7F9000A3F20 /* PDFPlugin.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = PDFPlugin.mm; path = PDF/PDFPlugin.mm; sourceTree = "<group>"; };
31099968146C71F50029DEB9 /* WebNotificationClient.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebNotificationClient.h; sourceTree = "<group>"; };
......@@ -5125,6 +5128,8 @@
2D2ADF0E16364D8200197E47 /* PDFPluginChoiceAnnotation.mm */,
2D2ADF0516362DC700197E47 /* PDFPluginTextAnnotation.h */,
2D2ADF0616362DC700197E47 /* PDFPluginTextAnnotation.mm */,
2D429BFA1721E2BA00EC681F /* PDFPluginPasswordField.h */,
2D429BFB1721E2BA00EC681F /* PDFPluginPasswordField.mm */,
E199875A142BF9B800BB2DE7 /* SimplePDFPlugin.h */,
E199875C142BFC9700BB2DE7 /* SimplePDFPlugin.mm */,
);
......@@ -6827,6 +6832,7 @@
6501BD1A12F1243400E9F248 /* WKBundleInspector.cpp in Sources */,
BC7043CD12F75EE0006472B9 /* WKBundleNavigationAction.cpp in Sources */,
BC4BEFE2120A1A4C00FBA0C7 /* WKBundleNodeHandle.cpp in Sources */,
2D429BFD1721E2C700EC681F /* PDFPluginPasswordField.mm in Sources */,
BC20528211C94284008F3375 /* WKBundlePage.cpp in Sources */,
BC7B633E12A45D1200D174A4 /* WKBundlePageGroup.cpp in Sources */,
EDCA71B7128DDA8C00201B26 /* WKBundlePageOverlay.cpp in Sources */,
......
......@@ -110,6 +110,8 @@
- (CGRect)boundsForAnnotation:(PDFAnnotation *)annotation;
- (void)activateNextAnnotation:(BOOL)previous;
- (void)attemptToUnlockWithPassword:(NSString *)password;
- (void)searchInDictionaryWithSelection:(PDFSelection *)selection;
@end
......@@ -58,6 +58,7 @@ struct PluginInfo;
namespace WebKit {
class PDFPluginAnnotation;
class PDFPluginPasswordField;
class PluginView;
class WebFrame;
......@@ -86,6 +87,8 @@ public:
void focusNextAnnotation();
void focusPreviousAnnotation();
void attemptToUnlockPDF(const String& password);
private:
explicit PDFPlugin(WebFrame*);
......@@ -133,6 +136,8 @@ private:
void updatePageAndDeviceScaleFactors();
void createPasswordEntryForm();
WebCore::IntPoint convertFromPDFViewToRootView(const WebCore::IntPoint&) const;
RetainPtr<CALayer> m_containerLayer;
......@@ -143,6 +148,7 @@ private:
RetainPtr<PDFLayerController> m_pdfLayerController;
RefPtr<PDFPluginAnnotation> m_activeAnnotation;
RefPtr<PDFPluginPasswordField> m_passwordField;
RefPtr<WebCore::Element> m_annotationContainer;
WebCore::AffineTransform m_rootViewToPluginTransform;
......
......@@ -23,11 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#if ENABLE(PDFKIT_PLUGIN)
#import "config.h"
#import "PDFPlugin.h"
#if ENABLE(PDFKIT_PLUGIN)
#import "ArgumentCoders.h"
#import "AttributedString.h"
#import "DataReference.h"
......@@ -36,6 +36,7 @@
#import "PDFKitImports.h"
#import "PDFLayerControllerDetails.h"
#import "PDFPluginAnnotation.h"
#import "PDFPluginPasswordField.h"
#import "PluginView.h"
#import "WebContextMessages.h"
#import "WebEvent.h"
......@@ -76,6 +77,9 @@ static const char* annotationStyle =
" left: 0; "
" right: 0; "
" bottom: 0; "
" display: -webkit-box; "
" -webkit-box-align: center; "
" -webkit-box-pack: center; "
"} "
".annotation { "
" position: absolute; "
......@@ -83,7 +87,12 @@ static const char* annotationStyle =
"} "
"textarea.annotation { "
" resize: none; "
"}";
"} "
"input.annotation[type='password'] { "
" position: static; "
" width: 200px; "
" margin-top: 100px; "
"} ";
// In non-continuous modes, a single scroll event with a magnitude of >= 20px
// will jump to the next or previous page, to match PDFKit behavior.
......@@ -319,6 +328,27 @@ void PDFPlugin::pdfDocumentDidLoad()
updateScrollbars();
runScriptsInPDFDocument();
if ([document.get() isLocked])
createPasswordEntryForm();
}
void PDFPlugin::createPasswordEntryForm()
{
m_passwordField = PDFPluginPasswordField::create(m_pdfLayerController.get(), this);
m_passwordField->attach(m_annotationContainer.get());
}
void PDFPlugin::attemptToUnlockPDF(const String& password)
{
[m_pdfLayerController attemptToUnlockWithPassword:password];
if (![pdfDocument() isLocked]) {
m_passwordField = nullptr;
calculateSizes();
updateScrollbars();
}
}
void PDFPlugin::updatePageAndDeviceScaleFactors()
......@@ -337,6 +367,11 @@ void PDFPlugin::contentsScaleFactorChanged(float)
void PDFPlugin::calculateSizes()
{
if ([pdfDocument() isLocked]) {
setPDFDocumentSize(IntSize(0, 0));
return;
}
// FIXME: This should come straight from PDFKit.
computePageBoxes();
......@@ -564,6 +599,9 @@ bool PDFPlugin::handleMouseEvent(const WebMouseEvent& event)
if (m_scrollCornerLayer && IntRect(m_scrollCornerLayer.get().frame).contains(mousePosition))
return false;
if ([pdfDocument() isLocked])
return false;
// Right-clicks and Control-clicks always call handleContextMenuEvent as well.
if (event.button() == WebMouseEvent::RightButton || (event.button() == WebMouseEvent::LeftButton && event.controlKey()))
return true;
......
......@@ -70,6 +70,9 @@ protected:
WebCore::Element* parent() const { return m_parent; }
PDFLayerController *pdfLayerController() const { return m_pdfLayerController; }
WebCore::EventListener* eventListener() const { return m_eventListener.get(); }
virtual bool handleEvent(WebCore::Event*);
private:
virtual PassRefPtr<WebCore::Element> createAnnotationElement() = 0;
......
......@@ -23,11 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#if ENABLE(PDFKIT_PLUGIN)
#import "config.h"
#import "PDFPluginAnnotation.h"
#if ENABLE(PDFKIT_PLUGIN)
#import "PDFKitImports.h"
#import "PDFLayerControllerDetails.h"
#import "PDFPlugin.h"
......@@ -108,13 +108,20 @@ void PDFPluginAnnotation::updateGeometry()
styledElement->setInlineStyleProperty(CSSPropertyTop, documentSize.height() - annotationRect.origin.y - annotationRect.size.height - scrollPosition.y(), CSSPrimitiveValue::CSS_PX);
}
void PDFPluginAnnotation::PDFPluginAnnotationEventListener::handleEvent(ScriptExecutionContext*, Event* event)
bool PDFPluginAnnotation::handleEvent(Event* event)
{
if (!m_annotation)
return;
if (event->type() == eventNames().blurEvent || event->type() == eventNames().changeEvent) {
m_plugin->setActiveAnnotation(0);
return true;
}
if (event->type() == eventNames().blurEvent || event->type() == eventNames().changeEvent)
m_annotation->plugin()->setActiveAnnotation(0);
return false;
}
void PDFPluginAnnotation::PDFPluginAnnotationEventListener::handleEvent(ScriptExecutionContext*, Event* event)
{
if (m_annotation)
m_annotation->handleEvent(event);
}
} // namespace WebKit
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PDFPluginPasswordField_h
#define PDFPluginPasswordField_h
#if ENABLE(PDFKIT_PLUGIN)
#include "PDFPluginTextAnnotation.h"
namespace WebKit {
class PDFPluginPasswordField : public PDFPluginTextAnnotation {
public:
static PassRefPtr<PDFPluginPasswordField> create(PDFLayerController *, PDFPlugin*);
virtual ~PDFPluginPasswordField();
virtual void updateGeometry() OVERRIDE;
private:
PDFPluginPasswordField(PDFLayerController *pdfLayerController, PDFPlugin* plugin)
: PDFPluginTextAnnotation(0, pdfLayerController, plugin)
{
}
virtual PassRefPtr<WebCore::Element> createAnnotationElement() OVERRIDE;
virtual bool handleEvent(WebCore::Event*) OVERRIDE;
};
} // namespace WebKit
#endif // ENABLE(PDFKIT_PLUGIN)
#endif // PDFPluginTextAnnotation_h
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import "config.h"
#import "PDFPluginPasswordField.h"
#if ENABLE(PDFKIT_PLUGIN)
#import "PDFKitImports.h"
#import "PDFLayerControllerDetails.h"
#import "PDFPlugin.h"
#import <PDFKit/PDFKit.h>
#import <WebCore/Event.h>
#import <WebCore/HTMLElement.h>
#import <WebCore/KeyboardEvent.h>
using namespace WebCore;
using namespace HTMLNames;
namespace WebKit {
PassRefPtr<PDFPluginPasswordField> PDFPluginPasswordField::create(PDFLayerController *pdfLayerController, PDFPlugin* plugin)
{
return adoptRef(new PDFPluginPasswordField(pdfLayerController, plugin));
}
PDFPluginPasswordField::~PDFPluginPasswordField()
{
element()->removeEventListener(eventNames().keyupEvent, eventListener(), false);
}
PassRefPtr<Element> PDFPluginPasswordField::createAnnotationElement()
{
RefPtr<Element> element = PDFPluginTextAnnotation::createAnnotationElement();
element->setAttribute(typeAttr, "password");
element->addEventListener(eventNames().keyupEvent, eventListener(), false);
return element;
}
void PDFPluginPasswordField::updateGeometry()
{
}
bool PDFPluginPasswordField::handleEvent(WebCore::Event* event)
{
if (event->isKeyboardEvent() && event->type() == eventNames().keyupEvent) {
KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event);
if (keyboardEvent->keyIdentifier() == "Enter") {
plugin()->attemptToUnlockPDF(value());
event->preventDefault();
return true;
}
}
return false;
}
} // namespace WebKit
#endif // ENABLE(PDFKIT_PLUGIN)
......@@ -30,6 +30,8 @@
#include "PDFPluginAnnotation.h"
#include <wtf/text/WTFString.h>
namespace WebCore {
class Element;
}
......@@ -46,41 +48,19 @@ public:
virtual void updateGeometry() OVERRIDE;
virtual void commit() OVERRIDE;
private:
protected:
PDFPluginTextAnnotation(PDFAnnotation *annotation, PDFLayerController *pdfLayerController, PDFPlugin* plugin)
: PDFPluginAnnotation(annotation, pdfLayerController, plugin)
, m_eventListener(PDFPluginTextAnnotationEventListener::create(this))
{
}
class PDFPluginTextAnnotationEventListener : public WebCore::EventListener {
public:
static PassRefPtr<PDFPluginTextAnnotationEventListener> create(PDFPluginTextAnnotation* annotation)
{
return adoptRef(new PDFPluginTextAnnotationEventListener(annotation));
}
virtual bool operator==(const EventListener& listener) OVERRIDE { return this == &listener; }
void setTextAnnotation(PDFPluginTextAnnotation* annotation) { m_annotation = annotation; }
private:
PDFPluginTextAnnotationEventListener(PDFPluginTextAnnotation* annotation)
: WebCore::EventListener(WebCore::EventListener::CPPEventListenerType)
, m_annotation(annotation)
{
}
virtual void handleEvent(WebCore::ScriptExecutionContext*, WebCore::Event*) OVERRIDE;
PDFPluginTextAnnotation* m_annotation;
};
virtual PassRefPtr<WebCore::Element> createAnnotationElement() OVERRIDE;
String value() const;
PDFAnnotationTextWidget * textAnnotation() { return static_cast<PDFAnnotationTextWidget *>(annotation()); }
private:
virtual bool handleEvent(WebCore::Event*) OVERRIDE;
RefPtr<PDFPluginTextAnnotationEventListener> m_eventListener;
PDFAnnotationTextWidget *textAnnotation() const { return static_cast<PDFAnnotationTextWidget *>(annotation()); }
};
} // namespace WebKit
......
......@@ -23,11 +23,11 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#if ENABLE(PDFKIT_PLUGIN)
#import "config.h"
#import "PDFPluginTextAnnotation.h"
#if ENABLE(PDFKIT_PLUGIN)
#import "PDFAnnotationTextWidgetDetails.h"
#import "PDFKitImports.h"
#import "PDFLayerControllerDetails.h"
......@@ -43,7 +43,6 @@
#import <WebCore/HTMLTextAreaElement.h>
#import <WebCore/KeyboardEvent.h>
#import <WebCore/Page.h>
#import <WebCore/WindowsKeyboardCodes.h>
using namespace WebCore;
......@@ -77,8 +76,7 @@ PassRefPtr<PDFPluginTextAnnotation> PDFPluginTextAnnotation::create(PDFAnnotatio
PDFPluginTextAnnotation::~PDFPluginTextAnnotation()
{
element()->removeEventListener(eventNames().keydownEvent, m_eventListener.get(), false);
m_eventListener->setTextAnnotation(0);
element()->removeEventListener(eventNames().keydownEvent, eventListener(), false);
}
PassRefPtr<Element> PDFPluginTextAnnotation::createAnnotationElement()
......@@ -94,10 +92,13 @@ PassRefPtr<Element> PDFPluginTextAnnotation::createAnnotationElement()
else
element = document->createElement(inputTag, false);
element->addEventListener(eventNames().keydownEvent, m_eventListener, false);
element->addEventListener(eventNames().keydownEvent, eventListener(), false);
StyledElement* styledElement = static_cast<StyledElement*>(element.get());
if (!textAnnotation)
return element;
// FIXME: Match font weight and style as well?
styledElement->setInlineStyleProperty(CSSPropertyColor, colorFromNSColor(textAnnotation.fontColor).serialized());
styledElement->setInlineStyleProperty(CSSPropertyFontFamily, textAnnotation.font.familyName);
......@@ -121,36 +122,38 @@ void PDFPluginTextAnnotation::updateGeometry()
void PDFPluginTextAnnotation::commit()
{
PDFAnnotationTextWidget *textAnnotation = this->textAnnotation();
if (textAnnotation.isMultiline)
textAnnotation.stringValue = static_cast<HTMLTextAreaElement*>(element())->value();
else
textAnnotation.stringValue = static_cast<HTMLInputElement*>(element())->value();
textAnnotation().stringValue = value();
PDFPluginAnnotation::commit();
}
void PDFPluginTextAnnotation::PDFPluginTextAnnotationEventListener::handleEvent(ScriptExecutionContext*, Event* event)
String PDFPluginTextAnnotation::value() const
{
if (!m_annotation)
return;
return toHTMLTextFormControlElement(element())->value();
}
bool PDFPluginTextAnnotation::handleEvent(Event* event)
{
if (PDFPluginAnnotation::handleEvent(event))
return true;
if (event->isKeyboardEvent() && event->type() == eventNames().keydownEvent) {
KeyboardEvent* keyboardEvent = static_cast<KeyboardEvent*>(event);
if (keyboardEvent->keyIdentifier() == "U+0009") {
if (keyboardEvent->ctrlKey() || keyboardEvent->metaKey() || keyboardEvent->altGraphKey())
return;
return false;
if (keyboardEvent->shiftKey())
m_annotation->plugin()->focusPreviousAnnotation();
plugin()->focusPreviousAnnotation();
else
m_annotation->plugin()->focusNextAnnotation();
plugin()->focusNextAnnotation();