1 #include "renderer/render_view_observer_efl.h"
6 #include "base/files/file_path.h"
7 #include "base/strings/string_number_conversions.h"
8 #include "base/strings/string_split.h"
9 #include "base/strings/string_util.h"
10 #include "content/public/renderer/render_view.h"
11 #include "common/render_messages_efl.h"
12 #include "third_party/WebKit/public/platform/WebCString.h"
13 #include "third_party/WebKit/public/platform/WebData.h"
14 #include "third_party/WebKit/public/platform/WebPoint.h"
15 #include "third_party/WebKit/public/platform/WebSize.h"
16 #include "third_party/WebKit/public/platform/WebString.h"
17 #include "third_party/WebKit/public/web/WebDocument.h"
18 #include "third_party/WebKit/public/web/WebFormElement.h"
19 #include "third_party/WebKit/public/web/WebFrame.h"
20 #include "third_party/WebKit/public/web/WebHitTestResult.h"
21 #include "third_party/WebKit/public/web/WebLocalFrame.h"
22 #include "third_party/WebKit/public/web/WebPageSerializer.h"
23 #include "third_party/WebKit/public/web/WebView.h"
24 #include "third_party/WebKit/public/web/WebNodeList.h"
26 // XXX: config.h needs to be included before internal blink headers.
27 // It'd be great if we did not include not internal blibk headers.
28 #include "third_party/WebKit/Source/config.h"
29 #include "third_party/WebKit/Source/platform/fonts/FontCache.h"
31 using namespace tizen_webview;
35 bool GetGRBAValuesFromString(const std::string& input, int* r, int* g, int* b, int* a)
37 bool parsing_status = false;
38 // for example - rgba(255, 255, 255, 255)
39 // for example - rgb(255, 255, 255)
40 if (std::string::npos != input.find("rgb")) {
41 size_t startPos = input.find("(");
42 size_t endPos = input.find(")");
44 std::string value = input.substr(startPos + 1, endPos - startPos - 1);
45 std::vector<std::string> colorValues;
46 base::SplitString(value, ',', &colorValues);
47 if (colorValues.size() == 4 || colorValues.size() == 3) {
48 base::StringToInt(colorValues[0], r);
49 base::StringToInt(colorValues[1], g);
50 base::StringToInt(colorValues[2], b);
51 if (std::string::npos != input.find("rgba") && colorValues.size() == 4)
52 base::StringToInt(colorValues[3], a);
55 parsing_status = true;
58 return parsing_status;
61 void PopulateEwkHitTestData(const blink::WebHitTestResult& web_hit_test, _Ewk_Hit_Test* ewk_hit_test)
64 ewk_hit_test->imageURI = web_hit_test.absoluteImageURL().string().utf8();
65 ewk_hit_test->linkURI = web_hit_test.absoluteLinkURL().string().utf8();
66 ewk_hit_test->mediaURI = web_hit_test.absoluteMediaURL().string().utf8();
67 ewk_hit_test->linkLabel = web_hit_test.textContent().utf8();
68 ewk_hit_test->linkTitle = web_hit_test.titleDisplayString().utf8();
69 ewk_hit_test->isEditable = web_hit_test.isContentEditable();
71 int context = TW_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
72 if (!web_hit_test.absoluteLinkURL().isEmpty())
73 context |= TW_HIT_TEST_RESULT_CONTEXT_LINK;
74 if (!web_hit_test.absoluteImageURL().isEmpty())
75 context |= TW_HIT_TEST_RESULT_CONTEXT_IMAGE;
76 if (!web_hit_test.absoluteMediaURL().isEmpty())
77 context |= TW_HIT_TEST_RESULT_CONTEXT_MEDIA;;
78 if (web_hit_test.isSelected())
79 context |= TW_HIT_TEST_RESULT_CONTEXT_SELECTION;
80 if (web_hit_test.isContentEditable())
81 context |= TW_HIT_TEST_RESULT_CONTEXT_EDITABLE;
82 if (web_hit_test.node().isTextNode())
83 context |= TW_HIT_TEST_RESULT_CONTEXT_TEXT;
85 ewk_hit_test->context = static_cast<tizen_webview::Hit_Test_Result_Context>(context);
86 ewk_hit_test->nodeData.attributeHash = 0;
88 if (ewk_hit_test->mode & TW_HIT_TEST_MODE_NODE_DATA) {
89 ewk_hit_test->nodeData.tagName = web_hit_test.node().nodeName().utf8();
90 ewk_hit_test->nodeData.nodeValue = web_hit_test.node().nodeValue().utf8();
93 if ((ewk_hit_test->mode & TW_HIT_TEST_MODE_IMAGE_DATA) &&
94 (ewk_hit_test->context & TW_HIT_TEST_RESULT_CONTEXT_IMAGE)) {
95 blink::WebElement hit_element = web_hit_test.node().toConst<blink::WebElement>();
96 ewk_hit_test->imageData.imageBitmap = hit_element.imageContents().getSkBitmap();
97 ewk_hit_test->imageData.fileNameExtension = hit_element.imageFilenameExtension().utf8();
101 void PopulateNodeAttributesMapFromHitTest(const blink::WebHitTestResult& web_hit_test,
102 NodeAttributesMap* attributes)
104 if (!attributes || !web_hit_test.node().isElementNode())
107 blink::WebElement hit_element = web_hit_test.node().toConst<blink::WebElement>();
108 for (unsigned int i = 0; i < hit_element.attributeCount(); i++) {
109 attributes->insert(std::pair<std::string, std::string>(
110 hit_element.attributeLocalName(i).utf8(), hit_element.attributeValue(i).utf8()));
116 RenderViewObserverEfl::RenderViewObserverEfl(content::RenderView* render_view)
117 : content::RenderViewObserver(render_view),
118 cached_min_page_scale_factor_(-1.0),
119 cached_max_page_scale_factor_(-1.0)
123 RenderViewObserverEfl::~RenderViewObserverEfl()
127 bool RenderViewObserverEfl::OnMessageReceived(const IPC::Message& message)
130 IPC_BEGIN_MESSAGE_MAP(RenderViewObserverEfl, message)
131 IPC_MESSAGE_HANDLER(EwkViewMsg_SetCSP, OnSetContentSecurityPolicy)
132 IPC_MESSAGE_HANDLER(EwkViewMsg_Scale, OnScale)
133 IPC_MESSAGE_HANDLER(EwkViewMsg_SetScroll, OnSetScroll)
134 IPC_MESSAGE_HANDLER(EwkViewMsg_UseSettingsFont, OnUseSettingsFont)
135 IPC_MESSAGE_HANDLER(EwkViewMsg_PlainTextGet, OnPlainTextGet)
136 IPC_MESSAGE_HANDLER(EwkViewMsg_GetSelectionStyle, OnGetSelectionStyle);
137 IPC_MESSAGE_HANDLER(EwkViewMsg_SelectClosestWord, OnSelectClosestWord);
138 IPC_MESSAGE_HANDLER(EwkViewMsg_DoHitTest, OnDoHitTest)
139 IPC_MESSAGE_HANDLER(EwkViewMsg_PrintToPdf, OnPrintToPdf)
140 IPC_MESSAGE_HANDLER(EwkViewMsg_GetMHTMLData, OnGetMHTMLData);
141 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppIconUrlGet, OnWebAppIconUrlGet);
142 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppIconUrlsGet, OnWebAppIconUrlsGet);
143 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppCapableGet, OnWebAppCapableGet);
144 IPC_MESSAGE_HANDLER(EwkViewMsg_SetDrawsTransparentBackground, OnSetDrawsTransparentBackground);
145 IPC_MESSAGE_HANDLER(EwkViewMsg_SetBrowserFont, OnSetBrowserFont);
146 IPC_MESSAGE_UNHANDLED(handled = false)
147 IPC_END_MESSAGE_MAP()
151 void RenderViewObserverEfl::DidCreateDocumentElement(blink::WebLocalFrame* frame)
154 tizen_webview::ContentSecurityPolicyType type = TW_CSP_DEFAULT_POLICY;
155 Send(new EwkHostMsg_GetContentSecurityPolicy(render_view()->GetRoutingID(), &policy, &type));
157 #if !defined(EWK_BRINGUP)
158 // Since, Webkit supports some more types and we cast ewk type to Webkit type.
159 // We allow only ewk types.
160 if (type == TW_CSP_REPORT_ONLY || type == TW_CSP_ENFORCE_POLICY)
161 frame->document().setContentSecurityPolicyUsingHeader(blink::WebString::fromUTF8(policy), type);
165 void RenderViewObserverEfl::OnSetContentSecurityPolicy(const std::string& policy, tizen_webview::ContentSecurityPolicyType header_type)
167 #if !defined(EWK_BRINGUP)
168 blink::WebView* view = render_view()->GetWebView();
170 blink::WebDocument document = view->mainFrame()->document();
171 document.setContentSecurityPolicyUsingHeader(blink::WebString::fromUTF8(policy), header_type);
175 void RenderViewObserverEfl::OnScale(double scale_factor, int x, int y)
177 blink::WebView* view = render_view()->GetWebView();
181 view->setPageScaleFactor(scale_factor,
182 blink::WebPoint(x, y));
185 void RenderViewObserverEfl::OnSetScroll(int x, int y)
187 blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
191 #if !defined(EWK_BRINGUP)
192 // I think we should use SetCrollOffset here!
193 frame->setScrollPosition(blink::WebSize(x, y));
197 void RenderViewObserverEfl::OnUseSettingsFont()
199 blink::FontCache::fontCache()->invalidate();
201 #if !defined(EWK_BRINGUP)
202 blink::WebView* view = render_view()->GetWebView();
204 view->sendResizeEventAndForceLayout();
208 void RenderViewObserverEfl::OnPlainTextGet(int plain_text_get_callback_id)
210 blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
213 blink::WebString content = frame->contentAsText(INT_MAX);
214 Send(new EwkHostMsg_PlainTextGetContents(render_view()->GetRoutingID(), content.utf8(), plain_text_get_callback_id));
217 #if !defined(EWK_BRINGUP)
218 void RenderViewObserverEfl::DidChangeContentsSize(blink::WebFrame* frame, const blink::WebSize& size)
220 Send(new EwkHostMsg_DidChangeContentsSize(render_view()->GetRoutingID(),
226 void RenderViewObserverEfl::DidChangeScrollOffset(blink::WebLocalFrame* frame)
228 if (!frame || (render_view()->GetWebView()->mainFrame() != frame))
231 if (max_scroll_offset_ != frame->maximumScrollOffset()) { //Check for change in MaxScrollOffset
232 max_scroll_offset_ = frame->maximumScrollOffset();
233 Send(new EwkHostMsg_DidChangeMaxScrollOffset(render_view()->GetRoutingID(),
234 frame->maximumScrollOffset().width,
235 frame->maximumScrollOffset().height));
239 void RenderViewObserverEfl::OnGetSelectionStyle()
241 blink::WebView* view = render_view()->GetWebView();
245 blink::WebFrame* frame = view->focusedFrame();
249 SelectionStylePrams params;
250 params.underline_state = frame->commandState(blink::WebString::fromUTF8("underline"));
251 params.italic_state = frame->commandState(blink::WebString::fromUTF8("italic"));
252 params.bold_state = frame->commandState(blink::WebString::fromUTF8("bold"));
253 blink::WebString bg_color = frame->commandValue(blink::WebString::fromUTF8("BackColor"));
254 GetGRBAValuesFromString(std::string(bg_color.utf8()), ¶ms.bg_color.r, ¶ms.bg_color.g, ¶ms.bg_color.b, ¶ms.bg_color.a);
255 blink::WebString color = frame->commandValue(blink::WebString::fromUTF8("ForeColor"));
256 GetGRBAValuesFromString(std::string(color.utf8()), ¶ms.color.r, ¶ms.color.g, ¶ms.color.b, ¶ms.color.a);
257 blink::WebString font_size = frame->commandValue(blink::WebString::fromUTF8("FontSize"));
258 params.font_size = font_size.utf8();
259 params.order_list_state = frame->commandState(blink::WebString::fromUTF8("InsertOrderedList"));
260 params.un_order_list_state = frame->commandState(blink::WebString::fromUTF8("InsertUnorderedList"));
261 params.text_align_center_state = frame->commandState(blink::WebString::fromUTF8("JustifyCenter"));
262 params.text_align_left_state = frame->commandState(blink::WebString::fromUTF8("JustifyLeft"));
263 params.text_align_right_state = frame->commandState(blink::WebString::fromUTF8("JustifyRight"));
264 params.text_align_full_state = frame->commandState(blink::WebString::fromUTF8("JustifyFull"));
265 params.has_composition = frame->hasMarkedText();
266 Send(new EwkViewMsg_SelectionTextStyleState(render_view()->GetRoutingID(), params));
269 void RenderViewObserverEfl::OnSelectClosestWord(int x, int y)
271 blink::WebView* view = render_view()->GetWebView();
275 blink::WebFrame* frame = view->focusedFrame();
279 frame->selectClosestWord(x, y);
282 void RenderViewObserverEfl::OnDoHitTest(int view_x, int view_y, tizen_webview::Hit_Test_Mode mode)
284 if (!render_view() || !render_view()->GetWebView())
287 const blink::WebHitTestResult web_hit_test_result =
288 render_view()->GetWebView()->hitTestResultAt(
289 blink::WebPoint(view_x, view_y));
290 _Ewk_Hit_Test ewk_hit_test_result;
291 ewk_hit_test_result.mode = mode;
293 PopulateEwkHitTestData(web_hit_test_result, &ewk_hit_test_result);
294 NodeAttributesMap attributes;
295 if (ewk_hit_test_result.mode & TW_HIT_TEST_MODE_NODE_DATA)
296 PopulateNodeAttributesMapFromHitTest(web_hit_test_result, &attributes);
298 Send(new EwkViewHostMsg_HitTestReply(routing_id(), ewk_hit_test_result, attributes));
301 void RenderViewObserverEfl::OnPrintToPdf(int width, int height, const base::FilePath& filename)
303 #if !(defined(EWK_BRINGUP) && defined(OS_TIZEN_MOBILE))
304 blink::WebView* web_view = render_view()->GetWebView();
306 PrintWebViewHelperEfl print_helper(render_view(), filename);
307 print_helper.PrintToPdf(width, height);
311 void RenderViewObserverEfl::OnGetMHTMLData(int callback_id)
313 blink::WebView* view = render_view()->GetWebView();
317 std::string content_string;
318 blink::WebCString content = blink::WebPageSerializer::serializeToMHTML(view);
319 if (!content.isEmpty())
320 content_string = content.data();
322 Send(new EwkHostMsg_ReadMHTMLData(render_view()->GetRoutingID(), content_string, callback_id));
325 #if !defined(EWK_BRINGUP)
326 void RenderViewObserverEfl::DidChangePageScaleFactor()
328 blink::WebView* view = render_view()->GetWebView();
332 Send(new EwkHostMsg_DidChangePageScaleFactor(render_view()->GetRoutingID(), view->pageScaleFactor()));
336 void RenderViewObserverEfl::DidUpdateLayout()
338 blink::WebView* view = render_view()->GetWebView();
342 float min_scale = view->minimumPageScaleFactor();
343 float max_scale = view->maximumPageScaleFactor();
345 // Checking for change in minimum and maximum page scale factors
346 if (std::abs(cached_max_page_scale_factor_ - max_scale) < std::numeric_limits<float>::epsilon() &&
347 std::abs(cached_min_page_scale_factor_ - min_scale) < std::numeric_limits<float>::epsilon())
350 cached_max_page_scale_factor_ = max_scale;
351 cached_min_page_scale_factor_ = min_scale;
352 Send(new EwkHostMsg_DidChangePageScaleRange(render_view()->GetRoutingID(), min_scale, max_scale));
355 void RenderViewObserverEfl::OnSetDrawsTransparentBackground(bool draws_transparent_background)
357 blink::WebView* view = render_view()->GetWebView();
361 blink::WebColor backgroundColor = draws_transparent_background ?
362 static_cast<blink::WebColor>(0x00000000) : static_cast<blink::WebColor>(0xFFFFFFFF);
364 view->setBaseBackgroundColor(backgroundColor);
367 void RenderViewObserverEfl::OnWebAppIconUrlGet(int callback_id)
369 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
374 blink::WebDocument document = frame->document();
375 blink::WebElement head = document.head();
381 std::string appleIconUrl;
382 blink::WebNodeList nodes = head.childNodes();
383 // We're looking for Apple style rel ("apple-touch-*")
384 // and Google style rel ("icon"), but we prefer the Apple one
385 // when both appear, as WebKit-efl was looking only for Apple style rels.
386 for (int i = 0; i < nodes.length(); ++i) {
387 blink::WebNode node = nodes.item(i);
388 if (!node.isElementNode()) {
391 blink::WebElement elem = node.to<blink::WebElement>();
392 if (!elem.hasHTMLTagName("link")) {
395 std::string rel = elem.getAttribute("rel").utf8();
396 if (LowerCaseEqualsASCII(rel, "apple-touch-icon") || // Apple's way
397 LowerCaseEqualsASCII(rel, "apple-touch-icon-precomposed")) {
398 appleIconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
400 } else if (LowerCaseEqualsASCII(rel, "icon")) { // Google's way
401 iconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
404 Send(new EwkHostMsg_WebAppIconUrlGet(render_view()->GetRoutingID(), appleIconUrl.empty() ? iconUrl : appleIconUrl, callback_id));
407 void RenderViewObserverEfl::OnWebAppIconUrlsGet(int callback_id) {
408 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
413 blink::WebDocument document = frame->document();
414 blink::WebElement head = document.head();
419 std::map<std::string, std::string> iconUrls;
420 blink::WebNodeList nodes = head.childNodes();
421 for (int i = 0; i < nodes.length(); ++i) {
422 blink::WebNode node = nodes.item(i);
423 if (!node.isElementNode()) {
426 blink::WebElement elem = node.to<blink::WebElement>();
427 if (!elem.hasHTMLTagName("link")) {
430 std::string rel = elem.getAttribute("rel").utf8();
431 if (LowerCaseEqualsASCII(rel, "apple-touch-icon") || // Apple's way
432 LowerCaseEqualsASCII(rel, "apple-touch-icon-precomposed") || // same here
433 LowerCaseEqualsASCII(rel, "icon")) { // Google's way
434 std::string iconSize = elem.getAttribute("sizes").utf8();
435 std::string iconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
437 iconUrls[iconSize] = iconUrl;
440 Send(new EwkHostMsg_WebAppIconUrlsGet(render_view()->GetRoutingID(), iconUrls, callback_id));
443 void RenderViewObserverEfl::OnWebAppCapableGet(int callback_id) {
444 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
448 blink::WebDocument document = frame->document();
449 blink::WebElement head = document.head();
453 bool capable = false;
454 blink::WebNodeList nodes = head.childNodes();
455 for (int i = 0; i < nodes.length(); ++i) {
456 blink::WebNode node = nodes.item(i);
457 if (!node.isElementNode())
460 blink::WebElement elem = node.to<blink::WebElement>();
461 if (!elem.hasHTMLTagName("meta"))
464 std::string name = elem.getAttribute("name").utf8();
465 if (LowerCaseEqualsASCII(name, "apple-mobile-web-app-capable") || // Apple's way
466 LowerCaseEqualsASCII(name, "mobile-web-app-capable")) { // Google's way
467 std::string content = elem.getAttribute("content").utf8();
468 if (LowerCaseEqualsASCII(content, "yes")) {
474 Send(new EwkHostMsg_WebAppCapableGet(render_view()->GetRoutingID(), capable, callback_id));
477 void RenderViewObserverEfl::OrientationChangeEvent()
479 #if !defined(EWK_BRINGUP)
480 // Previosly OrientationChangeEvent() had orientation parameter.
481 // Now it was removed. Thanks Mounir.
482 // Need to figure out how to get orientation.
483 Send(new EwkHostMsg_OrientationChangeEvent(render_view()->GetRoutingID(), orientation));
487 void RenderViewObserverEfl::WillSubmitForm(blink::WebFrame* frame, const blink::WebFormElement& form)
489 GURL url(form.action());
490 Send(new EwkHostMsg_FormSubmit(routing_id(),url));
493 void RenderViewObserverEfl::OnSetBrowserFont()
495 #if !defined(EWK_BRINGUP)
496 blink::WebView* view = render_view()->GetWebView();
498 view->setBrowserFont();