Add to ewk api for setting/getting the User Agent by using system info library.
[framework/web/webkit-efl.git] / Source / WebKit2 / Platform / tizen / AboutData / AboutDataTizen.cpp
1 /*
2  * Copyright (C) 2010, 2011 Research In Motion Limited. All rights reserved.
3  * Copyright (C) 2012 Samsung Electronics. All rights reserved.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18  */
19
20 #include "config.h"
21 #include "AboutDataTizen.h"
22
23 #if ENABLE(TIZEN_WEBKIT2_ABOUT_MEMORY)
24 #include "AboutCredits.html.cpp"
25 #include "AboutTemplate.html.cpp"
26 #include "BlobData.h"
27 #include "BlobRegistry.h"
28 #include "BlobRegistryImpl.h"
29 #include "JSDOMWindow.h"
30 #include "MemoryCache.h"
31 #include "MemoryStatistics.h"
32 #include "WebKitVersion.h"
33 #include "WebMemorySampler.h"
34 #include "ewk_context.h"
35 #include <WebCore/ApplicationCache.h>
36 #include <WebCore/ApplicationCacheResource.h>
37 #include <WebCore/ApplicationCacheStorage.h>
38 #include <WebCore/ApplicationCacheGroup.h>
39 #include <WebCore/PluginData.h>
40 #include <heap/Heap.h>
41 #include <malloc.h>
42 #include <runtime/JSGlobalData.h>
43 #include <sys/stat.h>
44 #include <sys/sysinfo.h>
45 #include <sys/utsname.h>
46 #include <wtf/text/CString.h>
47 #include <wtf/text/StringBuilder.h>
48 #if ENABLE(TIZEN_NATIVE_MEMORY_SNAPSHOT)
49 #include "InspectorMemoryAgent.h"
50 namespace WebCore {
51 extern HashSet<Page*>* allPages;
52 }
53 #endif
54 using namespace WebCore;
55 using namespace WTF;
56
57 const int kiloByte = 1024;
58 const int megaByte = 1024 * 1024;
59 const unsigned meminfoIndex = 10;
60
61 enum UNIT { BYTE, KILOBYTE, MEGABYTE, EA };
62
63 namespace WebKit {
64
65 typedef HashMap<String, RefPtr<BlobStorageData> > BlobMap;
66
67 PrintFormat printFormat = PRINT_FORMAT_HTML;
68
69 static String header(const String& description)
70 {
71     if (printFormat == PRINT_FORMAT_SIMPLE)
72         return description + "\n";
73     else if (printFormat == PRINT_FORMAT_JSON)
74         return  "";
75     else
76         return String("<div class='box'><div class='box-title'>")
77                + description + String("</div><table class='fixed-table'><col width=75%><col width=25%>");
78 }
79
80 static String footer()
81 {
82     if (printFormat == PRINT_FORMAT_SIMPLE)
83         return "";
84     else if (printFormat == PRINT_FORMAT_JSON)
85         return "";
86     else
87         return "</table></div><br>";
88 }
89
90 template<class T> static String numberToRow(const String& description, T number, UNIT type)
91 {
92     if (printFormat == PRINT_FORMAT_SIMPLE)
93         return description + ":" + String::number(number) + "\n";
94     else if (printFormat == PRINT_FORMAT_JSON)
95         return String("\"") + description + "\":" + String::number(number) + ",";
96
97     String unit;
98     switch (type) {
99     case BYTE:
100         unit = "B";
101         break;
102     case KILOBYTE:
103         unit = "KB";
104         number /= kiloByte;
105         break;
106     case MEGABYTE:
107         unit = "MB";
108         number /= megaByte;
109         break;
110     case EA:
111         break;
112     }
113     return String("<tr><td>") + description + "</td><td>" + String::number(number) + " " + unit + "</td></tr>";
114 }
115
116 String numberToRow(const String& description, bool truth)
117 {
118     if (printFormat == PRINT_FORMAT_SIMPLE)
119         return description + ":" + (truth?"true":"false") + "\n";
120     else if (printFormat == PRINT_FORMAT_JSON)
121         return String("\"") + description + "\":" + (truth?"true":"false") + ",";
122     else
123         return String("<tr><td>") + description + "</td><td>" + (truth?"true":"false") + "</td></tr>";
124 }
125
126 static String cacheTypeStatisticToRow(const String& description, const MemoryCache::TypeStatistic& statistic)
127 {
128     if (printFormat == PRINT_FORMAT_SIMPLE)
129         return description + ":"
130            + String::number(statistic.count) + " "
131            + String::number(statistic.size / kiloByte) + " "
132            + String::number(statistic.liveSize / kiloByte) + " "
133            + String::number(statistic.decodedSize / kiloByte) + "\n";
134     else if (printFormat == PRINT_FORMAT_JSON)  //If dump format is 'JSON', only print the size of the cache
135         return String("\"") +  description + "\":"
136            + String::number(statistic.size) +  "," ;
137     else
138         return String("<tr><td>") + description + "</td>"
139             + "<td>" + String::number(statistic.count) + "</td>"
140             + "<td>" + String::number(statistic.size / kiloByte) + "</td>"
141             + "<td>" + String::number(statistic.liveSize / kiloByte) + "</td>"
142             + "<td>" + String::number(statistic.decodedSize / kiloByte) + "</td>"
143             + "</tr>";
144 }
145
146 static String appcacheStatisticToRow(const String& flag, const String& description, const int cacheSize)
147 {
148     return String("<tr><td>") + flag + "</td>"
149         + "<td style=\"word-break:break-all;\">" + description + "</td>"
150         + "<td>" + String::number(cacheSize) + "B</td>"
151         + "</tr>";
152 }
153
154 static String helpTextToRow(const String& feature, const String& description)
155 {
156     return String("<tr><td>") + feature + "</td>" + "<td style=\"word-break:break-all;\">" + description + "</td></tr>";
157
158 }
159
160 static String creditToRow(const String& credit)
161 {
162     return "<div class='box'><span class='box-title'>" + credit + "</span>"
163         "<span class='license'><a href=# onclick=\"license('" + credit + "');\">license</a> </span>"
164         "<table class='fixed-table'><col width=75%><col width=25%>"
165         "<tr><td><div id='" + credit + "_license' style='display:none;'>"
166         + getLicense(credit) + "</div></td></tr></table></div><br>";
167 }
168
169 static void dumpJSCTypeCountSetToTableHTML(StringBuilder& tableHTML, JSC::TypeCountSet* typeCountSet)
170 {
171     if (!typeCountSet)
172         return;
173
174     for (JSC::TypeCountSet::const_iterator iter = typeCountSet->begin(); iter != typeCountSet->end(); ++iter)
175         tableHTML.append(numberToRow(iter->first, iter->second, EA));
176 }
177
178 static void getLowMemoryNotifyInfo(size_t value[])
179 {
180     const char* TIZEN_MEMORY_INFO_PATH = "/sys/class/memnotify/meminfo";
181     unsigned index = 0;
182     bool foundKeyName = false;
183     FILE* fSystemMemoryInfo = fopen(TIZEN_MEMORY_INFO_PATH, "r");
184
185     if(fSystemMemoryInfo) {
186         while (!feof(fSystemMemoryInfo)) {
187             String strToken = getToken(fSystemMemoryInfo);
188             if (strToken.find(':') != notFound) {
189                 String keyName = strToken.left(strToken.length() - 1);
190                 foundKeyName = true;
191             } else if (foundKeyName) {
192                 value[index++] = strToken.toInt();
193                 if (index == meminfoIndex)
194                     break;
195                 foundKeyName = false;
196             }
197         }
198         fclose(fSystemMemoryInfo);
199     }
200 }
201
202 String memoryPage(PrintFormat format)
203 {
204     printFormat = format;
205     StringBuilder page;
206     if (printFormat == PRINT_FORMAT_HTML)
207         page.append(writeHeader("Memory"));
208
209     // generate system memory infomation
210     page.append(header("System Memory Usage"));
211
212     // TIZEN System Memory Info
213     size_t systemMemory[meminfoIndex];
214     getLowMemoryNotifyInfo(systemMemory);
215
216     page.append(numberToRow("Total RAM size", systemMemory[0] * megaByte, MEGABYTE));
217     page.append(numberToRow("Used (Mem+Reclaimable) RAM size", systemMemory[1] * megaByte, MEGABYTE));
218     page.append(numberToRow("Used (Mem+Swap) RAM size", systemMemory[2] * megaByte, MEGABYTE));
219     page.append(numberToRow("Used (Mem) RAM size", systemMemory[3] * megaByte, MEGABYTE));
220     page.append(numberToRow("Used (Swap) RAM size", systemMemory[4] * megaByte, MEGABYTE));
221     page.append(numberToRow("Free RAM size", systemMemory[6] * megaByte, MEGABYTE));
222     page.append(numberToRow("Free CMA size", systemMemory[7] * megaByte, MEGABYTE));
223     page.append(numberToRow("Available (Free+Reclaimable) RAM size", systemMemory[8] * megaByte, MEGABYTE));
224     page.append(numberToRow("Reserved Page RAM size", systemMemory[9] * megaByte, MEGABYTE));
225
226     page.append(footer());
227
228     // UI Process memps information
229     ApplicationMemoryStats applicationStats = sampleApplicationMalloc(getppid());
230
231     page.append(header("UI Process"));
232
233     page.append(numberToRow("UI Process Private CODE", applicationStats.privateCleanSize * kiloByte, KILOBYTE));
234     page.append(numberToRow("UI Process Private DATA", applicationStats.privateDirtySize * kiloByte, KILOBYTE));
235     page.append(numberToRow("UI Process PEAK", applicationStats.peak * kiloByte, KILOBYTE));
236     page.append(numberToRow("UI Process RSS", applicationStats.residentSetSize * kiloByte, KILOBYTE));
237     page.append(numberToRow("UI Process PSS", applicationStats.proportionalSetSize * kiloByte, KILOBYTE));
238     page.append(numberToRow("UI Process 3D memory", applicationStats.graphics3DSize * kiloByte, KILOBYTE));
239     page.append(numberToRow("UI Process UMP memory", applicationStats.UMPSize * kiloByte, KILOBYTE));
240
241     page.append(footer());
242
243     // Web Process memps information
244     applicationStats = sampleApplicationMalloc(getpid());
245
246     page.append(header("Web Process"));
247
248     page.append(numberToRow("Web Process Private CODE", applicationStats.privateCleanSize* kiloByte, KILOBYTE));
249     page.append(numberToRow("Web Process Private DATA", applicationStats.privateDirtySize* kiloByte, KILOBYTE));
250     page.append(numberToRow("Web Process PEAK", applicationStats.peak * kiloByte, KILOBYTE));
251     page.append(numberToRow("Web Process RSS", applicationStats.residentSetSize * kiloByte, KILOBYTE));
252     page.append(numberToRow("Web Process PSS", applicationStats.proportionalSetSize * kiloByte, KILOBYTE));
253     page.append(numberToRow("Web Process 3D memory", applicationStats.graphics3DSize * kiloByte, KILOBYTE));
254     page.append(numberToRow("Web Process UMP memory", applicationStats.UMPSize * kiloByte, KILOBYTE));
255
256     page.append(footer());
257
258     // Memory Cache
259     MemoryCache* cacheInc = memoryCache();
260     MemoryCache::Statistics cacheStat = cacheInc->getStatistics();
261
262     MemoryCache::TypeStatistic total;
263     total.count = cacheStat.images.count + cacheStat.cssStyleSheets.count
264             + cacheStat.scripts.count + cacheStat.xslStyleSheets.count + cacheStat.fonts.count;
265     total.size = cacheInc->liveSize() + cacheInc->deadSize();
266     total.liveSize = cacheInc->liveSize();
267     total.decodedSize = cacheStat.images.decodedSize
268             + cacheStat.cssStyleSheets.decodedSize + cacheStat.scripts.decodedSize
269             + cacheStat.xslStyleSheets.decodedSize + cacheStat.fonts.decodedSize;
270
271     // JS engine memory usage.
272     JSC::GlobalMemoryStatistics jscMemoryStat = JSC::globalMemoryStatistics();
273     JSC::Heap& mainHeap = JSDOMWindow::commonJSGlobalData()->heap;
274     OwnPtr<JSC::TypeCountSet> objectTypeCounts = mainHeap.objectTypeCounts();
275     OwnPtr<JSC::TypeCountSet> protectedObjectTypeCounts = mainHeap.protectedObjectTypeCounts();
276
277     // Malloc info.
278     struct mallinfo mallocInfo = mallinfo();
279
280     page.append(header("Web Process Memory Details"));
281
282     page.append(numberToRow("Cache used memory", total.size, KILOBYTE));
283     page.append(numberToRow("JSC used memory", jscMemoryStat.stackBytes + jscMemoryStat.JITBytes + mainHeap.capacity(), KILOBYTE));
284     page.append(numberToRow("Malloc used memory", mallocInfo.usmblks + mallocInfo.uordblks, KILOBYTE));
285     page.append(numberToRow("Total(cache+JSC+malloc) used memory", total.size + mallocInfo.usmblks + mallocInfo.uordblks + jscMemoryStat.stackBytes + jscMemoryStat.JITBytes + mainHeap.capacity(), KILOBYTE));
286
287     page.append(footer());
288
289     // generate cache information
290     if(printFormat == PRINT_FORMAT_HTML) {
291         page.append(String("<div class=\"box\"><div class=\"box-title\">Cache Information<br><div style='font-size:11px;color:#A8A8A8'>Size, Living, and Decoded are expressed in KB.</div><br></div><table class='fixed-table'><col width=75%><col width=25%>"));
292         page.append(String("<tr> <th align=left>Item</th> <th align=left>Count</th> <th align=left>Size</th> <th align=left>Living</th> <th align=left>Decoded</th></tr>"));
293     } else
294         page.append(header("Cache Information"));
295
296     if (printFormat == PRINT_FORMAT_HTML) {
297         page.append(cacheTypeStatisticToRow("Total", total));
298         page.append(cacheTypeStatisticToRow("Images", cacheStat.images));
299         page.append(cacheTypeStatisticToRow("CSS Style Sheets", cacheStat.cssStyleSheets));
300         page.append(cacheTypeStatisticToRow("Scripts", cacheStat.scripts));
301     #if ENABLE(XSLT)
302         page.append(cacheTypeStatisticToRow("XSL Style Sheets", cacheStat.xslStyleSheets));
303     #endif
304         page.append(cacheTypeStatisticToRow("Fonts", cacheStat.fonts));
305    } else {
306         page.append(cacheTypeStatisticToRow("Images Cache", cacheStat.images));
307         page.append(cacheTypeStatisticToRow("CSS Style Sheets Cache", cacheStat.cssStyleSheets));
308         page.append(cacheTypeStatisticToRow("Scripts Cache", cacheStat.scripts));
309         page.append(cacheTypeStatisticToRow("Fonts Cache", cacheStat.fonts));
310    }
311
312     page.append(footer());
313    // [Native memory information]
314 #if ENABLE(TIZEN_NATIVE_MEMORY_SNAPSHOT)  //Using InspectorMemoryAgent's new interface for about:memory
315     if (allPages) {
316         MemoryInformation info[10];
317         int info_count;
318         HashSet<Page*>::iterator end = allPages->end();
319         for (HashSet<Page*>::iterator it = allPages->begin(); it != end; ++it) {
320             page.append(header((*it)->mainFrame()->loader()->documentLoader()->url().string()));
321             for (int i = 0; i < 10; ++i)
322                 info[i].value = 0;
323             info_count = WebCore::InspectorMemoryAgent::getMemoryInformationForPage(info,*it);
324             for(int i=0;i<info_count && i<10;i++)
325                 page.append(numberToRow(info[i].name, info[i].value, BYTE));
326     page.append(footer());
327        }
328     }
329 #endif
330
331
332     if (printFormat == PRINT_FORMAT_HTML) {
333     // JS Engine Memory Usage
334         page.append("<div class='box'><div class='box-title'>JS engine memory usage<br><div style='font-size:11px;color:#A8A8A8'>Stack, JIT, Heap are expressed in KB.</div><br></div><table class='fixed-table'><col width=75%><col width=25%>");
335
336         page.append(numberToRow("Stack size", jscMemoryStat.stackBytes, KILOBYTE));
337         page.append(numberToRow("JIT memory usage", jscMemoryStat.JITBytes, KILOBYTE));
338         page.append(numberToRow("Main heap capacity", mainHeap.capacity(), KILOBYTE));
339         page.append(numberToRow("Main heap size", mainHeap.size(), KILOBYTE));
340         page.append(numberToRow("Object count", mainHeap.objectCount(), EA));
341         page.append(numberToRow("Global object count", mainHeap.globalObjectCount(), EA));
342         page.append(numberToRow("Protected object count", mainHeap.protectedObjectCount(), EA));
343         page.append(numberToRow("Protected global object count", mainHeap.protectedGlobalObjectCount(), EA));
344
345         page.append(footer());
346
347         // JS object type counts
348          page.append(header("JS object type counts"));
349         dumpJSCTypeCountSetToTableHTML(page, objectTypeCounts.get());
350         page.append(footer());
351
352         // JS protected object type counts
353         page.append(header("JS protected object type counts"));
354         dumpJSCTypeCountSetToTableHTML(page, protectedObjectTypeCounts.get());
355         page.append(footer());
356
357         // Malloc Information
358         page.append(header("Malloc Information"));
359
360         page.append(numberToRow("Total space in use", mallocInfo.usmblks + mallocInfo.uordblks, KILOBYTE));
361         page.append(numberToRow("Total space in free blocks", mallocInfo.fsmblks + mallocInfo.fordblks, KILOBYTE));
362         page.append(numberToRow("Size of the arena", mallocInfo.arena, KILOBYTE));
363         page.append(numberToRow("Number of big blocks in use", mallocInfo.ordblks, EA));
364         page.append(numberToRow("Number of small blocks in use", mallocInfo.smblks, EA));
365         page.append(numberToRow("Number of header blocks in use", mallocInfo.hblks, EA));
366         page.append(numberToRow("Space in header block headers", mallocInfo.hblkhd, EA));
367         page.append(numberToRow("Space in small blocks in use", mallocInfo.usmblks, EA));
368         page.append(numberToRow("Memory in free small blocks", mallocInfo.fsmblks, EA));
369         page.append(numberToRow("Space in big blocks in use", mallocInfo.uordblks, KILOBYTE));
370         page.append(numberToRow("Memory in free big blocks", mallocInfo.fordblks, KILOBYTE));
371         page.append(footer());
372
373 #if ENABLE(GLOBAL_FASTMALLOC_NEW)
374         // Fast Malloc Information
375         page.append(header("Fast Malloc Information"));
376
377         FastMallocStatistics fastMallocStatistics = WTF::fastMallocStatistics();
378         size_t fastMallocBytesInUse = fastMallocStatistics.committedVMBytes - fastMallocStatistics.freeListBytes;
379         size_t fastMallocBytesCommitted = fastMallocStatistics.committedVMBytes;
380         totalBytesInUse += fastMallocBytesInUse;
381         totalBytesCommitted += fastMallocBytesCommitted;
382
383         page.append(numberToRow("Fast Malloc In Use", fastMallocBytesInUse, KILOBYTE));
384         page.append(numberToRow("Fast Malloc Committed Memory", fastMallocBytesCommitted, KILOBYTE));
385
386         page.append(footer());
387 #endif
388     }
389
390     if(printFormat == PRINT_FORMAT_HTML)
391         page.append("</body></html>");
392     return page.toString();
393 }
394
395 static String appCachePage()
396 {
397     printFormat = PRINT_FORMAT_HTML;
398
399     StringBuilder page;
400     page.append(writeHeader("Application Cache"));
401
402     Vector<KURL> urls;
403     cacheStorage().manifestURLs(&urls);
404
405     if (!urls.size()) {
406         page.append(header("Application cache is empty"));
407         page.append(footer());
408         return page.toString();
409     }
410
411     for(size_t index = 0; index < urls.size(); index++)
412     {
413         // generate application cache infomation
414         page.append(String("<div class='box'><div class='box-title'>")
415                + urls[index].string() + String("</div><table class='fixed-table'><col width=15%><col width=70%><col width=15%>"));
416
417         ApplicationCacheGroup* cacheGroup = cacheStorage().cacheGroupForURL(urls[index]);
418         ApplicationCache* cache = cacheGroup->newestCache();
419
420         if (!cache || !cache->isComplete()) {
421             page.append("cache is incomplete");
422             page.append(footer());
423         }
424
425         ApplicationCache::ResourceMap::const_iterator end = cache->end();
426         for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) {
427
428             RefPtr<ApplicationCacheResource> resource = it->second;
429             unsigned type = resource->type();
430
431             StringBuilder flags;
432             if (type & ApplicationCacheResource::Master)
433                 flags.append("Master");
434             if (type & ApplicationCacheResource::Manifest)
435                 flags.append("Manifest");
436             if (type & ApplicationCacheResource::Explicit)
437                 flags.append("Explicit");
438             if (type & ApplicationCacheResource::Foreign)
439                 flags.append("Foreign");
440             if (type & ApplicationCacheResource::Fallback)
441                 flags.append("Fallback");
442
443             page.append(appcacheStatisticToRow(flags.toString(), it->first, resource->estimatedSizeInStorage()));
444         }
445         page.append(footer());
446     }
447
448     return page.toString();
449 }
450
451 static String blobPage()
452 {
453     StringBuilder page;
454     page.append(writeHeader("Blob internals"));
455     page.append("<div class='box'><table class='fixed-table' style=word-break:break-all; width=100%>");
456
457     BlobMap map = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobData();
458
459     if (map.isEmpty()) {
460         page.append(header("There is no Blob data"));
461         page.append(footer());
462         return page.toString();
463     }
464
465     BlobMap::const_iterator it = map.begin();
466     const BlobMap::const_iterator itend = map.end();
467     for (; it != itend; ++it) {
468         // append blob object url information
469         page.append("<tr><td>" + it->first + "<ul>");
470
471         // append blob data information
472         RefPtr<BlobStorageData> blobData = it->second;
473         if (!blobData->contentType().isEmpty())
474             page.append("<li>Content Type:" + blobData->contentType() + "</li>");
475         if (!blobData->contentDisposition().isEmpty())
476             page.append("<li>Content Disposition:" + blobData->contentDisposition() + "</li>");
477
478         BlobDataItemList::const_iterator it = blobData->items().begin();
479         const BlobDataItemList::const_iterator itend = blobData->items().end();
480         for (; it != itend; ++it) {
481             const BlobDataItem& blobItem = *it;
482
483             switch (blobItem.type) {
484             case BlobDataItem::Data:
485                 page.append("<li>Type: data</li>");
486                 break;
487             case BlobDataItem::File:
488                 page.append("<li>Type: file</li>");
489                 if (!blobItem.path.isEmpty())
490                     page.append("<li>Path: " + blobItem.path + "</li>");
491                 break;
492             case BlobDataItem::Blob:
493                 page.append("<li>Type: blob</li>");
494                 if (!blobItem.url.isEmpty())
495                     page.append("<li>URL: " + blobItem.url.string() + "</li>");
496                 break;
497             }
498             page.append("<li>Length: " + String::number(blobItem.length) + "</li>");
499         }
500         page.append("</ul></td></tr>");
501     }
502
503     page.append(footer());
504
505     return page.toString();
506 }
507
508 static String cachePage()
509 {
510     printFormat = PRINT_FORMAT_HTML;
511
512     StringBuilder page;
513     page.append(writeHeader("Memory Cache"));
514     page.append("<div class='box'><table class='fixed-table' style=word-break:break-all; width=100%>");
515
516     String cachedResourceLists = memoryCache()->dumpCachedResourceLists();
517     if (cachedResourceLists.isEmpty()) {
518         page.append(header("Memory cache is empty"));
519         page.append(footer());
520         return page.toString();
521     }
522
523     Vector<String> cacheInfo;
524     cachedResourceLists.split('\n', cacheInfo);
525
526     Vector<String>::iterator iter = cacheInfo.begin();
527     for(; iter != cacheInfo.end(); ++iter)
528         page.append("<tr><td>" + *iter + "</td></tr>");
529
530     page.append(footer());
531
532     return page.toString();
533 }
534
535 static String creditsPage()
536 {
537     printFormat = PRINT_FORMAT_HTML;
538
539     StringBuilder page;
540     page.append(writeHeader("Credits"));
541     page.append(creditToRow("WebKit"));
542     page.append(footer());
543
544     return page.toString();
545 }
546
547 static String helpPage()
548 {
549     printFormat = PRINT_FORMAT_HTML;
550
551     StringBuilder page;
552     page.append(writeHeader("List of About Features"));
553     page.append("<div class='box'><table class='fixed-table' style=word-break:break-all;><col width=35%><col width=65%>");
554
555     page.append(helpTextToRow("about:appcache", "Application cache information"));
556     page.append(helpTextToRow("about:cache", "Memory cache information"));
557     page.append(helpTextToRow("about:credits", "License information"));
558     page.append(helpTextToRow("about:help", "List of About features"));
559     page.append(helpTextToRow("about:memory", "Memory Statistics"));
560     page.append(helpTextToRow("about:plugins", "Plugin information"));
561     page.append(helpTextToRow("about:version", "Version information"));
562
563     page.append(footer());
564
565     return page.toString();
566 }
567
568 static String pluginsPage()
569 {
570     printFormat = PRINT_FORMAT_HTML;
571
572     StringBuilder page;
573     page.append(writeHeader("Plugin"));
574     page.append("<div class='box'><table class='fixed-table' style=word-break:break-all; width=100%>");
575
576     // FIXME: Ewk_Context should be obtained from Ewk_View. This will be fixed after refactoring 'about:' implementation itself.
577     Ewk_Context* context = ewk_context_default_get();
578     Vector<PluginModuleInfo> plugins = (toImpl(context->wkContext())->pluginInfoStore()).plugins();
579
580     if (plugins.isEmpty()) {
581         page.append(header("There is no plugin"));
582         page.append(footer());
583         return page.toString();
584     }
585
586     Vector<PluginModuleInfo>::const_iterator it = plugins.begin();
587     const Vector<PluginModuleInfo>::const_iterator itend = plugins.end();
588     for (; it != itend; ++it) {
589         page.append("<tr><td>");
590
591         PluginInfo info = (*it).info;
592         if (!info.name.isEmpty())
593             page.append(info.name);
594
595         page.append("<ul>");
596
597         if (!info.file.isEmpty())
598             page.append("<li>File: " + info.file + "</li>");
599
600         if (!info.desc.isEmpty())
601             page.append("<li>Description: " + info.desc + "</li>");
602
603         page.append("</ul></td></td>");
604     }
605
606     page.append(footer());
607
608     return page.toString();
609 }
610
611 static String versionPage()
612 {
613     printFormat = PRINT_FORMAT_HTML;
614
615     StringBuilder page;
616     page.append(writeHeader("Version"));
617     page.append("<div class='box'><table class='fixed-table' style=word-break:break-all; width=100%>");
618
619     // TODO : More information(OS version, JavaScript Core version) will be added. 
620     page.append(helpTextToRow("WebKit", String::format("%d.%d", WEBKIT_MAJOR_VERSION, WEBKIT_MINOR_VERSION)));
621
622     HashSet<Page*>::iterator begin = allPages->begin();
623     HashSet<Page*>::iterator end = allPages->end();
624     KURL unused;
625     if (begin != end)
626         page.append(helpTextToRow("User Agent", header((*begin)->mainFrame()->loader()->userAgent(unused))));
627
628     page.append(footer());
629
630     return page.toString();
631 }
632
633 String aboutData(String aboutWhat)
634 {
635     if (aboutWhat.endsWith("about:appcache", false))
636         return appCachePage();
637     if (aboutWhat.endsWith("about:blob", false))
638         return blobPage();
639     if (aboutWhat.endsWith("about:cache", false))
640         return cachePage();
641     if (aboutWhat.endsWith("about:credits", false))
642         return creditsPage();
643     if (aboutWhat.endsWith("about:help", false))
644         return helpPage();
645     if (aboutWhat.endsWith("about:memory", false))
646         return memoryPage();
647     if (aboutWhat.endsWith("about:plugins", false))
648         return pluginsPage();
649     if (aboutWhat.endsWith("about:version", false))
650         return versionPage();
651
652     return String();
653 }
654
655 } // namespace WebKit
656 #endif // end of #if ENABLE(TIZEN_WEBKIT2_ABOUT_MEMORY)