Add API test for all parts of WebKit1 API related to favicons.
authorbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 2 Jul 2017 19:38:57 +0000 (19:38 +0000)
committerbeidson@apple.com <beidson@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 2 Jul 2017 19:38:57 +0000 (19:38 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174069

Reviewed by Andy Estes.

These two API tests cover all WebKit1 API related to icons.

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/mac/WebViewIconLoading.mm: Added.
(mainResourceData):
(defaultFaviconData):
(customFaviconData):
(imageFromData):
(+[IconLoadingProtocol canInitWithRequest:]):
(+[IconLoadingProtocol canonicalRequestForRequest:]):
(-[IconLoadingProtocol startLoading]):
(-[IconLoadingProtocol stopLoading]):
(-[IconLoadingFrameLoadDelegate webView:didReceiveIcon:forFrame:]):
(-[MainFrameIconKVO observeValueForKeyPath:ofObject:change:context:]):
(TestWebKitAPI::TEST):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@219059 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj
Tools/TestWebKitAPI/Tests/mac/WebViewIconLoading.mm [new file with mode: 0644]

index df776e8..b0104b2 100644 (file)
@@ -1,3 +1,26 @@
+2017-07-02  Brady Eidson  <beidson@apple.com>
+
+        Add API test for all parts of WebKit1 API related to favicons.
+        https://bugs.webkit.org/show_bug.cgi?id=174069
+
+        Reviewed by Andy Estes.
+
+        These two API tests cover all WebKit1 API related to icons.
+        
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/mac/WebViewIconLoading.mm: Added.
+        (mainResourceData):
+        (defaultFaviconData):
+        (customFaviconData):
+        (imageFromData):
+        (+[IconLoadingProtocol canInitWithRequest:]):
+        (+[IconLoadingProtocol canonicalRequestForRequest:]):
+        (-[IconLoadingProtocol startLoading]):
+        (-[IconLoadingProtocol stopLoading]):
+        (-[IconLoadingFrameLoadDelegate webView:didReceiveIcon:forFrame:]):
+        (-[MainFrameIconKVO observeValueForKeyPath:ofObject:change:context:]):
+        (TestWebKitAPI::TEST):
+
 2017-07-01  Dan Bernstein  <mitz@apple.com>
 
         [iOS] Remove code only needed when building for iOS 9.x
index d54ca9f..a4e221f 100644 (file)
                51CD1C721B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */; };
                51D124981E763B02002B2820 /* WKHTTPCookieStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51D124971E763AF8002B2820 /* WKHTTPCookieStore.mm */; };
                51D1249B1E785425002B2820 /* CookieManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F6F3F29013342FEB00A6BF19 /* CookieManager.cpp */; };
+               51DB16CE1F085137001FA4C5 /* WebViewIconLoading.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51DB16CD1F085047001FA4C5 /* WebViewIconLoading.mm */; };
                51E5C7021919C3B200D8B3E1 /* simple2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51E780361919AFF8001829A2 /* simple2.html */; };
                51E5C7031919C3B200D8B3E1 /* simple3.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 51E780371919AFF8001829A2 /* simple3.html */; };
                51E6A8941D2F1C0A00C004B6 /* LocalStorageClear.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51E6A8921D2F1BEC00C004B6 /* LocalStorageClear.mm */; };
                51CD1C6A1B38CE3600142CA5 /* ModalAlerts.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ModalAlerts.mm; sourceTree = "<group>"; };
                51CD1C711B38D48400142CA5 /* modal-alerts-in-new-about-blank-window.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = "modal-alerts-in-new-about-blank-window.html"; sourceTree = "<group>"; };
                51D124971E763AF8002B2820 /* WKHTTPCookieStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKHTTPCookieStore.mm; sourceTree = "<group>"; };
+               51DB16CD1F085047001FA4C5 /* WebViewIconLoading.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = WebViewIconLoading.mm; sourceTree = "<group>"; };
                51E5C7041919EA5F00D8B3E1 /* ShouldKeepCurrentBackForwardListItemInList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShouldKeepCurrentBackForwardListItemInList.cpp; sourceTree = "<group>"; };
                51E6A8921D2F1BEC00C004B6 /* LocalStorageClear.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalStorageClear.mm; sourceTree = "<group>"; };
                51E6A8951D2F1C7700C004B6 /* LocalStorageClear.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = LocalStorageClear.html; sourceTree = "<group>"; };
                                51B454EB1B4E236B0085EAA6 /* WebViewCloseInsideDidFinishLoadForFrame.mm */,
                                C2EB2DD116CAC7AC009B52EE /* WebViewDidCreateJavaScriptContext.mm */,
                                37E38C33169B7D010084C28C /* WebViewDidRemoveFrameFromHierarchy.mm */,
