Changeset 257503 in webkit
- Timestamp:
- Feb 26, 2020 12:57:49 PM (4 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r257487 r257503 1 2020-02-26 Chris Dumez <cdumez@apple.com> 2 3 Make sure a client cannot cause a whole DOM tree to get leaked by simply holding on to a WKBundleNodeHandle 4 https://bugs.webkit.org/show_bug.cgi?id=208218 5 6 Reviewed by Ryosuke Niwa. 7 8 Make sure a client cannot cause a whole DOM tree to get leaked by simply holding on to a WKBundleNodeHandle. 9 Previously, WKBundleNodeHandle would ref its node, which would keep the whole HTML document alive. To protect 10 against this, InjectedBundleNodeHandle is now an ActiveDOMObject which nulls out its node RefPtr when the 11 document is getting ready for destruction (i.e. ActiveDOMObject::stop() is called). 12 13 * WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.cpp: 14 (WebKit::InjectedBundleNodeHandle::InjectedBundleNodeHandle): 15 (WebKit::InjectedBundleNodeHandle::~InjectedBundleNodeHandle): 16 (WebKit::InjectedBundleNodeHandle::coreNode): 17 (WebKit::InjectedBundleNodeHandle::document): 18 (WebKit::InjectedBundleNodeHandle::elementBounds): 19 (WebKit::InjectedBundleNodeHandle::renderRect): 20 (WebKit::InjectedBundleNodeHandle::renderedImage): 21 (WebKit::InjectedBundleNodeHandle::visibleRange): 22 (WebKit::InjectedBundleNodeHandle::setHTMLInputElementValueForUser): 23 (WebKit::InjectedBundleNodeHandle::setHTMLInputElementSpellcheckEnabled): 24 (WebKit::InjectedBundleNodeHandle::isHTMLInputElementAutoFilled const): 25 (WebKit::InjectedBundleNodeHandle::isHTMLInputElementAutoFilledAndViewable const): 26 (WebKit::InjectedBundleNodeHandle::setHTMLInputElementAutoFilled): 27 (WebKit::InjectedBundleNodeHandle::setHTMLInputElementAutoFilledAndViewable): 28 (WebKit::InjectedBundleNodeHandle::isHTMLInputElementAutoFillButtonEnabled const): 29 (WebKit::InjectedBundleNodeHandle::setHTMLInputElementAutoFillButtonEnabled): 30 (WebKit::InjectedBundleNodeHandle::htmlInputElementAutoFillButtonType const): 31 (WebKit::InjectedBundleNodeHandle::htmlInputElementLastAutoFillButtonType const): 32 (WebKit::InjectedBundleNodeHandle::isAutoFillAvailable const): 33 (WebKit::InjectedBundleNodeHandle::setAutoFillAvailable): 34 (WebKit::InjectedBundleNodeHandle::htmlInputElementAutoFillButtonBounds): 35 (WebKit::InjectedBundleNodeHandle::htmlInputElementLastChangeWasUserEdit): 36 (WebKit::InjectedBundleNodeHandle::htmlTextAreaElementLastChangeWasUserEdit): 37 (WebKit::InjectedBundleNodeHandle::isTextField const): 38 (WebKit::InjectedBundleNodeHandle::htmlTableCellElementCellAbove): 39 (WebKit::InjectedBundleNodeHandle::documentFrame): 40 (WebKit::InjectedBundleNodeHandle::htmlFrameElementContentFrame): 41 (WebKit::InjectedBundleNodeHandle::htmlIFrameElementContentFrame): 42 (WebKit::InjectedBundleNodeHandle::stop): 43 (WebKit::InjectedBundleNodeHandle::activeDOMObjectName const): 44 * WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.h: 45 1 46 2020-02-26 Daniel Bates <dabates@apple.com> 2 47 -
trunk/Source/WebKit/WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.cpp
r257483 r257503 85 85 Ref<InjectedBundleNodeHandle> InjectedBundleNodeHandle::getOrCreate(Node& node) 86 86 { 87 DOMNodeHandleCache::AddResult result = domNodeHandleCache().add(&node, nullptr);88 if (!result.isNewEntry)89 return Ref<InjectedBundleNodeHandle>(*result.iterator->value); 90 91 Ref<InjectedBundleNodeHandle> nodeHandle = InjectedBundleNodeHandle::create(node);92 result.iterator->value = nodeHandle.ptr();87 if (auto* existingHandle = domNodeHandleCache().get(&node)) 88 return Ref<InjectedBundleNodeHandle>(*existingHandle); 89 90 auto nodeHandle = InjectedBundleNodeHandle::create(node); 91 if (nodeHandle->coreNode()) 92 domNodeHandleCache().add(nodeHandle->coreNode(), nodeHandle.ptr()); 93 93 return nodeHandle; 94 94 } … … 96 96 Ref<InjectedBundleNodeHandle> InjectedBundleNodeHandle::create(Node& node) 97 97 { 98 return adoptRef(*new InjectedBundleNodeHandle(node)); 98 auto handle = adoptRef(*new InjectedBundleNodeHandle(node)); 99 handle->suspendIfNeeded(); 100 return handle; 99 101 } 100 102 101 103 InjectedBundleNodeHandle::InjectedBundleNodeHandle(Node& node) 102 : m_node(node) 104 : ActiveDOMObject(node.document()) 105 , m_node(&node) 103 106 { 104 107 } … … 106 109 InjectedBundleNodeHandle::~InjectedBundleNodeHandle() 107 110 { 108 domNodeHandleCache().remove(m_node.ptr()); 111 if (m_node) 112 domNodeHandleCache().remove(m_node.get()); 109 113 } 110 114 111 115 Node* InjectedBundleNodeHandle::coreNode() 112 116 { 113 return m_node.ptr(); 114 } 115 116 Ref<InjectedBundleNodeHandle> InjectedBundleNodeHandle::document() 117 { 117 return m_node.get(); 118 } 119 120 RefPtr<InjectedBundleNodeHandle> InjectedBundleNodeHandle::document() 121 { 122 if (!m_node) 123 return nullptr; 124 118 125 return getOrCreate(m_node->document()); 119 126 } … … 127 134 return IntRect(); 128 135 129 return downcast<Element>( m_node.get()).boundsInRootViewSpace();136 return downcast<Element>(*m_node).boundsInRootViewSpace(); 130 137 } 131 138 132 139 IntRect InjectedBundleNodeHandle::renderRect(bool* isReplaced) 133 140 { 141 if (!m_node) 142 return { }; 143 134 144 return m_node->pixelSnappedRenderRect(isReplaced); 135 145 } … … 189 199 RefPtr<WebImage> InjectedBundleNodeHandle::renderedImage(SnapshotOptions options, bool shouldExcludeOverflow, const Optional<float>& bitmapWidth) 190 200 { 201 if (!m_node) 202 return nullptr; 203 191 204 Frame* frame = m_node->document().frame(); 192 205 if (!frame) … … 211 224 } 212 225 213 frameView->setNodeToDraw(m_node. ptr());226 frameView->setNodeToDraw(m_node.get()); 214 227 auto image = imageForRect(frameView, paintingRect, bitmapWidth, options); 215 228 frameView->setNodeToDraw(0); … … 220 233 RefPtr<InjectedBundleRangeHandle> InjectedBundleNodeHandle::visibleRange() 221 234 { 222 VisiblePosition start = firstPositionInNode(m_node.ptr()); 223 VisiblePosition end = lastPositionInNode(m_node.ptr()); 235 if (!m_node) 236 return nullptr; 237 238 VisiblePosition start = firstPositionInNode(m_node.get()); 239 VisiblePosition end = lastPositionInNode(m_node.get()); 224 240 225 241 RefPtr<Range> range = makeRange(start, end); … … 232 248 return; 233 249 234 downcast<HTMLInputElement>( m_node.get()).setValueForUser(value);250 downcast<HTMLInputElement>(*m_node).setValueForUser(value); 235 251 } 236 252 … … 240 256 return; 241 257 242 downcast<HTMLInputElement>( m_node.get()).setSpellcheckDisabledExceptTextReplacement(!enabled);258 downcast<HTMLInputElement>(*m_node).setSpellcheckDisabledExceptTextReplacement(!enabled); 243 259 } 244 260 … … 248 264 return false; 249 265 250 return downcast<HTMLInputElement>( m_node.get()).isAutoFilled();266 return downcast<HTMLInputElement>(*m_node).isAutoFilled(); 251 267 } 252 268 … … 256 272 return false; 257 273 258 return downcast<HTMLInputElement>( m_node.get()).isAutoFilledAndViewable();274 return downcast<HTMLInputElement>(*m_node).isAutoFilledAndViewable(); 259 275 } 260 276 … … 264 280 return; 265 281 266 downcast<HTMLInputElement>( m_node.get()).setAutoFilled(filled);282 downcast<HTMLInputElement>(*m_node).setAutoFilled(filled); 267 283 } 268 284 … … 272 288 return; 273 289 274 downcast<HTMLInputElement>( m_node.get()).setAutoFilledAndViewable(autoFilledAndViewable);290 downcast<HTMLInputElement>(*m_node).setAutoFilledAndViewable(autoFilledAndViewable); 275 291 } 276 292 … … 280 296 return false; 281 297 282 return downcast<HTMLInputElement>( m_node.get()).autoFillButtonType() != AutoFillButtonType::None;298 return downcast<HTMLInputElement>(*m_node).autoFillButtonType() != AutoFillButtonType::None; 283 299 } 284 300 … … 288 304 return; 289 305 290 downcast<HTMLInputElement>( m_node.get()).setShowAutoFillButton(autoFillButtonType);306 downcast<HTMLInputElement>(*m_node).setShowAutoFillButton(autoFillButtonType); 291 307 } 292 308 … … 295 311 if (!is<HTMLInputElement>(m_node)) 296 312 return AutoFillButtonType::None; 297 return downcast<HTMLInputElement>( m_node.get()).autoFillButtonType();313 return downcast<HTMLInputElement>(*m_node).autoFillButtonType(); 298 314 } 299 315 … … 302 318 if (!is<HTMLInputElement>(m_node)) 303 319 return AutoFillButtonType::None; 304 return downcast<HTMLInputElement>( m_node.get()).lastAutoFillButtonType();320 return downcast<HTMLInputElement>(*m_node).lastAutoFillButtonType(); 305 321 } 306 322 … … 310 326 return false; 311 327 312 return downcast<HTMLInputElement>( m_node.get()).isAutoFillAvailable();328 return downcast<HTMLInputElement>(*m_node).isAutoFillAvailable(); 313 329 } 314 330 … … 318 334 return; 319 335 320 downcast<HTMLInputElement>( m_node.get()).setAutoFillAvailable(autoFillAvailable);336 downcast<HTMLInputElement>(*m_node).setAutoFillAvailable(autoFillAvailable); 321 337 } 322 338 … … 326 342 return IntRect(); 327 343 328 auto autoFillButton = downcast<HTMLInputElement>( m_node.get()).autoFillButtonElement();344 auto autoFillButton = downcast<HTMLInputElement>(*m_node).autoFillButtonElement(); 329 345 if (!autoFillButton) 330 346 return IntRect(); … … 338 354 return false; 339 355 340 return downcast<HTMLInputElement>( m_node.get()).lastChangeWasUserEdit();356 return downcast<HTMLInputElement>(*m_node).lastChangeWasUserEdit(); 341 357 } 342 358 … … 346 362 return false; 347 363 348 return downcast<HTMLTextAreaElement>( m_node.get()).lastChangeWasUserEdit();364 return downcast<HTMLTextAreaElement>(*m_node).lastChangeWasUserEdit(); 349 365 } 350 366 … … 354 370 return false; 355 371 356 return downcast<HTMLInputElement>( m_node.get()).isTextField();372 return downcast<HTMLInputElement>(*m_node).isTextField(); 357 373 } 358 374 … … 367 383 return nullptr; 368 384 369 return getOrCreate(downcast<HTMLTableCellElement>( m_node.get()).cellAbove());385 return getOrCreate(downcast<HTMLTableCellElement>(*m_node).cellAbove()); 370 386 } 371 387 372 388 RefPtr<WebFrame> InjectedBundleNodeHandle::documentFrame() 373 389 { 374 if (!m_node ->isDocumentNode())375 return nullptr; 376 377 Frame* frame = downcast<Document>( m_node.get()).frame();390 if (!m_node || !m_node->isDocumentNode()) 391 return nullptr; 392 393 Frame* frame = downcast<Document>(*m_node).frame(); 378 394 if (!frame) 379 395 return nullptr; … … 387 403 return nullptr; 388 404 389 Frame* frame = downcast<HTMLFrameElement>( m_node.get()).contentFrame();405 Frame* frame = downcast<HTMLFrameElement>(*m_node).contentFrame(); 390 406 if (!frame) 391 407 return nullptr; … … 399 415 return nullptr; 400 416 401 Frame* frame = downcast<HTMLIFrameElement>( m_node.get()).contentFrame();417 Frame* frame = downcast<HTMLIFrameElement>(*m_node).contentFrame(); 402 418 if (!frame) 403 419 return nullptr; … … 406 422 } 407 423 424 void InjectedBundleNodeHandle::stop() 425 { 426 // Invalidate handles to nodes inside documents that are about to be destroyed in order to prevent leaks. 427 if (m_node) { 428 domNodeHandleCache().remove(m_node.get()); 429 m_node = nullptr; 430 } 431 } 432 433 const char* InjectedBundleNodeHandle::activeDOMObjectName() const 434 { 435 return "InjectedBundleNodeHandle"; 436 } 437 408 438 } // namespace WebKit -
trunk/Source/WebKit/WebProcess/InjectedBundle/DOM/InjectedBundleNodeHandle.h
r257482 r257503 29 29 #include "ImageOptions.h" 30 30 #include <JavaScriptCore/JSBase.h> 31 #include <WebCore/ActiveDOMObject.h> 31 32 #include <wtf/Forward.h> 32 33 #include <wtf/Optional.h> … … 46 47 class WebImage; 47 48 48 class InjectedBundleNodeHandle : public API::ObjectImpl<API::Object::Type::BundleNodeHandle> {49 class InjectedBundleNodeHandle : public API::ObjectImpl<API::Object::Type::BundleNodeHandle>, public WebCore::ActiveDOMObject { 49 50 public: 50 51 static RefPtr<InjectedBundleNodeHandle> getOrCreate(JSContextRef, JSObjectRef); … … 57 58 58 59 // Convenience DOM Operations 59 Ref <InjectedBundleNodeHandle> document();60 RefPtr<InjectedBundleNodeHandle> document(); 60 61 61 62 // Additional DOM Operations … … 93 94 InjectedBundleNodeHandle(WebCore::Node&); 94 95 95 Ref<WebCore::Node> m_node; 96 // ActiveDOMObject. 97 void stop() final; 98 const char* activeDOMObjectName() const final; 99 100 RefPtr<WebCore::Node> m_node; 96 101 }; 97 102
Note: See TracChangeset
for help on using the changeset viewer.