1 #include "web_contents_delegate_efl.h"
3 #include "API/ewk_console_message_private.h"
4 #include "API/ewk_error_private.h"
5 #include "API/ewk_certificate_private.h"
6 #include "API/ewk_policy_decision_private.h"
7 #include "API/ewk_user_media_private.h"
8 #include "browser/policy_response_delegate_efl.h"
9 #include "browser/renderer_host/render_widget_host_view_efl.h"
10 #include "browser/inputpicker/color_chooser_efl.h"
11 #include "common/render_messages_efl.h"
12 #include "eweb_view.h"
13 #include "eweb_view_callbacks.h"
14 #include "public/ewk_view.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "content/common/view_messages.h"
18 #include "content/public/browser/invalidate_type.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/navigation_entry.h"
21 #include "content/public/browser/favicon_status.h"
22 #include "content/public/common/favicon_url.h"
23 #include "content/common/date_time_suggestion.h"
24 #include "net/base/load_states.h"
25 #include "net/http/http_response_headers.h"
26 #include "printing/pdf_metafile_skia.h"
28 #include "browser/favicon/favicon_service.h"
30 #include "tizen_webview/public/tw_web_context.h"
31 #include "tizen_webview/public/tw_input_type.h"
33 #ifdef TIZEN_AUTOFILL_SUPPORT
34 #include "browser/autofill/autofill_manager_delegate_efl.h"
35 #include "browser/password_manager/password_manager_client_efl.h"
36 #include "components/autofill/content/browser/autofill_driver_impl.h"
37 #include "components/autofill/core/browser/autofill_manager.h"
38 #include "components/web_modal/web_contents_modal_dialog_manager.h"
40 using autofill::AutofillDriverImpl;
41 using autofill::AutofillManager;
42 using autofill::AutofillManagerDelegateEfl;
46 using namespace tizen_webview;
50 void WritePdfDataToFile(printing::PdfMetafileSkia* metafile, const base::FilePath& filename) {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
53 metafile->SaveTo(filename);
57 WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view)
59 , is_fullscreen_(false)
61 , document_created_(false)
62 , should_open_new_window_(true)
63 , dialog_manager_(NULL)
64 , forward_backward_list_count_(0)
65 , weak_ptr_factory_(this) {
66 BrowserContext* browser_context = web_view_->context()->browser_context();
67 web_contents_ = WebContents::Create(WebContents::CreateParams(browser_context));
68 web_contents_->SetDelegate(this);
69 Observe(web_contents_);
71 #ifdef TIZEN_AUTOFILL_SUPPORT
72 AutofillManagerDelegateEfl::CreateForWebContents(web_contents_);
73 AutofillManagerDelegateEfl * autofill_manager =
74 AutofillManagerDelegateEfl::FromWebContents(web_contents_);
75 autofill_manager->SetEWebView(view);
76 AutofillDriverImpl::CreateForWebContentsAndDelegate(web_contents_,
77 autofill_manager, EWebView::GetPlatformLocale(), AutofillManager::DISABLE_AUTOFILL_DOWNLOAD_MANAGER);
78 PasswordManagerClientEfl::CreateForWebContents(web_contents_);
82 WebContentsDelegateEfl::WebContentsDelegateEfl(EWebView* view, WebContents* contents)
83 : WebContentsObserver(contents)
85 , is_fullscreen_(false)
86 , web_contents_(contents)
87 , document_created_(false)
88 , should_open_new_window_(true)
89 , dialog_manager_(NULL)
90 , forward_backward_list_count_(0)
91 , weak_ptr_factory_(this) {
92 web_contents_->SetDelegate(this);
95 WebContentsDelegateEfl::~WebContentsDelegateEfl() {
96 // It's important to delete web_contents_ before dialog_manager_
97 // destructor of web contents uses dialog_manager_
100 delete dialog_manager_;
103 void WebContentsDelegateEfl::NavigationStateChanged(const WebContents* source, unsigned changed_flags) {
104 if (changed_flags & content::INVALIDATE_TYPE_URL) {
105 const char* url = source->GetVisibleURL().spec().c_str();
106 web_view_->SmartCallback<EWebViewCallbacks::URLChanged>().call(url);
107 web_view_->SmartCallback<EWebViewCallbacks::URIChanged>().call(url);
111 void WebContentsDelegateEfl::LoadingStateChanged(WebContents* source,
112 bool to_different_document) {
113 if (source->IsLoading())
114 web_view_->SmartCallback<EWebViewCallbacks::LoadProgressStarted>().call();
116 web_view_->SmartCallback<EWebViewCallbacks::LoadProgressFinished>().call();
119 void WebContentsDelegateEfl::LoadProgressChanged(WebContents* source, double progress) {
120 web_view_->SetProgressValue(progress);
121 web_view_->SmartCallback<EWebViewCallbacks::LoadProgress>().call(&progress);
124 bool WebContentsDelegateEfl::ShouldCreateWebContents(
125 WebContents* web_contents,
127 WindowContainerType window_container_type,
128 const string16& /*frame_name*/,
129 const GURL& target_url,
130 const std::string& partition_id,
131 SessionStorageNamespace* session_storage_namespace) {
132 // this method is called ONLY when creating new window - no matter what type
133 web_view_->set_policy_decision(new tizen_webview::PolicyDecision(this, target_url));
134 web_view_->SmartCallback<EWebViewCallbacks::NewWindowPolicyDecision>().call(web_view_->get_policy_decision());
135 // Chromium has sync API. We cannot block this calls on UI thread.
136 CHECK(!web_view_->get_policy_decision()->isSuspended());
137 if (web_view_->get_policy_decision()->isDecided())
138 return should_open_new_window_;
140 // By default we return false. If embedder is not prepared to handle new window creation then we prevent this behaviour.
144 void WebContentsDelegateEfl::WebContentsCreated(
145 WebContents* source_contents,
146 int opener_render_frame_id,
147 const string16& frame_name,
148 const GURL& target_url,
149 WebContents* new_contents) {
150 // FIXME: we should have the specifications for the new window (size, position, etc.) to set it up correctly.
152 RenderWidgetHostViewEfl* source_rwhv = reinterpret_cast<RenderWidgetHostViewEfl*>(source_contents->GetRenderWidgetHostView());
154 EWebView* source_view = source_rwhv->eweb_view();
156 source_view->CreateNewWindow(new_contents);
159 void WebContentsDelegateEfl::CloseContents(WebContents* source) {
160 web_view_->SmartCallback<EWebViewCallbacks::WindowClosed>().call();
163 void WebContentsDelegateEfl::ToggleFullscreenModeForTab(WebContents* web_contents,
164 bool enter_fullscreen) {
165 is_fullscreen_ = enter_fullscreen;
167 web_view_->SmartCallback<EWebViewCallbacks::EnterFullscreen>().call();
169 web_view_->SmartCallback<EWebViewCallbacks::ExitFullscreen>().call();
172 bool WebContentsDelegateEfl::IsFullscreenForTabOrPending(
173 const WebContents* web_contents) const {
174 return is_fullscreen_;
177 void WebContentsDelegateEfl::RegisterProtocolHandler(WebContents* web_contents,
178 const std::string& protocol, const GURL& url, bool user_gesture) {
179 scoped_ptr<tizen_webview::Custom_Handlers_Data> protocol_data(
180 new tizen_webview::Custom_Handlers_Data(protocol.c_str(),
181 url.host().c_str(), url.spec().c_str()));
182 web_view_->SmartCallback<EWebViewCallbacks::RegisterProtocolHandler>().call(protocol_data.get());
185 WebContentsDelegateEfl::PendingAccessRequest::PendingAccessRequest(
186 const content::MediaStreamRequest& request,
187 const content::MediaResponseCallback& callback)
189 , callback(callback) {
192 WebContentsDelegateEfl::PendingAccessRequest::~PendingAccessRequest() {
195 void WebContentsDelegateEfl::OnAccessRequestResponse(Eina_Bool allowed) {
196 #warning "[M37] Fix media permissions"
198 MediaStreamDevices devices;
199 DVLOG(1) << __FUNCTION__ << " Queue Size: " << requests_Queue_.size();
200 if (requests_Queue_.empty()) {
201 DVLOG(1) << __FUNCTION__ << " Empty Queue ";
204 PendingAccessRequest pending_request = requests_Queue_.front();
205 if (pending_request.callback.is_null()) {
206 requests_Queue_.pop_front();
207 DVLOG(1) << __FUNCTION__ << " Invalid Callback ";
211 if (pending_request.request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
212 DVLOG(1) << __FUNCTION__ << "Added Audio Device";
213 devices.push_back(MediaStreamDevice(pending_request.request.audio_type,
214 "default", "Default"));
216 if (pending_request.request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
217 DVLOG(1) << __FUNCTION__ << " Added Video Device";
218 devices.push_back(MediaStreamDevice(pending_request.request.video_type,
221 pending_request.callback.Run(devices, scoped_ptr<MediaStreamUI>());
223 DVLOG(1) << __FUNCTION__ << " Decline request with empty list";
224 pending_request.callback.Run(MediaStreamDevices(),
225 scoped_ptr<MediaStreamUI>());
227 requests_Queue_.pop_front();
231 void WebContentsDelegateEfl::RequestMediaAccessPermission(
232 WebContents* web_contents,
233 const MediaStreamRequest& request,
234 const MediaResponseCallback& callback) {
235 //send callback to application to request for user permission.
236 _Ewk_User_Media_Permission_Request* media_permission_request =
237 new _Ewk_User_Media_Permission_Request(web_view_, request,this);
238 requests_Queue_.push_back(PendingAccessRequest(request, callback));
239 web_view_->SmartCallback<EWebViewCallbacks::UserMediaPermission>().call(
240 media_permission_request);
243 void WebContentsDelegateEfl::OnAuthRequired(net::URLRequest* request,
244 const std::string& realm,
245 LoginDelegateEfl* login_delegate) {
246 web_view_->InvokeAuthCallback(login_delegate, request->url(), realm);
249 void WebContentsDelegateEfl::DidStartProvisionalLoadForFrame(RenderFrameHost* render_frame_host,
250 const GURL& validated_url,
252 bool is_iframe_srcdoc) {
253 web_view_->SmartCallback<EWebViewCallbacks::ProvisionalLoadStarted>().call();
256 void WebContentsDelegateEfl::DidCommitProvisionalLoadForFrame(RenderFrameHost* render_frame_host,
258 PageTransition transition_type) {
259 web_view_->SmartCallback<EWebViewCallbacks::LoadCommitted>().call();
262 void WebContentsDelegateEfl::DidNavigateAnyFrame(const LoadCommittedDetails& details, const FrameNavigateParams& params) {
263 web_view_->SmartCallback<EWebViewCallbacks::ProvisionalLoadRedirect>().call();
264 static_cast<BrowserContextEfl*>(web_contents_->GetBrowserContext())->AddVisitedURLs(params.redirects);
267 void WebContentsDelegateEfl::DidFailProvisionalLoad(RenderFrameHost* render_frame_host,
268 const GURL& validated_url,
270 const string16& error_description) {
271 DidFailLoad(render_frame_host, validated_url, error_code, error_description);
273 void WebContentsDelegateEfl::DidFailLoad(RenderFrameHost* render_frame_host,
274 const GURL& validated_url,
276 const string16& error_description) {
277 if (render_frame_host->GetParent())
280 scoped_ptr<_Ewk_Error> error(new _Ewk_Error(error_code,
281 validated_url.possibly_invalid_spec().c_str(),
282 error_description.empty() ?
283 net::ErrorToString(error_code) :
284 UTF16ToUTF8(error_description).c_str()));
286 web_view_->SmartCallback<EWebViewCallbacks::LoadError>().call(error.get());
289 void WebContentsDelegateEfl::DidFinishLoad(RenderFrameHost* render_frame_host,
290 const GURL& validated_url) {
291 if (!render_frame_host->GetParent())
294 NavigationEntry *entry = web_contents()->GetController().GetActiveEntry();
295 FaviconStatus &favicon = entry->GetFavicon();
297 // check/update the url and favicon url in favicon database
299 fs.SetFaviconURLForPageURL(favicon.url, validated_url);
301 // download favicon if there is no such in database
302 if (!fs.ExistsForFaviconURL(favicon.url)) {
303 fprintf(stderr, "[DidFinishLoad] :: no favicon in database for URL: %s\n", favicon.url.spec().c_str());
304 favicon_downloader_.reset(new FaviconDownloader(web_contents(),
306 base::Bind(&WebContentsDelegateEfl::DidDownloadFavicon,
307 weak_ptr_factory_.GetWeakPtr())));
308 favicon_downloader_->Start();
310 web_view_->SmartCallback<EWebViewCallbacks::IconReceived>().call();
313 web_view_->SmartCallback<EWebViewCallbacks::LoadFinished>().call();
316 void WebContentsDelegateEfl::DidStartLoading(RenderViewHost* render_view_host) {
317 web_view_->SmartCallback<EWebViewCallbacks::LoadStarted>().call();
320 void WebContentsDelegateEfl::DidUpdateFaviconURL(const std::vector<FaviconURL>& candidates) {
321 // select and set proper favicon
322 for (unsigned int i = 0; i < candidates.size(); ++i) {
323 FaviconURL favicon = candidates[i];
324 if (favicon.icon_type == FaviconURL::FAVICON && !favicon.icon_url.is_empty()) {
325 NavigationEntry *entry = web_contents_->GetController().GetActiveEntry();
328 entry->GetFavicon().url = favicon.icon_url;
329 entry->GetFavicon().valid = true;
336 void WebContentsDelegateEfl::DidDownloadFavicon(bool success, const GURL& icon_url, const SkBitmap& bitmap) {
337 favicon_downloader_.reset();
340 fs.SetBitmapForFaviconURL(bitmap, icon_url);
341 // emit "icon,received"
342 web_view_->SmartCallback<EWebViewCallbacks::IconReceived>().call();
346 void WebContentsDelegateEfl::RequestCertificateConfirm(WebContents* /*web_contents*/,
348 const net::SSLInfo& ssl_info,
350 ResourceType /*resource_type*/,
351 bool /*overridable*/,
352 bool /*strict_enforcement*/,
353 const base::Callback<void(bool)>& callback,
354 CertificateRequestResultType* result) {
356 std::string pem_certificate;
357 if (!net::X509Certificate::GetPEMEncoded(ssl_info.cert->os_cert_handle(), &pem_certificate)) {
358 *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL;
361 // |result| can be used to deny/cancel request synchronously.
362 // ewk api does not need it. We don't use it.
363 scoped_ptr<_Ewk_Certificate_Policy_Decision> policy(new _Ewk_Certificate_Policy_Decision(url,
367 web_view_->SmartCallback<EWebViewCallbacks::RequestCertificateConfirm>().call(policy.get());
368 if (!policy->isSuspended && !policy->isDecided)
372 void WebContentsDelegateEfl::SetContentSecurityPolicy(const std::string& policy, tizen_webview::ContentSecurityPolicyType header_type) {
373 // Might makes sense as it only uses existing functionality already exposed for javascript. Needs extra api at blink side.
374 // Not necessary for eflwebview bringup.
375 #if !defined(EWK_BRINGUP)
376 if (document_created_) {
377 RenderViewHost* rvh = web_contents_->GetRenderViewHost();
378 rvh->Send(new EwkViewMsg_SetCSP(rvh->GetRoutingID(), policy, header_type));
380 DCHECK(!pending_content_security_policy_.get());
381 pending_content_security_policy_.reset(new ContentSecurityPolicy(policy, header_type));
386 void WebContentsDelegateEfl::ShowPopupMenu(const gfx::Rect& rect, blink::TextDirection textDirection, double pageScaleFactor, const std::vector<MenuItem>& items, int data, int selectedIndex, bool multiple) {
387 web_view_->ShowPopupMenu(rect, textDirection, pageScaleFactor, items, data, selectedIndex, multiple);
390 void WebContentsDelegateEfl::HidePopupMenu() {
391 web_view_->HidePopupMenu();
394 void WebContentsDelegateEfl::FindReply(WebContents* web_contents,
396 int number_of_matches,
397 const gfx::Rect& selection_rect,
398 int active_match_ordinal,
400 if (final_update && request_id == web_view_->current_find_request_id()) {
401 unsigned int uint_number_of_matches = static_cast<unsigned int>(number_of_matches);
402 web_view_->SmartCallback<EWebViewCallbacks::TextFound>().call(&uint_number_of_matches);
406 JavaScriptDialogManager* WebContentsDelegateEfl::GetJavaScriptDialogManager() {
407 if (!dialog_manager_)
408 dialog_manager_ = new JavaScriptDialogManagerEfl();
409 return dialog_manager_;
412 bool WebContentsDelegateEfl::OnMessageReceived(const IPC::Message& message) {
414 IPC_BEGIN_MESSAGE_MAP(WebContentsDelegateEfl, message)
415 IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_GetContentSecurityPolicy, OnGetContentSecurityPolicy)
416 IPC_MESSAGE_HANDLER(EwkHostMsg_DidPrintPagesToPdf, OnPrintedMetafileReceived)
417 IPC_MESSAGE_HANDLER(EwkHostMsg_WrtMessage, OnWrtPluginMessage)
418 IPC_MESSAGE_HANDLER(EwkHostMsg_FormSubmit, OnFormSubmit)
419 IPC_MESSAGE_HANDLER_DELAY_REPLY(EwkHostMsg_WrtSyncMessage, OnWrtPluginSyncMessage)
420 IPC_MESSAGE_UNHANDLED(handled = false)
421 IPC_END_MESSAGE_MAP()
426 void WebContentsDelegateEfl::OnFormSubmit(const GURL&url) {
427 web_view_->SmartCallback<EWebViewCallbacks::FormSubmit>().call(url.GetContent().c_str());
430 void WebContentsDelegateEfl::OnWrtPluginMessage(const tizen_webview::WrtIpcMessageData& data) {
431 scoped_ptr<tizen_webview::WrtIpcMessageData> p(new tizen_webview::WrtIpcMessageData);
433 p->value = data.value;
435 p->reference_id = data.reference_id;
437 web_view_->SmartCallback<EWebViewCallbacks::WrtPluginsMessage>().call(p.get());
440 void WebContentsDelegateEfl::OnWrtPluginSyncMessage(const tizen_webview::WrtIpcMessageData& data,
441 IPC::Message* reply) {
442 scoped_ptr<tizen_webview::WrtIpcMessageData> tmp(new tizen_webview::WrtIpcMessageData);
443 tmp->type = data.type;
444 web_view_->SmartCallback<EWebViewCallbacks::WrtPluginsMessage>().call(tmp.get());
445 EwkHostMsg_WrtSyncMessage::WriteReplyParams(reply, tmp->value);
449 void WebContentsDelegateEfl::DidFirstVisuallyNonEmptyPaint() {
450 web_view_->SmartCallback<EWebViewCallbacks::FrameRendered>().call(0);
453 void WebContentsDelegateEfl::OnGetContentSecurityPolicy(IPC::Message* reply_msg) {
454 document_created_ = true;
455 if (!pending_content_security_policy_.get()) {
456 EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams(reply_msg, std::string(), TW_CSP_DEFAULT_POLICY);
458 EwkHostMsg_GetContentSecurityPolicy::WriteReplyParams(reply_msg,
459 pending_content_security_policy_->policy, pending_content_security_policy_->header_type);
460 pending_content_security_policy_.reset();
465 void WebContentsDelegateEfl::OnPrintedMetafileReceived(const DidPrintPagesParams& params) {
466 base::SharedMemory shared_buf(params.metafile_data_handle, true);
467 if (!shared_buf.Map(params.data_size)) {
468 NOTREACHED() << "couldn't map";
471 scoped_ptr<printing::PdfMetafileSkia> metafile(new printing::PdfMetafileSkia);
472 if (!metafile->InitFromData(shared_buf.memory(), params.data_size)) {
473 NOTREACHED() << "Invalid metafile header";
476 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
477 base::Bind(&WritePdfDataToFile, metafile.release(), params.filename));
480 void WebContentsDelegateEfl::NavigationEntryCommitted(const LoadCommittedDetails& load_details) {
481 int forward_backward_list_count = web_contents()->GetController().GetEntryCount();
482 if (forward_backward_list_count != forward_backward_list_count_) {
483 web_view_->InvokeBackForwardListChangedCallback();
484 forward_backward_list_count_ = forward_backward_list_count;
488 void WebContentsDelegateEfl::RenderProcessGone(base::TerminationStatus status) {
489 // See RenderWidgetHostViewEfl::RenderProcessGone.
490 if (status == base::TERMINATION_STATUS_ABNORMAL_TERMINATION
491 || status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED
492 || status == base::TERMINATION_STATUS_PROCESS_CRASHED) {
494 web_view_->SmartCallback<EWebViewCallbacks::WebProcessCrashed>().call(&unused);
495 // A sane app would handle the callback and delete the view immediately.
496 // Otherwise, we will most probably crash when a method is called on |web_view_|.
500 bool WebContentsDelegateEfl::AddMessageToConsole(WebContents* source,
502 const string16& message,
504 const string16& source_id) {
505 scoped_ptr<_Ewk_Console_Message> console_message(new _Ewk_Console_Message(level,
506 UTF16ToUTF8(message).c_str(),
508 source->GetVisibleURL().spec().c_str()));
509 web_view_->SmartCallback<EWebViewCallbacks::ConsoleMessage>().call(console_message.get());
513 void WebContentsDelegateEfl::RunFileChooser(WebContents* web_contents, const FileChooserParams& params) {
514 web_view_->ShowFileChooser(params);
517 content::ColorChooser* WebContentsDelegateEfl::OpenColorChooser(
518 WebContents* web_contents,
520 const std::vector<ColorSuggestion>& suggestions) {
521 ColorChooserEfl* color_chooser_efl = new ColorChooserEfl(web_contents);
522 web_view_->RequestColorPicker(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), SkColorGetA(color));
524 return color_chooser_efl;
527 void WebContentsDelegateEfl::OpenDateTimeDialog(
528 ui::TextInputType dialog_type,
533 const std::vector<DateTimeSuggestion>& suggestions) {
535 std::string inputMethodHints;
537 switch (dialog_type) {
538 case ui::TEXT_INPUT_TYPE_DATE:
539 inputPickerType = TW_INPUT_TYPE_DATE;
540 inputMethodHints = "date";
542 case ui::TEXT_INPUT_TYPE_DATE_TIME:
543 inputPickerType = TW_INPUT_TYPE_DATETIME;
544 inputMethodHints = "datetime";
546 case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
547 inputPickerType = TW_INPUT_TYPE_DATETIMELOCAL;
548 inputMethodHints = "datetime-local";
550 case ui::TEXT_INPUT_TYPE_TIME:
551 inputPickerType = TW_INPUT_TYPE_TIME;
552 inputMethodHints = "time";
554 case ui::TEXT_INPUT_TYPE_WEEK:
555 inputPickerType = TW_INPUT_TYPE_WEEK;
556 inputMethodHints = "week";
558 case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE:
559 inputPickerType = TW_INPUT_TYPE_TEXT;
560 inputMethodHints = "date";
562 case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
563 inputPickerType = TW_INPUT_TYPE_DATETIME;
564 inputMethodHints = "datetime";
566 case ui::TEXT_INPUT_TYPE_MONTH:
567 inputPickerType = TW_INPUT_TYPE_MONTH;
568 inputMethodHints = "month";
571 inputPickerType = TW_INPUT_TYPE_TEXT;
572 inputMethodHints = "";
575 web_view_->InputPickerShow(static_cast<tizen_webview::Input_Type>(inputPickerType), inputMethodHints.c_str());
577 } //namespace content