Changeset 220580 in webkit
- Timestamp:
- Aug 10, 2017 11:01:15 PM (7 years ago)
- Location:
- trunk/Source/WebKit
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit/ChangeLog
r220578 r220580 1 2017-08-10 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GTK][WPE] Assertion failure in TimerBase inside WebCore::IconRecord::setImageData 4 https://bugs.webkit.org/show_bug.cgi?id=173866 5 <rdar://problem/33122050> 6 7 Reviewed by Michael Catanzaro. 8 9 IconDatabase creates and destroys IconRecord objects in both database and main thread. If the IconRecord has a 10 valid icon, its Image could be created in one thread and destroyed in another, something that is not expected to 11 happen, because Image has a Timer member. Since we have all the data and we are decoding it right after creating 12 the Image, we don't really need to keep the Image object around, we could simply take a reference of the encoded 13 data and the decoded native image to be returned by synchronousIconForPageURL(). 14 15 * UIProcess/API/glib/IconDatabase.cpp: 16 (WebKit::IconDatabase::IconRecord::image): Return NativeImagePtr now. 17 (WebKit::IconDatabase::IconRecord::setImageData): Create a BitmapImage to decode it and keep a reference to the 18 encoded data and decoded native image. 19 (WebKit::IconDatabase::IconRecord::snapshot const): Use m_imageData to get the encoded data. 20 (WebKit::IconDatabase::synchronousIconForPageURL): Return the native image and whether the icon is known or not. 21 (WebKit::IconDatabase::IconRecord::loadImageFromResource): Deleted. 22 * UIProcess/API/glib/IconDatabase.h: 23 * UIProcess/API/glib/WebKitFaviconDatabase.cpp: 24 (getIconSurfaceSynchronously): Use new API. 25 1 26 2017-08-10 Dan Bernstein <mitz@apple.com> 2 27 -
trunk/Source/WebKit/UIProcess/API/glib/IconDatabase.cpp
r219863 r220580 107 107 } 108 108 109 Image*IconDatabase::IconRecord::image(const IntSize&)109 NativeImagePtr IconDatabase::IconRecord::image(const IntSize&) 110 110 { 111 111 // FIXME rdar://4680377 - For size right now, we are returning our one and only image and the Bridge 112 112 // is resizing it in place. We need to actually store all the original representations here and return a native 113 113 // one, or resize the best one to the requested size and cache that result. 114 return m_image .get();114 return m_image; 115 115 } 116 116 … … 118 118 { 119 119 m_dataSet = true; 120 121 // It's okay to delete the raw image here. Any existing clients using this icon will be122 // managing an image that was created with a copy of this raw image data. 123 if (! data->size()) {124 m_image = nullptr;125 return; 126 } 127 128 m_image = BitmapImage::create();129 if ( m_image->setData(WTFMove(data), true) < EncodedDataStatus::SizeAvailable) {120 m_imageData = WTFMove(data); 121 m_image = nullptr; 122 123 if (!m_imageData->size()) { 124 m_imageData = nullptr; 125 return; 126 } 127 128 auto image = BitmapImage::create(); 129 if (image->setData(RefPtr<SharedBuffer> { m_imageData }, true) < EncodedDataStatus::SizeAvailable) { 130 130 LOG(IconDatabase, "Manual image data for iconURL '%s' FAILED - it was probably invalid image data", m_iconURL.ascii().data()); 131 m_image = nullptr; 132 } 133 } 134 135 void IconDatabase::IconRecord::loadImageFromResource(const char* resource) 136 { 137 if (!resource) 138 return; 139 140 m_image = Image::loadPlatformResource(resource); 141 m_dataSet = true; 131 m_imageData = nullptr; 132 return; 133 } 134 135 m_image = image->nativeImageForCurrentFrame(); 136 if (!m_image) { 137 LOG(IconDatabase, "Manual image data for iconURL '%s' FAILED - it was probably invalid image data", m_iconURL.ascii().data()); 138 m_imageData = nullptr; 139 } 142 140 } 143 141 … … 154 152 { 155 153 if (forDeletion) 156 return IconSnapshot(m_iconURL, 0, 0);157 158 return IconSnapshot(m_iconURL, m_stamp, m_image ? m_image->data() : 0);154 return IconSnapshot(m_iconURL, 0, nullptr); 155 156 return IconSnapshot(m_iconURL, m_stamp, m_imageData ? m_imageData.get() : nullptr); 159 157 } 160 158 … … 306 304 } 307 305 308 Image*IconDatabase::synchronousIconForPageURL(const String& pageURLOriginal, const IntSize& size)306 std::pair<NativeImagePtr, IconDatabase::IsKnownIcon> IconDatabase::synchronousIconForPageURL(const String& pageURLOriginal, const IntSize& size) 309 307 { 310 308 ASSERT_NOT_SYNC_THREAD(); … … 314 312 315 313 if (!isOpen() || !documentCanHaveIcon(pageURLOriginal)) 316 return nullptr;314 return { nullptr, IsKnownIcon::No }; 317 315 318 316 LockHolder locker(m_urlAndIconLock); … … 339 337 m_pageURLsInterestedInIcons.add(pageURLCopy); 340 338 341 return nullptr;339 return { nullptr, IsKnownIcon::No }; 342 340 } 343 341 … … 348 346 // we can just bail now 349 347 if (!m_iconURLImportComplete && !iconRecord) 350 return nullptr;348 return { nullptr, IsKnownIcon::No }; 351 349 352 350 // Assuming we're done initializing and cleanup is allowed, … … 355 353 356 354 if (!iconRecord) 357 return nullptr;355 return { nullptr, IsKnownIcon::No }; 358 356 359 357 // If it's a new IconRecord object that doesn't have its imageData set yet, … … 367 365 m_iconsPendingReading.add(iconRecord); 368 366 wakeSyncThread(); 369 return nullptr;367 return { nullptr, IsKnownIcon::No }; 370 368 } 371 369 … … 373 371 // and isn't actually interested in the image return value 374 372 if (size == IntSize(0, 0)) 375 return nullptr; 376 377 // PARANOID DISCUSSION: This method makes some assumptions. It returns a WebCore::image which the icon database might dispose of at anytime in the future, 378 // and Images aren't ref counted. So there is no way for the client to guarantee continued existence of the image. 379 // This has *always* been the case, but in practice clients would always create some other platform specific representation of the image 380 // and drop the raw Image*. On Mac an NSImage, and on windows drawing into an HBITMAP. 381 // The async aspect adds a huge question - what if the image is deleted before the platform specific API has a chance to create its own 382 // representation out of it? 383 // If an image is read in from the icondatabase, we do *not* overwrite any image data that exists in the in-memory cache. 384 // This is because we make the assumption that anything in memory is newer than whatever is in the database. 385 // So the only time the data will be set from the second thread is when it is INITIALLY being read in from the database, but we would never 386 // delete the image on the secondary thread if the image already exists. 387 return iconRecord->image(size); 373 return { nullptr, IsKnownIcon::Yes }; 374 375 return { iconRecord->image(size), IsKnownIcon::Yes }; 388 376 } 389 377 -
trunk/Source/WebKit/UIProcess/API/glib/IconDatabase.h
r218922 r220580 38 38 39 39 namespace WebCore { 40 class Image;41 40 class SharedBuffer; 42 41 } … … 60 59 61 60 private: 62 enum ImageDataStatus {63 ImageDataStatusPresent, ImageDataStatusMissing, ImageDataStatusUnknown64 };65 66 61 class IconSnapshot { 67 62 public: … … 96 91 97 92 void setImageData(RefPtr<WebCore::SharedBuffer>&&); 98 WebCore:: Image*image(const WebCore::IntSize&);93 WebCore::NativeImagePtr image(const WebCore::IntSize&); 99 94 100 95 String iconURL() { return m_iconURL; } 101 102 void loadImageFromResource(const char*);103 96 104 97 enum class ImageDataStatus { Present, Missing, Unknown }; … … 114 107 String m_iconURL; 115 108 time_t m_stamp { 0 }; 116 RefPtr<WebCore::Image> m_image; 109 RefPtr<WebCore::SharedBuffer> m_imageData; 110 WebCore::NativeImagePtr m_image; 117 111 118 112 HashSet<String> m_retainingPageURLs; … … 198 192 void setIconURLForPageURL(const String& iconURL, const String& pageURL); 199 193 200 WebCore::Image* synchronousIconForPageURL(const String&, const WebCore::IntSize&); 194 enum class IsKnownIcon { No, Yes }; 195 std::pair<WebCore::NativeImagePtr, IsKnownIcon> synchronousIconForPageURL(const String&, const WebCore::IntSize&); 201 196 String synchronousIconURLForPageURL(const String&); 202 197 bool synchronousIconDataKnownForIconURL(const String&); -
trunk/Source/WebKit/UIProcess/API/glib/WebKitFaviconDatabase.cpp
r219863 r220580 140 140 // The exact size we pass is irrelevant to the iconDatabase code. 141 141 // We must pass something greater than 0x0 to get an icon. 142 WebCore::Image* iconImage= database->priv->iconDatabase->synchronousIconForPageURL(pageURL, WebCore::IntSize(1, 1));143 if ( !iconImage) {142 auto iconData = database->priv->iconDatabase->synchronousIconForPageURL(pageURL, WebCore::IntSize(1, 1)); 143 if (iconData.second == IconDatabase::IsKnownIcon::No) { 144 144 g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_UNKNOWN, _("Unknown favicon for page %s"), pageURL.utf8().data()); 145 145 return nullptr; 146 146 } 147 147 148 RefPtr<cairo_surface_t> surface = iconImage->nativeImageForCurrentFrame(); 149 if (!surface) { 148 if (!iconData.first) { 150 149 g_set_error(error, WEBKIT_FAVICON_DATABASE_ERROR, WEBKIT_FAVICON_DATABASE_ERROR_FAVICON_NOT_FOUND, _("Page %s does not have a favicon"), pageURL.utf8().data()); 151 150 return nullptr; 152 151 } 153 152 154 return surface;153 return iconData.first; 155 154 } 156 155
Note: See TracChangeset
for help on using the changeset viewer.