[M85 Migration] Support PrepareErrorPage
[platform/framework/web/chromium-efl.git] / tizen_src / ewk / efl_integration / renderer / render_frame_observer_efl.cc
1 // Copyright 2014 Samsung Electronics. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "renderer/render_frame_observer_efl.h"
6
7 #include "content/common/content_client_export.h"
8 #include "content/common/frame_messages.h"
9 #include "content/public/common/content_client.h"
10 #include "content/public/common/url_constants.h"
11 #include "content/public/renderer/content_renderer_client.h"
12 #include "content/public/renderer/render_frame.h"
13 #include "content/public/renderer/render_view.h"
14 // RenderFrameImpl declares itself as a friend class to
15 // RenderFrameObserver. In order to access private members of
16 // the former from a descendant class of RenderFrameObserver,
17 // we define redefine "private" while including the associated header.
18 #define private public
19 #include "content/renderer/render_frame_impl.h"
20 #undef private
21 #include "common/render_messages_ewk.h"
22 #include "net/url_request/url_request_status.h"
23 #include "renderer/content_renderer_client_efl.h"
24 #include "third_party/blink/public/platform/url_conversion.h"
25 #include "third_party/blink/public/platform/web_url_error.h"
26 #include "third_party/blink/public/platform/web_url_request.h"
27 #include "third_party/blink/public/web/web_document.h"
28 #include "third_party/blink/public/web/web_element.h"
29 #include "third_party/blink/public/web/web_element_collection.h"
30 #include "third_party/blink/public/web/web_form_element.h"
31 #include "third_party/blink/public/web/web_local_frame.h"
32 #include "third_party/blink/public/web/web_view.h"
33
34 #include "base/logging.h"
35
36 using blink::WebDocument;
37 using blink::WebElement;
38 using blink::WebElementCollection;
39 using blink::WebFrame;
40 using blink::WebLocalFrame;
41 using blink::WebView;
42
43 namespace content {
44
45 namespace {
46
47 WebElement GetFocusedElement(WebLocalFrame* frame) {
48   WebDocument doc = frame->GetDocument();
49   if (!doc.IsNull())
50     return doc.FocusedElement();
51
52   return WebElement();
53 }
54
55 bool hasHTMLTagNameSelect(const WebElement& element) {
56   if (element.IsNull())
57     return false;
58
59   if (element.HasHTMLTagName("select"))
60     return true;
61
62   return false;
63 }
64
65 } // namespace
66
67 RenderFrameObserverEfl::RenderFrameObserverEfl(RenderFrame* render_frame)
68     : content::RenderFrameObserver(render_frame) {
69 }
70
71 RenderFrameObserverEfl::~RenderFrameObserverEfl() {
72 }
73
74 void RenderFrameObserverEfl::OnDestruct() {
75   delete this;
76 }
77
78 bool RenderFrameObserverEfl::OnMessageReceived(const IPC::Message& message) {
79   bool handled = true;
80   IPC_BEGIN_MESSAGE_MAP(RenderFrameObserverEfl, message)
81     IPC_MESSAGE_HANDLER(EwkFrameMsg_LoadNotFoundErrorPage, OnLoadNotFoundErrorPage)
82 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
83     IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
84 #endif
85     IPC_MESSAGE_HANDLER(EwkFrameMsg_MoveToNextOrPreviousSelectElement, OnMoveToNextOrPreviousSelectElement)
86     IPC_MESSAGE_HANDLER(EwkFrameMsg_RequestSelectCollectionInformation, OnRequestSelectCollectionInformation);
87     IPC_MESSAGE_UNHANDLED(handled = false)
88   IPC_END_MESSAGE_MAP()
89   return handled;
90 }
91
92 void RenderFrameObserverEfl::OnSelectPopupMenuItems(
93     bool canceled,
94     const std::vector<int>& selected_indices) {
95 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
96   RenderFrameImpl* render_frame_impl_ = static_cast<RenderFrameImpl*>(render_frame());
97   ExternalPopupMenu* external_popup_menu_ = render_frame_impl_->external_popup_menu_.get();
98   if (external_popup_menu_ == NULL)
99     return;
100   // It is possible to receive more than one of these calls if the user presses
101   // a select faster than it takes for the show-select-popup IPC message to make
102   // it to the browser UI thread. Ignore the extra-messages.
103   // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
104   canceled = canceled || !hasHTMLTagNameSelect(GetFocusedElement(render_frame()->GetWebFrame()));
105   external_popup_menu_->DidSelectItems(canceled, selected_indices);
106   if (canceled)
107     render_frame_impl_->DidHideExternalPopupMenu();
108 #endif
109 }
110
111 void RenderFrameObserverEfl::OnLoadNotFoundErrorPage(std::string errorUrl) {
112   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
113   blink::WebURL web_url = blink::WebURL(GURL(errorUrl));
114   blink::WebURLError error(net::URLRequestStatus::FAILED, web_url);
115   blink::WebURLRequest failed_request(web_url);
116   bool replace = true;
117
118   std::string error_html;
119
120   GetContentClientExport()->renderer()->PrepareErrorPage(
121       render_frame(), error, failed_request.HttpMethod().Ascii(), &error_html);
122
123   render_frame()->LoadHTMLString(error_html, GURL(kUnreachableWebDataURL), "UTF-8",
124                                  web_url, replace);
125 }
126
127 void RenderFrameObserverEfl::OnMoveToNextOrPreviousSelectElement(bool direction) {
128 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
129   content::RenderView* render_view_ = render_frame()->GetRenderView();
130   if (direction)
131     render_view_->GetWebView()->moveFocusToNext(WebView::TraverseFocusThrough::SelectElement);
132   else
133     render_view_->GetWebView()->moveFocusToPrevious(WebView::TraverseFocusThrough::SelectElement);
134 #endif
135 }
136
137 void RenderFrameObserverEfl::OnRequestSelectCollectionInformation() {
138   WebElement focused_element = GetFocusedElement(render_frame()->GetWebFrame());
139   if (focused_element.IsNull())
140     return;
141
142   content::RenderView* render_view_ = render_frame()->GetRenderView();
143   WebLocalFrame* focused_frame = render_view_->GetWebView()->FocusedFrame();
144   if (!focused_frame)
145     return;
146
147   WebDocument document = focused_frame->GetDocument();
148   if (document.IsNull())
149     return;
150
151   WebElementCollection select_elements =
152       document.GetElementsByHTMLTagName("select");
153   int count = 0;
154   int index = 0;
155   for (WebElement e = select_elements.FirstItem(); !e.IsNull();
156        e = select_elements.NextItem()) {
157     // take only visible elements into account
158 #if !defined(EWK_BRINGUP)  // FIXME: m76 bringup
159     if (e.HasNonEmptyLayoutSize()) {
160       if (e == focused_element)
161         index = count;
162       ++count;
163     }
164 #endif
165   }
166
167   if (count) {
168     bool prev_status = index > 0;
169     bool next_status = index < count - 1;
170
171     Send(new EwkHostMsg_RequestSelectCollectionInformationUpdateACK(
172         render_frame()->GetRoutingID(), count, index, prev_status, next_status));
173   }
174 }
175
176 void RenderFrameObserverEfl::DidChangeScrollOffset() {
177   if (render_frame()->GetRenderView()->GetMainRenderFrame() != render_frame())
178     return;
179
180   blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
181 #if !defined(EWK_BRINGUP)  // FIXME: m67 bringup
182   blink::WebSize contentsSize = frame->ContentsSize();
183 #else
184   blink::WebSize contentsSize;
185 #endif
186   blink::WebRect visibleContentRect = frame->VisibleContentRect();
187   blink::WebSize maximumScrollOffset(
188       contentsSize.width - visibleContentRect.width,
189       contentsSize.height - visibleContentRect.height);
190
191   if (max_scroll_offset_ != maximumScrollOffset) {
192     max_scroll_offset_ = maximumScrollOffset;
193     Send(new EwkHostMsg_DidChangeMaxScrollOffset(render_frame()->GetRoutingID(),
194                                                  maximumScrollOffset.width,
195                                                  maximumScrollOffset.height));
196   }
197
198   if (last_scroll_offset_ != frame->GetScrollOffset()) {
199     last_scroll_offset_ = frame->GetScrollOffset();
200     Send(new EwkHostMsg_DidChangeScrollOffset(render_frame()->GetRoutingID(),
201                                               frame->GetScrollOffset().width,
202                                               frame->GetScrollOffset().height));
203   }
204 }
205
206 void RenderFrameObserverEfl::WillSubmitForm(
207     const blink::WebFormElement& form) {
208   GURL url(blink::WebStringToGURL(form.Action()));
209   Send(new EwkHostMsg_FormSubmit(render_frame()->GetRoutingID(), url));
210 }
211
212 void RenderFrameObserverEfl::DidCreateScriptContext(
213     v8::Local<v8::Context> context,
214     int world_id) {
215   ContentRendererClientEfl* client = static_cast<ContentRendererClientEfl*>(
216       GetContentClientExport()->renderer());
217
218   client->DidCreateScriptContext(render_frame()->GetWebFrame(), context,
219                                  world_id);
220 }
221
222 void RenderFrameObserverEfl::WillReleaseScriptContext(
223     v8::Handle<v8::Context> context, int world_id) {
224   ContentRendererClientEfl* client = static_cast<ContentRendererClientEfl*>(
225       GetContentClientExport()->renderer());
226
227   client->WillReleaseScriptContext(
228       render_frame()->GetWebFrame(), context, world_id);
229 }
230
231 } // namespace content