+                               51DB16CD1F085047001FA4C5 /* WebViewIconLoading.mm */,
                                CE32C7C718184C4900CD8C28 /* WillPerformClientRedirectToURLCrash.mm */,
                                1A7BFC0A171A0BDB00BC5F64 /* WillSendSubmitEvent.mm */,
                                A5E2027215B2181900C13E14 /* WindowlessWebViewWithMedia.mm */,
                                0F139E781A423A6B00F590F5 /* PlatformUtilitiesCocoa.mm in Sources */,
                                F4D7BCD81EA5789800C421D3 /* PositionInformationTests.mm in Sources */,
                                7CCE7EA61A411A0F00447C4C /* PlatformUtilitiesMac.mm in Sources */,
+                               51DB16CE1F085137001FA4C5 /* WebViewIconLoading.mm in Sources */,
                                7CCE7EA71A411A1300447C4C /* PlatformWebViewMac.mm in Sources */,
                                7CCE7F261A411AF600447C4C /* Preferences.mm in Sources */,
                                7C1AF7951E8DCBAB002645B9 /* PrepareForMoveToWindow.mm in Sources */,
diff --git a/Tools/TestWebKitAPI/Tests/mac/WebViewIconLoading.mm b/Tools/TestWebKitAPI/Tests/mac/WebViewIconLoading.mm
new file mode 100644 (file)
index 0000000..2b4d79b
--- /dev/null
@@ -0,0 +1,242 @@
+
+/*
+ * Copyright (C) 2017 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 "PlatformUtilities.h"
+#import <WebKit/WebFrameLoadDelegate.h>
+#import <WebKit/WebView.h>
+#import <wtf/RetainPtr.h>
+
+static NSString *MainFrameIconKeyPath = @"mainFrameIcon";
+static bool messageReceived = false;
+
+static const char defaultFaviconHTML[] =
+"<html>" \
+"</html>";
+
+static const char customFaviconHTML[] =
+"<head>" \
+"<link rel=\"icon\" href=\"custom.ico\">" \
+"</head>";
+
+static const char* currentMainHTML;
+static NSData *mainResourceData()
+{
+    return [NSData dataWithBytesNoCopy:(void*)currentMainHTML length:strlen(currentMainHTML) freeWhenDone:NO];
+}
+
+static NSData *defaultFaviconData()
+{
+    NSURL *url = [[NSBundle mainBundle] URLForResource:@"icon" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"];
+    return [NSData dataWithContentsOfURL:url];
+}
+
+static NSData *customFaviconData()
+{
+    NSURL *url = [[NSBundle mainBundle] URLForResource:@"large-red-square" withExtension:@"png" subdirectory:@"TestWebKitAPI.resources"];
+    return [NSData dataWithContentsOfURL:url];
+}
+
+static NSImage *imageFromData(NSData *data)
+{
+    auto *image = [[NSImage alloc] initWithData:data];
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [image setScalesWhenResized:YES];
+#pragma clang diagnostic pop
+    [image setSize:NSMakeSize(16, 16)];
+
+    return [image autorelease];
+}
+
+@interface IconLoadingProtocol : NSURLProtocol
+@end
+
+@implementation IconLoadingProtocol
+
++ (BOOL)canInitWithRequest:(NSURLRequest *)request
+{
+    return [request.URL.scheme isEqual:@"http"];
+}
+
++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
+{
+    return request;
+}
+
+- (void)startLoading
+{
+    NSData *resourceData = nil;
+    RetainPtr<NSURLResponse> response;
+
+    if ([self.request.URL.path hasSuffix:@"main"]) {
+        resourceData = mainResourceData();
+        response = adoptNS([[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"text/html" expectedContentLength:-1 textEncodingName:nil]);
+    } else if ([self.request.URL.path hasSuffix:@"favicon.ico"]) {
+        resourceData = defaultFaviconData();
+        response = adoptNS([[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil]);
+    } else if ([self.request.URL.path hasSuffix:@"custom.ico"]) {
+        resourceData = customFaviconData();
+        response = adoptNS([[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil]);
+    } else
+        RELEASE_ASSERT_NOT_REACHED();
+
+    [self.client URLProtocol:self didReceiveResponse:response.get() cacheStoragePolicy:NSURLCacheStorageNotAllowed];
+    [self.client URLProtocol:self didLoadData:resourceData];
+    [self.client URLProtocolDidFinishLoading:self];
+}
+
+- (void)stopLoading
+{
+}
+
+@end
+
+@interface IconLoadingFrameLoadDelegate : NSObject <WebFrameLoadDelegate> {
+@public
+    RetainPtr<NSImage> receivedIcon;
+}
+@end
+
+@implementation IconLoadingFrameLoadDelegate
+
+- (void)webView:(WebView *)sender didReceiveIcon:(NSImage *)image forFrame:(WebFrame *)frame
+{
+    receivedIcon = image;
+    messageReceived = true;
+}
+
+@end
+
+@interface MainFrameIconKVO : NSObject {
+@public
+    RetainPtr<NSImage> oldImage;
+    RetainPtr<NSImage> expectedImage;
+}
+@end
+
+@implementation MainFrameIconKVO
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *, id> *)change context:(void *)context
+{
+    ASSERT([keyPath isEqualToString:MainFrameIconKeyPath]);
+    ASSERT([[object class] isEqual:[WebView class]]);
+
+    // FIXME: As mentioned in a FIXME in WebKit1 code when sending these KVO events, the old icon is already lost by the time we send the event.
+    // The below line should actually be "EXPECT_TRUE" once that bug is fixed.
+    EXPECT_FALSE([[[change objectForKey:NSKeyValueChangeOldKey] TIFFRepresentation] isEqual:[oldImage TIFFRepresentation]]);
+    EXPECT_TRUE([[[change objectForKey:NSKeyValueChangeNewKey] TIFFRepresentation] isEqual:[expectedImage TIFFRepresentation]]);
+    EXPECT_TRUE([[((WebView *)object).mainFrameIcon TIFFRepresentation] isEqual:[expectedImage TIFFRepresentation]]);
+
+}
+
+@end
+
+namespace TestWebKitAPI {
+
+TEST(WebKit1, IconLoadingDelegateDefaultFirst)
+{
+    [NSURLProtocol registerClass:[IconLoadingProtocol class]];
+
+    currentMainHTML = defaultFaviconHTML;
+    @autoreleasepool {
+        auto webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]);
+        auto frameLoadDelegate = adoptNS([[IconLoadingFrameLoadDelegate alloc] init]);
+
+        auto kvo = adoptNS([[MainFrameIconKVO alloc] init]);
+        kvo->oldImage = webView.get().mainFrameIcon;
+        kvo->expectedImage = imageFromData(defaultFaviconData());
+        [webView.get() addObserver:kvo.get() forKeyPath:MainFrameIconKeyPath options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
+
+        webView.get().frameLoadDelegate = frameLoadDelegate.get();
+        [webView.get().mainFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://testserver/1/main"]]];
+
+        Util::run(&messageReceived);
+
+        EXPECT_TRUE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+        EXPECT_TRUE([[webView.get().mainFrameIcon TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+        EXPECT_FALSE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+
+        // Now load the next page which should have a custom icon and make sure things are as expected.
+        messageReceived = false;
+        kvo->oldImage = imageFromData(defaultFaviconData());
+        kvo->expectedImage = imageFromData(customFaviconData());
+        currentMainHTML = customFaviconHTML;
+        [webView.get().mainFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://testserver/2/main"]]];
+
+        Util::run(&messageReceived);
+
+        EXPECT_TRUE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+        EXPECT_TRUE([[webView.get().mainFrameIcon TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+        EXPECT_FALSE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+
+    }
+
+    [NSURLProtocol unregisterClass:[IconLoadingProtocol class]];
+}
+
+TEST(WebKit1, IconLoadingDelegateCustomFirst)
+{
+    [NSURLProtocol registerClass:[IconLoadingProtocol class]];
+
+    currentMainHTML = customFaviconHTML;
+    @autoreleasepool {
+        auto webView = adoptNS([[WebView alloc] initWithFrame:NSMakeRect(0, 0, 120, 200) frameName:nil groupName:nil]);
+        auto frameLoadDelegate = adoptNS([[IconLoadingFrameLoadDelegate alloc] init]);
+
+        auto kvo = adoptNS([[MainFrameIconKVO alloc] init]);
+        kvo->oldImage = webView.get().mainFrameIcon;
+        kvo->expectedImage = imageFromData(customFaviconData());
+        [webView.get() addObserver:kvo.get() forKeyPath:MainFrameIconKeyPath options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
+
+        webView.get().frameLoadDelegate = frameLoadDelegate.get();
+        [webView.get().mainFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://testserver/1/main"]]];
+
+        Util::run(&messageReceived);
+
+        EXPECT_TRUE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+        EXPECT_TRUE([[webView.get().mainFrameIcon TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+        EXPECT_FALSE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+
+        // Now load the next page which should have the default icon and make sure things are as expected.
+        messageReceived = false;
+        kvo->oldImage = imageFromData(customFaviconData());
+        kvo->expectedImage = imageFromData(defaultFaviconData());
+        currentMainHTML = defaultFaviconHTML;
+        [webView.get().mainFrame loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://testserver/2/main"]]];
+
+        Util::run(&messageReceived);
+
+        EXPECT_TRUE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+        EXPECT_TRUE([[webView.get().mainFrameIcon TIFFRepresentation] isEqual:[imageFromData(defaultFaviconData()) TIFFRepresentation]]);
+        EXPECT_FALSE([[frameLoadDelegate->receivedIcon.get() TIFFRepresentation] isEqual:[imageFromData(customFaviconData()) TIFFRepresentation]]);
+    }
+
+    [NSURLProtocol unregisterClass:[IconLoadingProtocol class]];
+}
+
+} // namespace TestWebKitAPI