<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[183293] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/183293">183293</a></dd>
<dt>Author</dt> <dd>timothy_horton@apple.com</dd>
<dt>Date</dt> <dd>2015-04-24 16:54:59 -0700 (Fri, 24 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>WKPDFView does not support password-protected PDFs
https://bugs.webkit.org/show_bug.cgi?id=144162
&lt;rdar://problem/18411512&gt;

Reviewed by Andy Estes.

* Platform/spi/ios/UIKitSPI.h:
Add some SPI.

* UIProcess/ios/WKPDFView.h:
* UIProcess/ios/WKPDFView.mm:
(-[WKPDFView _didLoadPDFDocument]):
(-[WKPDFView web_setContentProviderData:suggestedFilename:]):
Move creation of the UIPDFDocument (only possible if the CGPDFDocument is unlocked)
and initial setup of the page views out into _didLoadPDFDocument.

If the CGPDFDocument is locked, we'll show some UI to unlock it; otherwise
we'll continue on to _didLoadPDFDocument as previously.

(-[WKPDFView web_setMinimumSize:]):
Resize the password UI instead of the PDF pages if we have it.

(-[WKPDFView _computePageAndDocumentFrames]):
Don't bother doing any work revalidating PDF pages if the document is locked.

(-[WKPDFView _updatePasswordEntryField]):
Make sure that the UIDocumentPassword view is always the size of the scrollview.
This takes care of rotation.

(-[WKPDFView _keyboardDidShow:]):
Make sure that we scroll the password field around, if necessary, to keep it
on screen when editing begins.

(-[WKPDFView _showPasswordEntryField]):
(-[WKPDFView _hidePasswordEntryField]):
Adjust the background color (to match the UIDocumentPasswordView) and disable zooming
while it's up. The UIDocumentPassword view is installed into the scroll view
to match UIWebView behavior.

(-[WKPDFView userDidEnterPassword:forPasswordView:]):
(-[WKPDFView didBeginEditingPassword:inView:]):
(-[WKPDFView didEndEditingPassword:inView:]):
(-[WKPDFView _didFailToUnlock]):
Pop up a dialog informing the user that they entered the wrong password.

(-[WKPDFView _tryToUnlockWithPassword:]):
Try to unlock the document. If it succeeds, hide the unlock UI and go back to
_didLoadPDFDocument.

* English.lproj/Localizable.strings:
Add some localizable strings.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreEnglishlprojLocalizablestrings">trunk/Source/WebCore/English.lproj/Localizable.strings</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2PlatformspiiosUIKitSPIh">trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKPDFViewh">trunk/Source/WebKit2/UIProcess/ios/WKPDFView.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessiosWKPDFViewmm">trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebCore/ChangeLog        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-04-24  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WKPDFView does not support password-protected PDFs
+        https://bugs.webkit.org/show_bug.cgi?id=144162
+        &lt;rdar://problem/18411512&gt;
+
+        Reviewed by Andy Estes.
+
+        * English.lproj/Localizable.strings:
+        Add some localizable strings.
+
</ins><span class="cx"> 2015-04-24  David Kilzer  &lt;ddkilzer@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix iOS EWS builds after updating to iOS 8.3 SDK
</span></span></pre></div>
<a id="trunkSourceWebCoreEnglishlprojLocalizablestrings"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/English.lproj/Localizable.strings (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/English.lproj/Localizable.strings        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebCore/English.lproj/Localizable.strings        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -1108,3 +1108,8 @@
</span><span class="cx"> /* accessibility label for video element controller */
</span><span class="cx"> &quot;video playback&quot; = &quot;video playback&quot;;
</span><span class="cx"> 
</span><ins>+/* PDF password failure alert message */
+&quot;The document could not be opened with that password.&quot; = &quot;The document could not be opened with that password.&quot;;
+
+/* OK button label in PDF password failure alert */
+&quot;OK (PDF password failure alert)&quot; = &quot;OK&quot;;
</ins></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebKit2/ChangeLog        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -1,3 +1,54 @@
</span><ins>+2015-04-24  Tim Horton  &lt;timothy_horton@apple.com&gt;
+
+        WKPDFView does not support password-protected PDFs
+        https://bugs.webkit.org/show_bug.cgi?id=144162
+        &lt;rdar://problem/18411512&gt;
+
+        Reviewed by Andy Estes.
+
+        * Platform/spi/ios/UIKitSPI.h:
+        Add some SPI.
+
+        * UIProcess/ios/WKPDFView.h:
+        * UIProcess/ios/WKPDFView.mm:
+        (-[WKPDFView _didLoadPDFDocument]):
+        (-[WKPDFView web_setContentProviderData:suggestedFilename:]):
+        Move creation of the UIPDFDocument (only possible if the CGPDFDocument is unlocked)
+        and initial setup of the page views out into _didLoadPDFDocument.
+
+        If the CGPDFDocument is locked, we'll show some UI to unlock it; otherwise
+        we'll continue on to _didLoadPDFDocument as previously.
+
+        (-[WKPDFView web_setMinimumSize:]):
+        Resize the password UI instead of the PDF pages if we have it.
+
+        (-[WKPDFView _computePageAndDocumentFrames]):
+        Don't bother doing any work revalidating PDF pages if the document is locked.
+
+        (-[WKPDFView _updatePasswordEntryField]):
+        Make sure that the UIDocumentPassword view is always the size of the scrollview.
+        This takes care of rotation.
+
+        (-[WKPDFView _keyboardDidShow:]):
+        Make sure that we scroll the password field around, if necessary, to keep it
+        on screen when editing begins.
+
+        (-[WKPDFView _showPasswordEntryField]):
+        (-[WKPDFView _hidePasswordEntryField]):
+        Adjust the background color (to match the UIDocumentPasswordView) and disable zooming
+        while it's up. The UIDocumentPassword view is installed into the scroll view
+        to match UIWebView behavior.
+
+        (-[WKPDFView userDidEnterPassword:forPasswordView:]):
+        (-[WKPDFView didBeginEditingPassword:inView:]):
+        (-[WKPDFView didEndEditingPassword:inView:]):
+        (-[WKPDFView _didFailToUnlock]):
+        Pop up a dialog informing the user that they entered the wrong password.
+
+        (-[WKPDFView _tryToUnlockWithPassword:]):
+        Try to unlock the document. If it succeeds, hide the unlock UI and go back to
+        _didLoadPDFDocument.
+
</ins><span class="cx"> 2015-04-24  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r183266.
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformspiiosUIKitSPIh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebKit2/Platform/spi/ios/UIKitSPI.h        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -32,6 +32,7 @@
</span><span class="cx"> #import &lt;UIKit/UIBarButtonItem_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIDatePicker_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIDevice_Private.h&gt;
</span><ins>+#import &lt;UIKit/UIDocumentPasswordView.h&gt;
</ins><span class="cx"> #import &lt;UIKit/UIFont_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIGeometry_Private.h&gt;
</span><span class="cx"> #import &lt;UIKit/UIGestureRecognizer_Private.h&gt;
</span><span class="lines">@@ -676,6 +677,33 @@
</span><span class="cx"> @property (nonatomic, assign, setter = _setIgnoreApplicationEntitlementForImport:, getter = _ignoreApplicationEntitlementForImport) BOOL _ignoreApplicationEntitlementForImport;
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+@protocol UIDocumentPasswordViewDelegate;
+
+@interface UIDocumentPasswordView : UIView &lt;UITextFieldDelegate&gt;
+@end
+
+@interface UIDocumentPasswordView (Details)
+
+- (id)initWithDocumentName:(NSString *)documentName;
+
+@property (nonatomic, assign) NSObject&lt;UIDocumentPasswordViewDelegate&gt; *passwordDelegate;
+@property (nonatomic, readonly) UITextField *passwordField;
+
+@end
+
+@protocol UIDocumentPasswordViewDelegate
+
+@required
+
+- (void)userDidEnterPassword:(NSString *)password forPasswordView:(UIDocumentPasswordView *)passwordView;
+
+@optional
+
+- (void)didBeginEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView;
+- (void)didEndEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView;
+
+@end
+
</ins><span class="cx"> #endif // USE(APPLE_INTERNAL_SDK)
</span><span class="cx"> 
</span><span class="cx"> @interface UIView (IPI)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKPDFViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKPDFView.h (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKPDFView.h        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebKit2/UIProcess/ios/WKPDFView.h        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -26,11 +26,11 @@
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> 
</span><span class="cx"> #import &quot;CorePDFSPI.h&quot;
</span><ins>+#import &quot;UIKitSPI.h&quot;
</ins><span class="cx"> #import &quot;WKActionSheetAssistant.h&quot;
</span><span class="cx"> #import &quot;WKWebViewContentProvider.h&quot;
</span><del>-#import &lt;UIKit/UIView.h&gt;
</del><span class="cx"> 
</span><del>-@interface WKPDFView : UIView &lt;WKWebViewContentProvider, UIPDFPageViewDelegate, UIPDFAnnotationControllerDelegate, WKActionSheetAssistantDelegate&gt;
</del><ins>+@interface WKPDFView : UIView &lt;WKWebViewContentProvider, UIPDFPageViewDelegate, UIPDFAnnotationControllerDelegate, WKActionSheetAssistantDelegate, UIDocumentPasswordViewDelegate&gt;
</ins><span class="cx"> 
</span><span class="cx"> @property (nonatomic, readonly) NSString *suggestedFilename;
</span><span class="cx"> @property (nonatomic, readonly) CGPDFDocumentRef pdfDocument;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessiosWKPDFViewmm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm (183292 => 183293)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm        2015-04-24 23:51:39 UTC (rev 183292)
+++ trunk/Source/WebKit2/UIProcess/ios/WKPDFView.mm        2015-04-24 23:54:59 UTC (rev 183293)
</span><span class="lines">@@ -40,6 +40,7 @@
</span><span class="cx"> #import &quot;_WKFindDelegate.h&quot;
</span><span class="cx"> #import &lt;MobileCoreServices/UTCoreTypes.h&gt;
</span><span class="cx"> #import &lt;WebCore/FloatRect.h&gt;
</span><ins>+#import &lt;WebCore/LocalizedStrings.h&gt;
</ins><span class="cx"> #import &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> #import &lt;wtf/Vector.h&gt;
</span><span class="cx"> 
</span><span class="lines">@@ -49,6 +50,8 @@
</span><span class="cx"> const CGFloat pdfMinimumZoomScale = 1;
</span><span class="cx"> const CGFloat pdfMaximumZoomScale = 5;
</span><span class="cx"> 
</span><ins>+const CGFloat passwordEntryFieldPadding = 10;
+
</ins><span class="cx"> const float overdrawHeightMultiplier = 1.5;
</span><span class="cx"> 
</span><span class="cx"> static const CGFloat smartMagnificationElementPadding = 0.05;
</span><span class="lines">@@ -65,10 +68,13 @@
</span><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> @implementation WKPDFView {
</span><ins>+    RetainPtr&lt;CGPDFDocumentRef&gt; _cgPDFDocument;
</ins><span class="cx">     RetainPtr&lt;UIPDFDocument&gt; _pdfDocument;
</span><span class="cx">     RetainPtr&lt;NSString&gt; _suggestedFilename;
</span><span class="cx">     RetainPtr&lt;WKPDFPageNumberIndicator&gt; _pageNumberIndicator;
</span><span class="cx"> 
</span><ins>+    RetainPtr&lt;UIDocumentPasswordView&gt; _passwordView;
+
</ins><span class="cx">     Vector&lt;PDFPageInfo&gt; _pages;
</span><span class="cx">     unsigned _centerPageNumber;
</span><span class="cx"> 
</span><span class="lines">@@ -125,6 +131,8 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)dealloc
</span><span class="cx"> {
</span><ins>+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+
</ins><span class="cx">     [self _clearPages];
</span><span class="cx">     [_pageNumberIndicator removeFromSuperview];
</span><span class="cx">     dispatch_release(_findQueue);
</span><span class="lines">@@ -152,6 +160,17 @@
</span><span class="cx">     _pages.clear();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)_didLoadPDFDocument
+{
+    _pdfDocument = adoptNS([[UIPDFDocument alloc] initWithCGPDFDocument:_cgPDFDocument.get()]);
+
+    // FIXME: Restore the scroll position and page scale if navigating from the back/forward list.
+
+    [self _computePageAndDocumentFrames];
+    [self _revalidateViews];
+    [self _scrollToFragment:_webView.URL.fragment];
+}
+
</ins><span class="cx"> - (void)web_setContentProviderData:(NSData *)data suggestedFilename:(NSString *)filename
</span><span class="cx"> {
</span><span class="cx">     _suggestedFilename = adoptNS([filename copy]);
</span><span class="lines">@@ -159,18 +178,26 @@
</span><span class="cx">     [self _clearPages];
</span><span class="cx"> 
</span><span class="cx">     RetainPtr&lt;CGDataProviderRef&gt; dataProvider = adoptCF(CGDataProviderCreateWithCFData((CFDataRef)data));
</span><del>-    RetainPtr&lt;CGPDFDocumentRef&gt; cgPDFDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
-    _pdfDocument = adoptNS([[UIPDFDocument alloc] initWithCGPDFDocument:cgPDFDocument.get()]);
</del><ins>+    _cgPDFDocument = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get()));
</ins><span class="cx"> 
</span><del>-    // FIXME: restore the scroll position and page scale if navigating from the back/forward list.
</del><ins>+    if (!_cgPDFDocument)
+        return;
</ins><span class="cx"> 
</span><del>-    [self _computePageAndDocumentFrames];
-    [self _revalidateViews];
-    [self _scrollToFragment:_webView.URL.fragment];
</del><ins>+    if (CGPDFDocumentIsUnlocked(_cgPDFDocument.get())) {
+        [self _didLoadPDFDocument];
+        return;
+    }
+
+    [self _showPasswordEntryField];
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> - (void)web_setMinimumSize:(CGSize)size
</span><span class="cx"> {
</span><ins>+    if (_passwordView) {
+        [self _updatePasswordEntryField];
+        return;
+    }
+
</ins><span class="cx">     _minimumSize = size;
</span><span class="cx"> 
</span><span class="cx">     CGFloat oldDocumentLeftFraction = 0;
</span><span class="lines">@@ -328,6 +355,9 @@
</span><span class="cx"> 
</span><span class="cx"> - (void)_computePageAndDocumentFrames
</span><span class="cx"> {
</span><ins>+    if (_passwordView)
+        return;
+
</ins><span class="cx">     NSUInteger pageCount = [_pdfDocument numberOfPages];
</span><span class="cx">     [_pageNumberIndicator setPageCount:pageCount];
</span><span class="cx">     
</span><span class="lines">@@ -693,6 +723,110 @@
</span><span class="cx">     return _webView-&gt;_page-&gt;uiClient().actionsForElement(element, WTF::move(defaultActions));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#pragma mark Password protection UI
+
+- (void)_updatePasswordEntryField
+{
+    [_passwordView setFrame:CGRectMake(0, 0, _webView.bounds.size.width, _webView.bounds.size.height)];
+    [_scrollView setContentSize:[_passwordView bounds].size];
+}
+
+- (void)_keyboardDidShow:(NSNotification *)notification
+{
+    UITextField *passwordField = [_passwordView passwordField];
+    if (!passwordField.isEditing)
+        return;
+
+    CGRect keyboardRect = [UIPeripheralHost visiblePeripheralFrame];
+    if (CGRectIsEmpty(keyboardRect))
+        return;
+
+    UIWindow *window = _scrollView.window;
+    keyboardRect = [window convertRect:keyboardRect fromWindow:nil];
+    keyboardRect = [_scrollView convertRect:keyboardRect fromView:window];
+
+    CGRect passwordFieldFrame = [passwordField convertRect:passwordField.bounds toView:_scrollView];
+
+    CGSize contentSize = [_passwordView bounds].size;
+    contentSize.height += CGRectGetHeight(keyboardRect);
+    [_scrollView setContentSize:contentSize];
+
+    if (CGRectIntersectsRect(passwordFieldFrame, keyboardRect)) {
+        CGFloat yDelta = CGRectGetMaxY(passwordFieldFrame) - CGRectGetMinY(keyboardRect);
+
+        CGPoint contentOffset = _scrollView.contentOffset;
+        contentOffset.y += yDelta + passwordEntryFieldPadding;
+
+        [_scrollView setContentOffset:contentOffset animated:YES];
+    }
+}
+
+- (void)_showPasswordEntryField
+{
+    [_scrollView setMinimumZoomScale:1];
+    [_scrollView setMaximumZoomScale:1];
+    [_scrollView setBackgroundColor:[UIColor groupTableViewBackgroundColor]];
+
+    _passwordView = adoptNS([[UIDocumentPasswordView alloc] initWithDocumentName:_suggestedFilename.get()]);
+    [_passwordView setPasswordDelegate:self];
+
+    [self _updatePasswordEntryField];
+
+    [self addSubview:_passwordView.get()];
+}
+
+- (void)_hidePasswordEntryField
+{
+    [_passwordView removeFromSuperview];
+    _passwordView = nil;
+
+    [_scrollView setMinimumZoomScale:pdfMinimumZoomScale];
+    [_scrollView setMaximumZoomScale:pdfMaximumZoomScale];
+    [_scrollView setBackgroundColor:[UIColor grayColor]];
+}
+
+- (void)userDidEnterPassword:(NSString *)password forPasswordView:(UIDocumentPasswordView *)passwordView
+{
+    [self _tryToUnlockWithPassword:password];
+}
+
+- (void)didBeginEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView
+{
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
+}
+
+- (void)didEndEditingPassword:(UITextField *)passwordField inView:(UIDocumentPasswordView *)passwordView
+{
+    [_scrollView setContentSize:[_passwordView frame].size];
+    [_scrollView setContentOffset:CGPointMake(-_scrollView.contentInset.left, -_scrollView.contentInset.top) animated:YES];
+
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
+}
+
+- (void)_didFailToUnlock
+{
+    [[_passwordView passwordField] setText:@&quot;&quot;];
+    UIAlertController* alert = [UIAlertController alertControllerWithTitle:WEB_UI_STRING(&quot;The document could not be opened with that password.&quot;, &quot;PDF password failure alert message&quot;) message:@&quot;&quot; preferredStyle:UIAlertControllerStyleAlert];
+
+    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle:WEB_UI_STRING_KEY(&quot;OK&quot;, &quot;OK (PDF password failure alert)&quot;, &quot;OK button label in PDF password failure alert&quot;) style:UIAlertActionStyleDefault handler:[](UIAlertAction *) { }];
+    
+    [alert addAction:defaultAction];
+
+    [self.window.rootViewController presentViewController:alert animated:YES completion:nil];
+}
+
+- (BOOL)_tryToUnlockWithPassword:(NSString *)password
+{
+    if (CGPDFDocumentUnlockWithPassword(_cgPDFDocument.get(), [password UTF8String])) {
+        [self _hidePasswordEntryField];
+        [self _didLoadPDFDocument];
+        return YES;
+    }
+
+    [self _didFailToUnlock];
+    return NO;
+}
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif /* PLATFORM(IOS) */
</span></span></pre>
</div>
</div>

</body>
</html>