Tizen 2.1 base
[framework/web/webkit-efl.git] / Tools / EWebLauncher / addon.cc
1 #include <string>
2 #include <algorithm>
3 #include <queue>
4 #include <sstream>
5 #include <cerrno>
6 #include <sys/stat.h>
7 #include <limits.h>
8 #include <Evas.h>
9 #include <Ecore.h>
10 #include <Ecore_Evas.h>
11 #include <JavaScriptCore/API/JSContextRef.h>
12 #include <JavaScriptCore/API/JSStringRef.h>
13 #include "EWebKit.h"
14 #include "EWebLauncher.h"
15
16 using namespace std;
17
18
19 namespace {
20 ELauncher* g_elauncher = 0;
21
22 int currentZoomLevel = DEFAULT_ZOOM_LEVEL;
23
24 // the zoom values are chosen to be like in Mozilla Firefox 3
25 int zoomLevels[] = {30, 50, 67, 80, 90,
26                             100,
27                             110, 120, 133, 150, 170, 200, 240, 300};
28
29 void print_history(Eina_List *list)
30 {
31     Eina_List *l;
32     void *d;
33
34     if (!ewk_test_verbose)
35        return;
36
37     printf("Session history contains:\n");
38
39     EINA_LIST_FOREACH(list, l, d) {
40        Ewk_History_Item *item = (Ewk_History_Item*)d;
41        cairo_surface_t *cs = ewk_history_item_icon_surface_get(item);
42        char buf[PATH_MAX];
43        int s = snprintf(buf, sizeof(buf), "/tmp/favicon-%s.png", ewk_history_item_uri_original_get(item));
44        for (s--; s >= (int)sizeof("/tmp/favicon-"); s--) {
45            if (!isalnum(buf[s]) && buf[s] != '.')
46                buf[s] = '_';
47        }
48        cs = ewk_history_item_icon_surface_get(item);
49
50        if (cs && cairo_surface_status(cs) == CAIRO_STATUS_SUCCESS)
51            cairo_surface_write_to_png(cs, buf);
52        else
53            buf[0] = '\0';
54
55        printf("* '%s' title='%s' icon='%s'\n",
56               ewk_history_item_uri_original_get(item),
57               ewk_history_item_title_get(item), buf);
58     }
59 }
60
61 void zoom_level_set(Evas_Object *webview, int level)
62 {
63     float factor = ((float) zoomLevels[level]) / 100.0;
64     Evas_Coord ox, oy, mx, my, cx, cy;
65     evas_pointer_canvas_xy_get(evas_object_evas_get(webview), &mx, &my);
66     evas_object_geometry_get(webview, &ox, &oy, NULL, NULL);
67     cx = mx - ox;
68     cy = my - oy;
69     printf( "EWL: Zoom set: %f\n", factor );
70     ewk_view_zoom_animated_set(webview, factor, 0.5, cx, cy);
71 }
72
73
74
75 // UTILITY!
76
77 template <class Object, size_t size> inline
78 Object* ra_end( Object (&aref)[size] )
79 {
80     Object* begin = aref;
81     return begin + size;
82 }
83
84 struct Cmd2Key
85 {
86     string cmd;
87     string key;
88
89 } ewk_test_cmd2key [] = {
90     { "quit", "Escape" },
91     { "back", "F1" },
92     { "forward", "F2" },
93     { "next-encoding", "F3" },
94     { "hit-test", "F4" },
95     { "reload", "F5" },
96     { "stop", "F6" },
97     { "zoom-out", "F7" },
98     { "zoom-in", "F8" },
99     { "new", "F9" },
100     { "expand", "F10" },
101     { "prerender1", "F11" },
102     { "suspend", "d" },
103     { "resume", "e" },
104     { "js-suspend", "s" },
105     { "js-resume", "q" }
106 };
107
108
109 struct FCmdEql
110 {
111     string k;
112     FCmdEql( string yk ): k( yk ) {}
113     template <class Kmd>
114     bool operator()( const Kmd& item ) { return item.cmd == k; }
115 };
116
117 queue<string> cmdq;
118
119 }
120
121 int ewk_test_load_script( const char* script )
122 {
123     struct stat state;
124     if ( -1 == stat( script, &state ) )
125     {
126         perror( script );
127         return EINA_FALSE;
128     }
129     size_t size = state.st_size;
130     FILE* sin = fopen( script, "r" );
131     if ( sin )
132     {
133         char* buf = (char*)malloc( size+1 );
134         int realsize = fread( buf, size, 1, sin );
135         if ( realsize != 1 )
136         {
137             printf( "Warning: script not fully read!\n" );
138             free( buf );
139         }
140         else
141         {
142             buf[size] = '\0';
143             ewk_test_script_commands = buf;
144         }
145         fclose( sin );
146         return EINA_TRUE;
147     }
148     return EINA_FALSE;
149 }
150
151 Eina_Bool ewk_test_pickup_script_command( void* state );
152
153 Eina_Bool kick_ecore( void* )
154 {
155     printf( "*TICK\n" );
156     if ( cmdq.empty() )
157     {
158         printf( "*--- empty (60 second of delay)\n" );
159         ecore_timer_add( 60, kick_ecore, 0 );
160         return ECORE_CALLBACK_CANCEL;
161     }
162
163     ecore_idler_add( &ewk_test_pickup_script_command, g_elauncher );
164     return ECORE_CALLBACK_CANCEL; // stop timing - idler will install you back
165 }
166
167 void ewk_test_reload_script( int signum )
168 {
169     if ( !ewk_test_script_path )
170         return;
171
172     printf( "EWK: Reloading commands from %s\n", ewk_test_script_path );
173     if ( ewk_test_load_script( ewk_test_script_path ) )
174     {
175         ewk_test_enqueue_script( ewk_test_script_commands );
176     }
177     return;
178 }
179
180 void ewk_test_execute_command( ELauncher* app, const char* cmd )
181 {
182     Evas_Object* obj = app->browser;
183     int s = 0;
184     switch (*cmd)
185     {
186     case '.':
187         printf( "**EWK: %s\n", cmd+1 );
188         goto end;
189
190     case '%':
191         s = atoi( cmd+1 );
192         sleep( s );
193         goto end;
194
195     case '*':
196         printf( "**EWK is setting new URL: %s\n", cmd+1 );
197         ewk_view_uri_set( app->browser, cmd+1 );
198         goto end;
199
200     case '#':
201         return; // comment
202
203
204     default:
205         break;
206
207     }
208
209     {
210         string k = cmd;
211         printf( "*COMMAND: %s\n", k.c_str() );
212         const char scrollprefix [] = "scroll:"; size_t scrolln = (sizeof scrollprefix)-1;
213         if ( 0 == k.compare( 0, scrolln, scrollprefix ) )
214         {
215             k = k.substr( scrolln );
216             size_t pos = k.find( ':' );
217             if ( pos == string::npos )
218                 return;
219
220             int x = atoi( k.substr( 0, pos-0 ).c_str() );
221             int y = atoi( k.substr( pos+1 ).c_str() );
222
223             ewk_frame_scroll_add( ewk_view_frame_main_get(obj), x, y );
224         }
225         else
226         {
227             Cmd2Key* i = find_if( ewk_test_cmd2key, ra_end( ewk_test_cmd2key ), FCmdEql( cmd ) );
228             if ( i == ra_end( ewk_test_cmd2key ) )
229                 return; // ignore false commands - this is only a test application
230
231             ewk_test_handle_command( app, i->key.c_str(), obj );
232         }
233
234         if ( k == "quit" )
235             return; // prevent any additional action after you already quit
236     }
237
238 end: ;
239    // ecore_main_loop_iterate(); // flush pending events
240 }
241
242 void ewk_test_handle_command( ELauncher* app, const char* ev_key, Evas_Object* obj )
243 {
244     static const char *encodings[] = {
245         "ISO-8859-1",
246         "UTF-8",
247         NULL
248     };
249     static int currentEncoding = -1;
250
251     if (0 == strcmp(ev_key, "Escape")) {
252         ewk_test_close_window(app->ee);
253     } else if (0 == strcmp(ev_key, "F1")) {
254         info("Back (F1) was pressed\n");
255         if (ewk_view_back_possible(obj)) {
256             Ewk_History *history = ewk_view_history_get(obj);
257             Eina_List *list = ewk_history_back_list_get(history);
258             print_history(list);
259             ewk_history_item_list_free(list);
260             ewk_view_back(obj);
261         } else
262             info("Back ignored: No back history\n");
263     } else if (0 == strcmp(ev_key, "F2")) {
264         info("Forward (F2) was pressed\n");
265         if (ewk_view_forward_possible(obj)) {
266             Ewk_History *history = ewk_view_history_get(obj);
267             Eina_List *list = ewk_history_forward_list_get(history);
268             print_history(list);
269             ewk_history_item_list_free(list);
270             ewk_view_forward(obj);
271         } else
272             info("Forward ignored: No forward history\n");
273     } else if (0 == strcmp(ev_key, "F3")) {
274         currentEncoding++;
275         currentEncoding %= (sizeof(encodings) / sizeof(encodings[0]));
276         info("Set encoding (F3) pressed. New encoding to %s", encodings[currentEncoding]);
277         ewk_view_setting_encoding_custom_set(obj, encodings[currentEncoding]);
278     } else if (0 == strcmp(ev_key, "F4")) {
279         Evas_Object *frame = ewk_view_frame_main_get(obj);
280         Evas_Coord x, y;
281         Ewk_Hit_Test *ht;
282
283         evas_pointer_canvas_xy_get(evas_object_evas_get(obj), &x, &y);
284         ht = ewk_frame_hit_test_new(frame, x, y);
285         if (!ht)
286             printf("No hit test returned for point %d,%d\n", x, y);
287         else {
288             printf("Hit test for point %d,%d\n"
289                    "  pos=%3d,%3d\n"
290                    "  bounding_box=%d,%d + %dx%d\n"
291                    "  title='%s'\n"
292                    "  alternate_text='%s'\n"
293                    "  frame=%p (%s)\n"
294                    "  link {\n"
295                    "    text='%s'\n"
296                    "    url='%s'\n"
297                    "    title='%s'\n"
298                    "    target frame=%p (%s)\n"
299                    "  }\n"
300                    "  flags {\n"
301                    "    editable=%hhu\n"
302                    "    selected=%hhu\n"
303                    "  }\n",
304                    x, y,
305                    ht->x, ht->y,
306                    ht->bounding_box.x, ht->bounding_box.y, ht->bounding_box.w, ht->bounding_box.h,
307                    ht->title,
308                    ht->alternate_text,
309                    ht->frame, evas_object_name_get(ht->frame),
310                    ht->link.text,
311                    ht->link.url,
312                    ht->link.title,
313                    ht->link.target_frame, evas_object_name_get(ht->link.target_frame),
314                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_EDITABLE,
315                    ht->context & EWK_HIT_TEST_RESULT_CONTEXT_SELECTION);
316             ewk_frame_hit_test_free(ht);
317         }
318
319     } else if (0 == strcmp(ev_key, "F5")) {
320         info("Reload (F5) was pressed, reloading.\n");
321         ewk_view_reload(obj);
322     } else if (0 == strcmp(ev_key, "F6")) {
323         info("Stop (F6) was pressed, stop loading.\n");
324         ewk_view_stop(obj);
325     /* } FIXME: uncomment code below after Bug 18662 lands upstream.
326     else if (0 == strcmp(ev_key, "F12")) {
327         bool status = ewk_webframe_object_keyboard_navigation_get(page);
328         ewk_webframe_object_keyboard_navigation_set(page, !status);
329         info("Command::keyboard navigation toggle\n");*/
330     } else if (0 == strcmp(ev_key, "F7")) {
331         info("Zoom out (F7) was pressed.\n");
332         if (currentZoomLevel > MIN_ZOOM_LEVEL)
333             zoom_level_set(obj, --currentZoomLevel);
334     } else if (0 == strcmp(ev_key, "F8")) {
335         info("Zoom in (F8) was pressed.\n");
336         if (currentZoomLevel < MAX_ZOOM_LEVEL)
337             zoom_level_set(obj, ++currentZoomLevel);
338     } else if (0 == strcmp(ev_key, "F9")) {
339         info("Create new window (F9) was pressed.\n");
340         Eina_Rectangle geometry = {0, 0, 0, 0};
341         ewk_test_create_browser("http://www.google.com",
342                       app->theme, app->userAgent, geometry, app->backingStore,
343                       NULL, 0, ewk_view_zoom_cairo_scaling_get(obj));
344     } else if (0 == strcmp(ev_key, "F10")) {
345         Evas_Coord x, y, w, h;
346         Evas_Object *frame = ewk_view_frame_main_get(obj);
347         float zoom = zoomLevels[currentZoomLevel] / 100.0;
348
349         ewk_frame_visible_content_geometry_get(frame, EINA_FALSE, &x, &y, &w, &h);
350         x -= w;
351         y -= h;
352         w *= 4;
353         h *= 4;
354         info("Pre-render %d,%d + %dx%d\n", x, y, w, h);
355         ewk_view_pre_render_region(obj, x, y, w, h, zoom);
356     } else if (0 == strcmp(ev_key, "d")) {
357         info("Render suspended");
358         ewk_view_disable_render(obj);
359     } else if (0 == strcmp(ev_key, "e")) {
360         info("Render resumed");
361         ewk_view_enable_render(obj);
362     } else if (0 == strcmp(ev_key, "s")) {
363         ewk_view_javascript_suspend( obj );
364     } else if (0 == strcmp(ev_key, "q")) {
365         ewk_view_javascript_resume( obj );
366     }
367 }
368
369 Eina_Bool ewk_test_pickup_script_command( void* state )
370 {
371     if ( cmdq.empty() )
372     {
373         // shouldn't happen, but let's not make difference
374         ecore_timer_add( 60, kick_ecore, 0 );
375         return ECORE_CALLBACK_CANCEL;
376     }
377
378     ELauncher* app = static_cast<ELauncher*>( state );
379     string cmd = cmdq.front();
380     cmdq.pop();
381     ewk_test_execute_command( app, cmd.c_str() );
382     ecore_timer_add( 0.5, kick_ecore, 0 );
383     return ECORE_CALLBACK_CANCEL;
384 }
385
386 void ewk_test_enqueue_script( char* commands )
387 {
388     const char* p = commands;
389     for (;;) {
390         const char* b = p;
391         p = strchr( p, '\n' );
392         if ( !p )
393         {
394             string cmd( b );
395             if ( cmd != "" )
396                 cmdq.push( cmd );
397             break;
398         }
399
400         string cmd( b, p );
401         ++p;
402         if ( cmd != "" )
403             cmdq.push( cmd );
404     }
405     free( ewk_test_script_commands ); // eat up
406 }
407
408 void ewk_test_install_ewk_function( ELauncher* app )
409 {
410     g_elauncher = app;
411     ecore_timer_add( 0.5, kick_ecore, 0 );
412 }
413