1/*
2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include "UnitTestUtils/EWK2UnitTestBase.h"
29#include "UnitTestUtils/EWK2UnitTestServer.h"
30
31using namespace EWK2UnitTest;
32
33extern EWK2UnitTestEnvironment* environment;
34
35static const char defaultTitle[] = "Default Testing Web Page";
36
37static const char toBeRedirectedPath[] = "/some_page_to_be_redirected";
38static const char redirectionTargetPath[] = "/redirection_target";
39
40static EWK2UnitTestServer* httpServer()
41{
42    static EWK2UnitTestServer* server = 0;
43
44    if (!server)
45        server = new EWK2UnitTestServer;
46
47    return server;
48}
49
50#define DECLARE_INVOKE_FLAG(functionName) \
51    static bool functionName##Invoked = false;
52
53#define WAS_INVOKED(functionName) \
54    if (functionName##Invoked)    \
55        return;                   \
56    functionName##Invoked = true
57
58#define CHECK_WAS_INVOKED(functionName) \
59    ASSERT_TRUE(functionName##Invoked)
60
61DECLARE_INVOKE_FLAG(navigateWithNavigationData)
62DECLARE_INVOKE_FLAG(performClientRedirect)
63DECLARE_INVOKE_FLAG(performServerRedirect)
64DECLARE_INVOKE_FLAG(updateHistoryTitle)
65DECLARE_INVOKE_FLAG(populateVisitedLinks)
66
67static void navigateWithNavigationData(const Evas_Object* view, Ewk_Navigation_Data* navigationData, void* userData)
68{
69    WAS_INVOKED(navigateWithNavigationData);
70
71    EWK2UnitTestBase* unitTest = static_cast<EWK2UnitTestBase*>(userData);
72    ASSERT_TRUE(unitTest);
73    ASSERT_EQ(unitTest->webView(), view);
74    // FIXME: WebFrameLoaderClient sends empty title.
75    // ASSERT_STREQ(defaultTitle, ewk_navigation_data_title_get(navigationData));
76    ASSERT_STREQ(environment->defaultTestPageUrl(), ewk_navigation_data_url_get(navigationData));
77
78    Ewk_Url_Request* request = ewk_navigation_data_original_request_get(navigationData);
79    ASSERT_STREQ("GET", ewk_url_request_http_method_get(request));
80    ASSERT_STREQ(environment->defaultTestPageUrl(), ewk_url_request_url_get(request));
81    ASSERT_EQ(0, ewk_request_cookies_first_party_get(request));
82}
83
84static void performClientRedirect(const Evas_Object* view, const char* sourceUrl, const char* destinationUrl, void* userData)
85{
86    WAS_INVOKED(performClientRedirect);
87
88    EWK2UnitTestBase* unitTest = static_cast<EWK2UnitTestBase*>(userData);
89    ASSERT_TRUE(unitTest);
90    ASSERT_EQ(unitTest->webView(), view);
91    ASSERT_STREQ(environment->urlForResource("redirect_url_to_default.html").data(), sourceUrl);
92    ASSERT_STREQ(environment->defaultTestPageUrl(), destinationUrl);
93}
94
95static void performServerRedirect(const Evas_Object* view, const char* sourceUrl, const char* destinationUrl, void* userData)
96{
97    WAS_INVOKED(performServerRedirect);
98
99    EWK2UnitTestBase* unitTest = static_cast<EWK2UnitTestBase*>(userData);
100    ASSERT_TRUE(unitTest);
101    ASSERT_EQ(unitTest->webView(), view);
102    ASSERT_STREQ(httpServer()->getURLForPath(toBeRedirectedPath).data(), sourceUrl);
103    ASSERT_STREQ(httpServer()->getURLForPath(redirectionTargetPath).data(), destinationUrl);
104}
105
106static void updateHistoryTitle(const Evas_Object* view, const char* title, const char* url, void* userData)
107{
108    WAS_INVOKED(updateHistoryTitle);
109
110    EWK2UnitTestBase* unitTest = static_cast<EWK2UnitTestBase*>(userData);
111    ASSERT_TRUE(unitTest);
112    ASSERT_EQ(unitTest->webView(), view);
113    ASSERT_STREQ(defaultTitle, title);
114    ASSERT_STREQ(environment->defaultTestPageUrl(), url);
115}
116
117static void populateVisitedLinks(void* userData)
118{
119    WAS_INVOKED(populateVisitedLinks);
120
121    EWK2UnitTestBase* unitTest = static_cast<EWK2UnitTestBase*>(userData);
122    ASSERT_TRUE(unitTest);
123}
124
125static void onLoadFinishedForRedirection(void* userData, Evas_Object*, void*)
126{
127    int* countLoadFinished = static_cast<int*>(userData);
128    --(*countLoadFinished);
129}
130
131static void serverCallbackRedirection(SoupServer*, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer)
132{
133    if (message->method != SOUP_METHOD_GET) {
134        soup_message_set_status(message, SOUP_STATUS_NOT_IMPLEMENTED);
135        return;
136    }
137
138    if (strcmp(path, redirectionTargetPath)) { // Redirect if 'path' is not equal to 'redirectionTargetPath'.
139        soup_message_set_status(message, SOUP_STATUS_TEMPORARY_REDIRECT);
140        soup_message_headers_append(message->response_headers, "Location", httpServer()->getURLForPath(redirectionTargetPath).data());
141        return;
142    }
143
144    soup_message_set_status(message, SOUP_STATUS_OK);
145    Eina_Strbuf* body = eina_strbuf_new();
146    eina_strbuf_append_printf(body, "<html><title>Redirection Target</title></html>");
147    const size_t bodyLength = eina_strbuf_length_get(body);
148    soup_message_body_append(message->response_body, SOUP_MEMORY_TAKE, eina_strbuf_string_steal(body), bodyLength);
149    eina_strbuf_free(body);
150
151    soup_message_body_complete(message->response_body);
152}
153
154TEST_F(EWK2UnitTestBase, ewk_context_history_callbacks_set)
155{
156    ewk_context_history_callbacks_set(ewk_view_context_get(webView()), navigateWithNavigationData, performClientRedirect, performServerRedirect, updateHistoryTitle, populateVisitedLinks, this);
157
158    // Test navigation.
159    ASSERT_TRUE(loadUrlSync(environment->defaultTestPageUrl()));
160    CHECK_WAS_INVOKED(navigateWithNavigationData);
161    CHECK_WAS_INVOKED(updateHistoryTitle);
162    CHECK_WAS_INVOKED(populateVisitedLinks);
163
164    // Test client redirect.
165    int countLoadFinished = 2;
166    evas_object_smart_callback_add(webView(), "load,finished", onLoadFinishedForRedirection, &countLoadFinished);
167    ewk_view_url_set(webView(), environment->urlForResource("redirect_url_to_default.html").data());
168    while (countLoadFinished)
169        ecore_main_loop_iterate();
170    evas_object_smart_callback_del(webView(), "load,finished", onLoadFinishedForRedirection);
171    CHECK_WAS_INVOKED(performClientRedirect);
172
173    // Test server redirect.
174    httpServer()->run(serverCallbackRedirection);
175
176    ASSERT_TRUE(loadUrlSync(httpServer()->getURLForPath(toBeRedirectedPath).data()));
177    CHECK_WAS_INVOKED(performServerRedirect);
178}
179
180