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 #if !defined(EWK_BRINGUP)
65 // Unifdef it when this change will be relanded: http://165.213.202.130:8080/#/c/68152/
66 ewk_hit_test->imageURI = web_hit_test.absoluteImageURL().string().utf8();
67 ewk_hit_test->linkURI = web_hit_test.absoluteLinkURL().string().utf8();
68 ewk_hit_test->mediaURI = web_hit_test.absoluteMediaURL().string().utf8();
69 ewk_hit_test->linkLabel = web_hit_test.textContent().utf8();
70 ewk_hit_test->linkTitle = web_hit_test.titleDisplayString().utf8();
71 ewk_hit_test->isEditable = web_hit_test.isContentEditable();
73 int context = TW_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
74 if (!web_hit_test.absoluteLinkURL().isEmpty())
75 context |= TW_HIT_TEST_RESULT_CONTEXT_LINK;
76 if (!web_hit_test.absoluteImageURL().isEmpty())
77 context |= TW_HIT_TEST_RESULT_CONTEXT_IMAGE;
78 if (!web_hit_test.absoluteMediaURL().isEmpty())
79 context |= TW_HIT_TEST_RESULT_CONTEXT_MEDIA;;
80 if (web_hit_test.isSelected())
81 context |= TW_HIT_TEST_RESULT_CONTEXT_SELECTION;
82 if (web_hit_test.isContentEditable())
83 context |= TW_HIT_TEST_RESULT_CONTEXT_EDITABLE;
84 if (web_hit_test.node().isTextNode())
85 context |= TW_HIT_TEST_RESULT_CONTEXT_TEXT;
87 int context = TW_HIT_TEST_RESULT_CONTEXT_DOCUMENT;
89 ewk_hit_test->context = static_cast<tizen_webview::Hit_Test_Result_Context>(context);
90 ewk_hit_test->nodeData.attributeHash = 0;
92 if (ewk_hit_test->mode & TW_HIT_TEST_MODE_NODE_DATA) {
93 ewk_hit_test->nodeData.tagName = web_hit_test.node().nodeName().utf8();
94 ewk_hit_test->nodeData.nodeValue = web_hit_test.node().nodeValue().utf8();
97 if ((ewk_hit_test->mode & TW_HIT_TEST_MODE_IMAGE_DATA) &&
98 (ewk_hit_test->context & TW_HIT_TEST_RESULT_CONTEXT_IMAGE)) {
99 blink::WebElement hit_element = web_hit_test.node().toConst<blink::WebElement>();
100 ewk_hit_test->imageData.imageBitmap = hit_element.imageContents().getSkBitmap();
101 #if !defined(EWK_BRINGUP)
102 ewk_hit_test->imageData.fileNameExtension = hit_element.imageFilenameExtension().utf8();
107 void PopulateNodeAttributesMapFromHitTest(const blink::WebHitTestResult& web_hit_test,
108 NodeAttributesMap* attributes)
110 if (!attributes || !web_hit_test.node().isElementNode())
113 blink::WebElement hit_element = web_hit_test.node().toConst<blink::WebElement>();
114 for (unsigned int i = 0; i < hit_element.attributeCount(); i++) {
115 attributes->insert(std::pair<std::string, std::string>(
116 hit_element.attributeLocalName(i).utf8(), hit_element.attributeValue(i).utf8()));
122 RenderViewObserverEfl::RenderViewObserverEfl(content::RenderView* render_view)
123 : content::RenderViewObserver(render_view),
124 cached_min_page_scale_factor_(-1.0),
125 cached_max_page_scale_factor_(-1.0)
129 RenderViewObserverEfl::~RenderViewObserverEfl()
133 bool RenderViewObserverEfl::OnMessageReceived(const IPC::Message& message)
136 IPC_BEGIN_MESSAGE_MAP(RenderViewObserverEfl, message)
137 IPC_MESSAGE_HANDLER(EwkViewMsg_SetCSP, OnSetContentSecurityPolicy)
138 IPC_MESSAGE_HANDLER(EwkViewMsg_Scale, OnScale)
139 IPC_MESSAGE_HANDLER(EwkViewMsg_SetScroll, OnSetScroll)
140 IPC_MESSAGE_HANDLER(EwkViewMsg_UseSettingsFont, OnUseSettingsFont)
141 IPC_MESSAGE_HANDLER(EwkViewMsg_PlainTextGet, OnPlainTextGet)
142 IPC_MESSAGE_HANDLER(EwkViewMsg_GetSelectionStyle, OnGetSelectionStyle);
143 IPC_MESSAGE_HANDLER(EwkViewMsg_SelectClosestWord, OnSelectClosestWord);
144 IPC_MESSAGE_HANDLER(EwkViewMsg_DoHitTest, OnDoHitTest)
145 IPC_MESSAGE_HANDLER(EwkViewMsg_PrintToPdf, OnPrintToPdf)
146 IPC_MESSAGE_HANDLER(EwkViewMsg_GetMHTMLData, OnGetMHTMLData);
147 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppIconUrlGet, OnWebAppIconUrlGet);
148 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppIconUrlsGet, OnWebAppIconUrlsGet);
149 IPC_MESSAGE_HANDLER(EwkViewMsg_WebAppCapableGet, OnWebAppCapableGet);
150 IPC_MESSAGE_HANDLER(EwkViewMsg_SetDrawsTransparentBackground, OnSetDrawsTransparentBackground);
151 IPC_MESSAGE_HANDLER(EwkViewMsg_SetBrowserFont, OnSetBrowserFont);
152 IPC_MESSAGE_UNHANDLED(handled = false)
153 IPC_END_MESSAGE_MAP()
157 void RenderViewObserverEfl::DidCreateDocumentElement(blink::WebLocalFrame* frame)
160 tizen_webview::ContentSecurityPolicyType type = TW_CSP_DEFAULT_POLICY;
161 Send(new EwkHostMsg_GetContentSecurityPolicy(render_view()->GetRoutingID(), &policy, &type));
163 #if !defined(EWK_BRINGUP)
164 // Since, Webkit supports some more types and we cast ewk type to Webkit type.
165 // We allow only ewk types.
166 if (type == TW_CSP_REPORT_ONLY || type == TW_CSP_ENFORCE_POLICY)
167 frame->document().setContentSecurityPolicyUsingHeader(blink::WebString::fromUTF8(policy), type);
171 void RenderViewObserverEfl::OnSetContentSecurityPolicy(const std::string& policy, tizen_webview::ContentSecurityPolicyType header_type)
173 #if !defined(EWK_BRINGUP)
174 blink::WebView* view = render_view()->GetWebView();
176 blink::WebDocument document = view->mainFrame()->document();
177 document.setContentSecurityPolicyUsingHeader(blink::WebString::fromUTF8(policy), header_type);
181 void RenderViewObserverEfl::OnScale(double scale_factor, int x, int y)
183 blink::WebView* view = render_view()->GetWebView();
187 view->setPageScaleFactor(scale_factor,
188 blink::WebPoint(x, y));
191 void RenderViewObserverEfl::OnSetScroll(int x, int y)
193 blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
197 #if !defined(EWK_BRINGUP)
198 // I think we should use SetCrollOffset here!
199 frame->setScrollPosition(blink::WebSize(x, y));
203 void RenderViewObserverEfl::OnUseSettingsFont()
205 blink::FontCache::fontCache()->invalidate();
207 #if !defined(EWK_BRINGUP)
208 blink::WebView* view = render_view()->GetWebView();
210 view->sendResizeEventAndForceLayout();
214 void RenderViewObserverEfl::OnPlainTextGet(int plain_text_get_callback_id)
216 blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
219 blink::WebString content = frame->contentAsText(INT_MAX);
220 Send(new EwkHostMsg_PlainTextGetContents(render_view()->GetRoutingID(), content.utf8(), plain_text_get_callback_id));
223 #if !defined(EWK_BRINGUP)
224 void RenderViewObserverEfl::DidChangeContentsSize(blink::WebFrame* frame, const blink::WebSize& size)
226 Send(new EwkHostMsg_DidChangeContentsSize(render_view()->GetRoutingID(),
232 void RenderViewObserverEfl::DidChangeScrollOffset(blink::WebLocalFrame* frame)
234 if (!frame || (render_view()->GetWebView()->mainFrame() != frame))
237 if (max_scroll_offset_ != frame->maximumScrollOffset()) { //Check for change in MaxScrollOffset
238 max_scroll_offset_ = frame->maximumScrollOffset();
239 Send(new EwkHostMsg_DidChangeMaxScrollOffset(render_view()->GetRoutingID(),
240 frame->maximumScrollOffset().width,
241 frame->maximumScrollOffset().height));
245 void RenderViewObserverEfl::OnGetSelectionStyle()
247 blink::WebView* view = render_view()->GetWebView();
251 blink::WebFrame* frame = view->focusedFrame();
255 #if !defined(EWK_BRINGUP)
256 // Unifdef it when this change will be relanded: http://165.213.202.130:8080/#/c/68152/
257 SelectionStylePrams params;
258 params.underline_state = frame->stateCommand(blink::WebString::fromUTF8("underline"));
259 params.italic_state = frame->stateCommand(blink::WebString::fromUTF8("italic"));
260 params.bold_state = frame->stateCommand(blink::WebString::fromUTF8("bold"));
261 blink::WebString bg_color = frame->valueCommand(blink::WebString::fromUTF8("BackColor"));
262 GetGRBAValuesFromString(std::string(bg_color.utf8()), ¶ms.bg_color.r, ¶ms.bg_color.g, ¶ms.bg_color.b, ¶ms.bg_color.a);
263 blink::WebString color = frame->valueCommand(blink::WebString::fromUTF8("ForeColor"));
264 GetGRBAValuesFromString(std::string(color.utf8()), ¶ms.color.r, ¶ms.color.g, ¶ms.color.b, ¶ms.color.a);
265 blink::WebString font_size = frame->valueCommand(blink::WebString::fromUTF8("FontSize"));
266 params.font_size = font_size.utf8();
267 params.order_list_state = frame->stateCommand(blink::WebString::fromUTF8("InsertOrderedList"));
268 params.un_order_list_state = frame->stateCommand(blink::WebString::fromUTF8("InsertUnorderedList"));
269 params.text_align_center_state = frame->stateCommand(blink::WebString::fromUTF8("JustifyCenter"));
270 params.text_align_left_state = frame->stateCommand(blink::WebString::fromUTF8("JustifyLeft"));
271 params.text_align_right_state = frame->stateCommand(blink::WebString::fromUTF8("JustifyRight"));
272 params.text_align_full_state = frame->stateCommand(blink::WebString::fromUTF8("JustifyFull"));
273 params.has_composition = frame->hasMarkedText();
274 Send(new EwkViewMsg_SelectionTextStyleState(render_view()->GetRoutingID(), params));
278 void RenderViewObserverEfl::OnSelectClosestWord(int x, int y)
280 blink::WebView* view = render_view()->GetWebView();
284 blink::WebFrame* frame = view->focusedFrame();
288 frame->selectClosestWord(x, y);
291 void RenderViewObserverEfl::OnDoHitTest(int view_x, int view_y, tizen_webview::Hit_Test_Mode mode)
293 if (!render_view() || !render_view()->GetWebView())
296 const blink::WebHitTestResult web_hit_test_result =
297 render_view()->GetWebView()->hitTestResultAt(
298 blink::WebPoint(view_x, view_y));
299 _Ewk_Hit_Test ewk_hit_test_result;
300 ewk_hit_test_result.mode = mode;
302 PopulateEwkHitTestData(web_hit_test_result, &ewk_hit_test_result);
303 NodeAttributesMap attributes;
304 if (ewk_hit_test_result.mode & TW_HIT_TEST_MODE_NODE_DATA)
305 PopulateNodeAttributesMapFromHitTest(web_hit_test_result, &attributes);
307 Send(new EwkViewHostMsg_HitTestReply(routing_id(), ewk_hit_test_result, attributes));
310 void RenderViewObserverEfl::OnPrintToPdf(int width, int height, const base::FilePath& filename)
312 blink::WebView* web_view = render_view()->GetWebView();
314 PrintWebViewHelperEfl print_helper(render_view(), filename);
315 print_helper.PrintToPdf(width, height);
318 void RenderViewObserverEfl::OnGetMHTMLData(int callback_id)
320 blink::WebView* view = render_view()->GetWebView();
324 std::string content_string;
325 blink::WebCString content = blink::WebPageSerializer::serializeToMHTML(view);
326 if (!content.isEmpty())
327 content_string = content.data();
329 Send(new EwkHostMsg_ReadMHTMLData(render_view()->GetRoutingID(), content_string, callback_id));
332 #if !defined(EWK_BRINGUP)
333 void RenderViewObserverEfl::DidChangePageScaleFactor()
335 blink::WebView* view = render_view()->GetWebView();
339 Send(new EwkHostMsg_DidChangePageScaleFactor(render_view()->GetRoutingID(), view->pageScaleFactor()));
343 void RenderViewObserverEfl::DidUpdateLayout()
345 blink::WebView* view = render_view()->GetWebView();
349 float min_scale = view->minimumPageScaleFactor();
350 float max_scale = view->maximumPageScaleFactor();
352 // Checking for change in minimum and maximum page scale factors
353 if (std::abs(cached_max_page_scale_factor_ - max_scale) < std::numeric_limits<float>::epsilon() &&
354 std::abs(cached_min_page_scale_factor_ - min_scale) < std::numeric_limits<float>::epsilon())
357 cached_max_page_scale_factor_ = max_scale;
358 cached_min_page_scale_factor_ = min_scale;
359 Send(new EwkHostMsg_DidChangePageScaleRange(render_view()->GetRoutingID(), min_scale, max_scale));
362 void RenderViewObserverEfl::OnSetDrawsTransparentBackground(bool draws_transparent_background)
364 blink::WebView* view = render_view()->GetWebView();
368 blink::WebColor backgroundColor = draws_transparent_background ?
369 static_cast<blink::WebColor>(0x00000000) : static_cast<blink::WebColor>(0xFFFFFFFF);
371 view->setBaseBackgroundColor(backgroundColor);
374 void RenderViewObserverEfl::OnWebAppIconUrlGet(int callback_id)
376 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
381 blink::WebDocument document = frame->document();
382 blink::WebElement head = document.head();
388 std::string appleIconUrl;
389 blink::WebNodeList nodes = head.childNodes();
390 // We're looking for Apple style rel ("apple-touch-*")
391 // and Google style rel ("icon"), but we prefer the Apple one
392 // when both appear, as WebKit-efl was looking only for Apple style rels.
393 for (int i = 0; i < nodes.length(); ++i) {
394 blink::WebNode node = nodes.item(i);
395 if (!node.isElementNode()) {
398 blink::WebElement elem = node.to<blink::WebElement>();
399 if (!elem.hasHTMLTagName("link")) {
402 std::string rel = elem.getAttribute("rel").utf8();
403 if (LowerCaseEqualsASCII(rel, "apple-touch-icon") || // Apple's way
404 LowerCaseEqualsASCII(rel, "apple-touch-icon-precomposed")) {
405 appleIconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
407 } else if (LowerCaseEqualsASCII(rel, "icon")) { // Google's way
408 iconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
411 Send(new EwkHostMsg_WebAppIconUrlGet(render_view()->GetRoutingID(), appleIconUrl.empty() ? iconUrl : appleIconUrl, callback_id));
414 void RenderViewObserverEfl::OnWebAppIconUrlsGet(int callback_id) {
415 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
420 blink::WebDocument document = frame->document();
421 blink::WebElement head = document.head();
426 std::map<std::string, std::string> iconUrls;
427 blink::WebNodeList nodes = head.childNodes();
428 for (int i = 0; i < nodes.length(); ++i) {
429 blink::WebNode node = nodes.item(i);
430 if (!node.isElementNode()) {
433 blink::WebElement elem = node.to<blink::WebElement>();
434 if (!elem.hasHTMLTagName("link")) {
437 std::string rel = elem.getAttribute("rel").utf8();
438 if (LowerCaseEqualsASCII(rel, "apple-touch-icon") || // Apple's way
439 LowerCaseEqualsASCII(rel, "apple-touch-icon-precomposed") || // same here
440 LowerCaseEqualsASCII(rel, "icon")) { // Google's way
441 std::string iconSize = elem.getAttribute("sizes").utf8();
442 std::string iconUrl = document.completeURL(elem.getAttribute("href")).string().utf8();
444 iconUrls[iconSize] = iconUrl;
447 Send(new EwkHostMsg_WebAppIconUrlsGet(render_view()->GetRoutingID(), iconUrls, callback_id));
450 void RenderViewObserverEfl::OnWebAppCapableGet(int callback_id) {
451 blink::WebFrame *frame = render_view()->GetWebView()->mainFrame();
455 blink::WebDocument document = frame->document();
456 blink::WebElement head = document.head();
460 bool capable = false;
461 blink::WebNodeList nodes = head.childNodes();
462 for (int i = 0; i < nodes.length(); ++i) {
463 blink::WebNode node = nodes.item(i);
464 if (!node.isElementNode())
467 blink::WebElement elem = node.to<blink::WebElement>();
468 if (!elem.hasHTMLTagName("meta"))
471 std::string name = elem.getAttribute("name").utf8();
472 if (LowerCaseEqualsASCII(name, "apple-mobile-web-app-capable") || // Apple's way
473 LowerCaseEqualsASCII(name, "mobile-web-app-capable")) { // Google's way
474 std::string content = elem.getAttribute("content").utf8();
475 if (LowerCaseEqualsASCII(content, "yes")) {
481 Send(new EwkHostMsg_WebAppCapableGet(render_view()->GetRoutingID(), capable, callback_id));
484 void RenderViewObserverEfl::OrientationChangeEvent()
486 #if !defined(EWK_BRINGUP)
487 // Previosly OrientationChangeEvent() had orientation parameter.
488 // Now it was removed. Thanks Mounir.
489 // Need to figure out how to get orientation.
490 Send(new EwkHostMsg_OrientationChangeEvent(render_view()->GetRoutingID(), orientation));
494 void RenderViewObserverEfl::WillSubmitForm(blink::WebFrame* frame, const blink::WebFormElement& form)
496 GURL url(form.action());
497 Send(new EwkHostMsg_FormSubmit(routing_id(),url));
500 void RenderViewObserverEfl::OnSetBrowserFont()
502 #if !defined(EWK_BRINGUP)
503 blink::WebView* view = render_view()->GetWebView();
505 view->setBrowserFont();