Changeset 21430 in webkit
- Timestamp:
- May 12, 2007, 2:22:08 PM (18 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r21428 r21430 1 2007-05-11 Brady Eidson <beidson@apple.com> 2 3 Reviewed by Darin and Geoff 4 5 Fix for http://bugs.webkit.org/show_bug.cgi?id=13630 6 and 7 <rdar://problem/4873628> 8 9 Back/Forward cache should work with pages with login fields. 10 11 First change is to relocate the "useSecureKeyboardEntry" flag to the document. This lets 12 it persist through page cache transitions and it is truly a per-document concept more than 13 per-frame anyways since its the document that has a password field, not the frame. 14 15 Second change is to introduce the concept of an Element getting a "didRestoreFromCache()" callback. 16 The idea is for elements to register with the document if they need work to be done when the 17 page comes out of the back/forward cache. Currently the only client of this service is 18 HTMLInputElements that are input type == PASSWORD. Such an element's implementation for this 19 method is to call reset() 20 21 Finally, after a page is restored from the cache we have the document send the didRestoreFromCache() 22 callback to its registered Elements. The whole design is to clear the password fields after 23 restoring the page instead of when caching the page because we want to defer work for the common 24 case - there shouldn't be extra work here just to navigate away from a page when the common case 25 is that you'll never go back! 26 27 No layout tests possible until http://bugs.webkit.org/show_bug.cgi?id=13672 is resolved 28 29 * dom/Document.cpp: 30 (WebCore::Document::Document): 31 (WebCore::Document::registerForDidRestoreFromCacheCallback): Add an Element to the special page-restoration callback list 32 (WebCore::Document::unregisterForDidRestoreFromCacheCallback): Remove such an element 33 (WebCore::Document::didRestoreFromCache): Called by FrameLoader - dispatch to all the registered elements 34 (WebCore::Document::setUseSecureKeyboardEntryWhenActive): Set the local flag and call updateSecureKeyboardEntryIfActive 35 on the Frame 36 (WebCore::Document::useSecureKeyboardEntryWhenActive): Return the flag 37 38 * dom/Document.h: 39 (WebCore::Document::unregisterFormElementWithState): Renamed 40 41 * dom/Element.h: 42 (WebCore::Element::didRestoreFromCache): Added virtual base method 43 44 * html/HTMLInputElement.cpp: 45 (WebCore::HTMLInputElement::~HTMLInputElement): Deregister from the document if inputType == PASSWORD 46 (WebCore::HTMLInputElement::dispatchFocusEvent): Set the flag on the document, not the frame 47 (WebCore::HTMLInputElement::dispatchBlurEvent): Ditto 48 (WebCore::HTMLInputElement::setInputType): If changing to/from PASSWORD, register/deregister in the document accordingly 49 (WebCore::HTMLInputElement::attach): Call registerForDidRestoreFromCacheCallback(this) instead of passwordFieldAdded() 50 (WebCore::HTMLInputElement::didRestoreFromCache): Call reset(); 51 * html/HTMLInputElement.h: 52 53 * html/HTMLSelectElement.cpp: 54 (WebCore::HTMLSelectElement::~HTMLSelectElement): Renamed deregisterFormElementWithState to unregisterFormElementWithState 55 * html/HTMLTextAreaElement.cpp: 56 (WebCore::HTMLTextAreaElement::~HTMLTextAreaElement): Ditto 57 58 * loader/FrameLoader.cpp: 59 (WebCore::FrameLoader::canCachePage): Remove the check for password fields - they're allowed now! 60 (WebCore::FrameLoader::opened): Tell the document to dispatch to the registered elements 61 (WebCore::FrameLoader::saveDocumentState): Remove the check for password fields. Turns out that when we grab a copy a the 62 form state we're only copying the state of form elements that are registered with the Document - and that set 63 explicitly excludes Password elements 64 65 * page/Frame.cpp: 66 (WebCore::Frame::setDocument): If the frame is active, set the setUseSecureKeyboardEntry based on the setting contained 67 in the new document 68 (WebCore::Frame::updateSecureKeyboardEntryIfActive): Notification for the secure entry flag changing - if the Frame is 69 active, then update to the new setting from the document 70 (WebCore::Frame::setIsActive): Grab the useSecureKeyboardEntry flag from the document instead of FramePrivate 71 (WebCore::FramePrivate::FramePrivate): 72 * page/Frame.h: 73 * page/FramePrivate.h: 74 1 75 2007-05-12 David Hyatt <hyatt@apple.com> 2 76 -
trunk/WebCore/dom/Document.cpp
r21420 r21430 287 287 #endif 288 288 , m_savedRenderer(0) 289 , m_passwordFields(0)290 289 , m_secureForms(0) 291 290 , m_designMode(inherit) … … 300 299 , m_inPageCache(false) 301 300 , m_isAllowedToLoadLocalResources(false) 301 , m_useSecureKeyboardEntryWhenActive(false) 302 302 #if USE(LOW_BANDWIDTH_DISPLAY) 303 303 , m_inLowBandwidthDisplay(false) … … 2684 2684 } 2685 2685 2686 void Document::passwordFieldAdded() 2687 { 2688 m_passwordFields++; 2689 } 2690 2691 void Document::passwordFieldRemoved() 2692 { 2693 ASSERT(m_passwordFields > 0); 2694 m_passwordFields--; 2695 } 2696 2697 bool Document::hasPasswordField() const 2698 { 2699 return m_passwordFields > 0; 2686 void Document::registerForDidRestoreFromCacheCallback(Element* e) 2687 { 2688 m_didRestorePageCallbackSet.add(e); 2689 } 2690 2691 void Document::unregisterForDidRestoreFromCacheCallback(Element* e) 2692 { 2693 m_didRestorePageCallbackSet.remove(e); 2694 } 2695 2696 void Document::didRestoreFromCache() 2697 { 2698 HashSet<Element*>::iterator it = m_didRestorePageCallbackSet.begin(); 2699 for (; it != m_didRestorePageCallbackSet.end(); ++it) 2700 (*it)->didRestoreFromCache(); 2700 2701 } 2701 2702 … … 3605 3606 } 3606 3607 3607 } 3608 void Document::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard) 3609 { 3610 if (m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard) 3611 return; 3612 3613 m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard; 3614 m_frame->updateSecureKeyboardEntryIfActive(); 3615 } 3616 3617 bool Document::useSecureKeyboardEntryWhenActive() const 3618 { 3619 return m_useSecureKeyboardEntryWhenActive; 3620 } 3621 3622 } -
trunk/WebCore/dom/Document.h
r21179 r21430 291 291 // Machinery for saving and restoring state when you leave and then go back to a page. 292 292 void registerFormElementWithState(HTMLGenericFormElement* e) { m_formElementsWithState.add(e); } 293 void deregisterFormElementWithState(HTMLGenericFormElement* e) { m_formElementsWithState.remove(e); }293 void unregisterFormElementWithState(HTMLGenericFormElement* e) { m_formElementsWithState.remove(e); } 294 294 Vector<String> formElementsState() const; 295 295 void setStateForNewFormElements(const Vector<String>&); … … 635 635 bool isAllowedToLoadLocalResources() const { return m_isAllowedToLoadLocalResources; } 636 636 637 void setUseSecureKeyboardEntryWhenActive(bool); 638 bool useSecureKeyboardEntryWhenActive() const; 639 637 640 #if USE(LOW_BANDWIDTH_DISPLAY) 638 641 void setDocLoader(DocLoader* loader) { m_docLoader = loader; } … … 702 705 FormElementStateMap m_stateForNewFormElements; 703 706 707 HashSet<Element*> m_didRestorePageCallbackSet; 708 704 709 Color m_linkColor; 705 710 Color m_visitedLinkColor; … … 767 772 void setInPageCache(bool flag); 768 773 769 void passwordFieldAdded(); 770 void passwordFieldRemoved(); 771 bool hasPasswordField() const; 774 // Elements can register themselves for the "didRestoreFromCache()" callback which will be 775 // called if the document is restored from the Page Cache 776 void registerForDidRestoreFromCacheCallback(Element*); 777 void unregisterForDidRestoreFromCacheCallback(Element*); 778 779 void didRestoreFromCache(); 772 780 773 781 void secureFormAdded(); … … 816 824 mutable String m_domain; 817 825 RenderObject* m_savedRenderer; 818 int m_passwordFields;819 826 int m_secureForms; 820 827 … … 854 861 855 862 bool m_isAllowedToLoadLocalResources; 863 864 bool m_useSecureKeyboardEntryWhenActive; 856 865 857 866 #if USE(LOW_BANDWIDTH_DISPLAY) -
trunk/WebCore/dom/Element.h
r21184 r21430 183 183 void setMinimumSizeForResizing(const IntSize&); 184 184 185 // The following method is called when a Document is restored from the page cache 186 // and the element has registered itself with the Document via registerForDidRestorePageCallback() 187 virtual void didRestoreFromCache() { } 188 185 189 private: 186 190 ElementRareData* rareData(); -
trunk/WebCore/html/HTMLInputElement.cpp
r21055 r21430 137 137 HTMLInputElement::~HTMLInputElement() 138 138 { 139 document()->deregisterFormElementWithState(this); 139 document()->unregisterFormElementWithState(this); 140 document()->unregisterForDidRestoreFromCacheCallback(this); 140 141 delete m_imageLoader; 141 142 } … … 233 234 setAutofilled(false); 234 235 if (inputType() == PASSWORD && document()->frame()) 235 document()-> frame()->setUseSecureKeyboardEntryWhenActive(true);236 document()->setUseSecureKeyboardEntryWhenActive(true); 236 237 } 237 238 HTMLGenericFormElement::dispatchFocusEvent(); … … 242 243 if (isTextField() && document()->frame()) { 243 244 if (inputType() == PASSWORD) 244 document()-> frame()->setUseSecureKeyboardEntryWhenActive(false);245 document()->setUseSecureKeyboardEntryWhenActive(false); 245 246 document()->frame()->textFieldDidEndEditing(this); 246 247 } … … 306 307 307 308 bool didStoreValue = storesValueSeparateFromAttribute(); 308 bool didMaintainState = inputType() != PASSWORD;309 bool wasPasswordField = inputType() == PASSWORD; 309 310 bool didRespectHeightAndWidth = respectHeightAndWidthAttrs(); 310 311 m_type = newType; 311 312 bool willStoreValue = storesValueSeparateFromAttribute(); 312 bool willMaintainState = inputType() != PASSWORD;313 bool isPasswordField = inputType() == PASSWORD; 313 314 bool willRespectHeightAndWidth = respectHeightAndWidthAttrs(); 314 315 … … 322 323 recheckValue(); 323 324 324 if (w illMaintainState && !didMaintainState)325 if (wasPasswordField && !isPasswordField) { 325 326 document()->registerFormElementWithState(this); 326 else if (!willMaintainState && didMaintainState) 327 document()->deregisterFormElementWithState(this); 327 document()->unregisterForDidRestoreFromCacheCallback(this); 328 } else if (!wasPasswordField && isPasswordField) { 329 document()->unregisterFormElementWithState(this); 330 document()->registerForDidRestoreFromCacheCallback(this); 331 } 328 332 329 333 if (didRespectHeightAndWidth != willRespectHeightAndWidth) { … … 759 763 } 760 764 761 // note we don't deal with calling passwordFieldRemoved() on detach, because the timing762 // was such that it cleared our state too early763 765 if (inputType() == PASSWORD) 764 document()-> passwordFieldAdded();766 document()->unregisterForDidRestoreFromCacheCallback(this); 765 767 } 766 768 … … 1471 1473 return static_cast<RenderTextControl*>(renderer())->selection(cachedSelStart, cachedSelEnd); 1472 1474 } 1475 1476 void HTMLInputElement::didRestoreFromCache() 1477 { 1478 ASSERT(inputType() == PASSWORD); 1479 reset(); 1480 } 1473 1481 1474 1482 } // namespace -
trunk/WebCore/html/HTMLInputElement.h
r20440 r21430 184 184 String constrainValue(const String& proposedValue) const; 185 185 186 virtual void didRestoreFromCache(); 187 186 188 protected: 187 189 AtomicString m_name; -
trunk/WebCore/html/HTMLSelectElement.cpp
r21269 r21430 97 97 HTMLSelectElement::~HTMLSelectElement() 98 98 { 99 document()-> deregisterFormElementWithState(this);99 document()->unregisterFormElementWithState(this); 100 100 } 101 101 -
trunk/WebCore/html/HTMLTextAreaElement.cpp
r21224 r21430 61 61 HTMLTextAreaElement::~HTMLTextAreaElement() 62 62 { 63 document()-> deregisterFormElementWithState(this);63 document()->unregisterFormElementWithState(this); 64 64 } 65 65 -
trunk/WebCore/loader/FrameLoader.cpp
r21421 r21430 1617 1617 && !m_frame->document()->applets()->length() 1618 1618 && !m_frame->document()->hasWindowEventListener(unloadEvent) 1619 // If you change the following to allow caching of documents with password fields,1620 // you also need to make sure that Frame::setDocument turns on secure keyboard1621 // entry mode if the document's focused node requires it.1622 && !m_frame->document()->hasPasswordField()1623 1619 && m_frame->page() 1624 1620 && m_frame->page()->backForwardList()->pageCacheSize() != 0 … … 3245 3241 3246 3242 if (m_documentLoader->isLoadingFromCachedPage()) { 3243 m_frame->document()->didRestoreFromCache(); 3244 3247 3245 // Force a layout to update view size and thereby update scrollbars. 3248 3246 m_client->forceLayout(); … … 3743 3741 return; 3744 3742 3745 // Do not save doc state if the page has a password field and aform that would be submitted via https.3743 // Do not save doc state if the page has a form that would be submitted via https. 3746 3744 Document* document = m_frame->document(); 3747 3745 ASSERT(document); 3748 if (document->hasPasswordField() && document->hasSecureForm())3749 return;3750 3746 3747 if (document->hasSecureForm()) 3748 return; 3749 3751 3750 // For a standard page load, we will have a previous item set, which will be used to 3752 3751 // store the form state. However, in some cases we will have no previous item, and -
trunk/WebCore/page/Frame.cpp
r21387 r21430 308 308 void Frame::setDocument(PassRefPtr<Document> newDoc) 309 309 { 310 if (d) { 311 if (d->m_doc) { 312 if (d->m_doc->attached()) 313 d->m_doc->detach(); 314 // The old document's focused node may have turned on secure keyboard entry. 315 // Now that it's going away, turn it off. Documents containing a password 316 // field cannot enter the page cache, therefore |newDoc| cannot contain a 317 // focused password field, and hence we can always set to false. 318 setUseSecureKeyboardEntryWhenActive(false); 319 } 320 d->m_doc = newDoc; 321 if (d->m_doc && !d->m_doc->attached()) 322 d->m_doc->attach(); 323 } 310 if (d->m_doc && d->m_doc->attached()) 311 d->m_doc->detach(); 312 313 d->m_doc = newDoc; 314 if (d->m_doc && d->m_isActive) 315 setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive()); 316 317 if (d->m_doc && !d->m_doc->attached()) 318 d->m_doc->attach(); 324 319 } 325 320 … … 790 785 #endif 791 786 792 void Frame::setUseSecureKeyboardEntryWhenActive(bool usesSecureKeyboard) 793 { 794 if (d->m_useSecureKeyboardEntryWhenActive == usesSecureKeyboard) 795 return; 796 d->m_useSecureKeyboardEntryWhenActive = usesSecureKeyboard; 797 787 void Frame::updateSecureKeyboardEntryIfActive() 788 { 798 789 if (d->m_isActive) 799 setUseSecureKeyboardEntry( usesSecureKeyboard);790 setUseSecureKeyboardEntry(d->m_doc->useSecureKeyboardEntryWhenActive()); 800 791 } 801 792 … … 1518 1509 1519 1510 // Secure keyboard entry is set by the active frame. 1520 if (d->m_ useSecureKeyboardEntryWhenActive)1511 if (d->m_doc->useSecureKeyboardEntryWhenActive()) 1521 1512 setUseSecureKeyboardEntry(flag); 1522 1513 } … … 1871 1862 , m_caretPaint(true) 1872 1863 , m_isActive(false) 1873 , m_useSecureKeyboardEntryWhenActive(false)1874 1864 , m_lifeSupportTimer(thisFrame, &Frame::lifeSupportTimerFired) 1875 1865 , m_loader(new FrameLoader(thisFrame, frameLoaderClient)) -
trunk/WebCore/page/Frame.h
r21387 r21430 317 317 bool isContentEditable() const; // if true, everything in frame is editable 318 318 319 void setUseSecureKeyboardEntryWhenActive(bool);319 void updateSecureKeyboardEntryIfActive(); 320 320 321 321 CSSMutableStyleDeclaration* typingStyle() const; -
trunk/WebCore/page/FramePrivate.h
r20901 r21430 98 98 bool m_caretPaint : 1; 99 99 bool m_isActive : 1; 100 bool m_useSecureKeyboardEntryWhenActive : 1;101 100 102 101 RefPtr<CSSMutableStyleDeclaration> m_typingStyle;
Note:
See TracChangeset
for help on using the changeset viewer.