This commit is a merge of two commits from branch beta/m34_1847.
Some refactoring was done in addition.
Load WRT injected bundle in the file protocol handler to be able to
access WRT's URL parsing. It is not possible to ask the render process to
do the URL parsing as some resource requests are requested via sync
messages from the render process. In such case the render process blocks
and is unable to process the URL parsing request.
Loading WRT's injected bundle in the browser process is potentially
dangerous as it expects to be loaded in the render process.
Original patches:
1) "Add file:// protocol handler specific for WRT." by Zbigniew Kostrzewa
http://165.213.202.130:8080/#/c/70649/
2) "fixup! Add file:// protocol handler specific for WRT" by Marek Ruszczynski
http://165.213.202.130:8080/#/c/70977/
Reviewed by: Daniel Waślicki, Jaesik Chang, Piotr Tworek
Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=10413
Change-Id: I94d0de04051c5d06ca65b552e3a7bb482d93d7d1
Signed-off-by: Piotr An Nguyen <p.annguyen@samsung.com>
'web_process_content_main_delegate_efl.h',
'wrt/dynamicplugin.cc',
'wrt/dynamicplugin.h',
+ 'wrt/wrt_file_protocol_handler.cc',
+ 'wrt/wrt_file_protocol_handler.h',
+ 'wrt/wrt_url_parse.h',
+ 'wrt/wrt_widget_host.cc',
+ 'wrt/wrt_widget_host.h',
'wrt/wrtwidget.cc',
'wrt/wrtwidget.h',
- 'wrt/wrt_url_parse.h',
# Temporary fix for M40 build
'third_party/webrtc/system_wrappers/source/cpu_features_tizen.c',
// JS garbage, not in purging irreplaceable objects.
IPC_MESSAGE_CONTROL0(EwkViewMsg_PurgeMemory)
-IPC_MESSAGE_CONTROL4(EwkViewMsg_SetWidgetInfo,
+IPC_MESSAGE_CONTROL4(WrtMsg_SetWidgetInfo,
int, // result: widgetHandle
double, // result: scale
std::string, // result: theme
std::string) // result: encodedBundle
-IPC_MESSAGE_CONTROL1(EwkViewMsg_SendWrtMessage,
+IPC_MESSAGE_CONTROL2(WrtMsg_ParseUrl,
+ int, // result: request_id
+ GURL) // result: url
+IPC_MESSAGE_CONTROL2(WrtMsg_ParseUrlResponse,
+ int, // result: request_id
+ GURL); // result: url
+
+IPC_MESSAGE_CONTROL1(WrtMsg_SendWrtMessage,
tizen_webview::WrtIpcMessageData /* data */);
IPC_MESSAGE_ROUTED0(EwkViewMsg_GetSelectionStyle)
#include "tizen_webview/public/tw_wrt.h"
#include "tizen_webview/tw_misc_utility.h"
+#include "wrt/wrt_widget_host.h"
+
using content::BrowserThread;
using content::BrowserContext;
using content::BrowserContextEfl;
}
void EWebContext::SendWidgetInfo(int widget_id, double scale, const string &theme, const string &encoded_bundle) {
-#if !defined(EWK_BRINGUP)
- content::RenderProcessHost::iterator i(content::RenderProcessHost::AllHostsIterator());
- for (; !i.IsAtEnd(); i.Advance()) {
- i.GetCurrentValue()->Send(
- new EwkViewMsg_SetWidgetInfo(widget_id, scale, theme, encoded_bundle));
- }
-#endif
+ WrtWidgetHost::Get()->SetWidgetInfo(widget_id, scale, theme, encoded_bundle);
}
void EWebContext::SendWrtMessage(const tizen_webview::WrtIpcMessageData& data) {
-#if !defined(EWK_BRINGUP)
- content::RenderProcessHost::iterator i(content::RenderProcessHost::AllHostsIterator());
- for (; !i.IsAtEnd(); i.Advance()) {
- i.GetCurrentValue()->Send(new EwkViewMsg_SendWrtMessage(data));
- }
-#endif
+ WrtWidgetHost::Get()->SendWrtMessage(data);
}
void EWebContext::SetMimeOverrideCallback(
};
ContentRendererClientEfl::ContentRendererClientEfl() {
- wrt_widget_.reset(new WrtWidget);
}
ContentRendererClientEfl::~ContentRendererClientEfl() {
void ContentRendererClientEfl::RenderThreadStarted()
{
- render_process_observer_.reset(new RenderProcessObserverEfl(this));
- visited_link_slave_.reset(new visitedlink::VisitedLinkSlave());
content::RenderThread* thread = content::RenderThread::Get();
+
+ wrt_widget_.reset(new WrtWidget);
+
+ render_process_observer_.reset(new RenderProcessObserverEfl(this));
thread->AddObserver(render_process_observer_.get());
+
+ visited_link_slave_.reset(new visitedlink::VisitedLinkSlave());
thread->AddObserver(visited_link_slave_.get());
wrt_url_parser_.reset(new WrtUrlParseImpl(wrt_widget_.get()));
return result;
}
-bool ContentRendererClientEfl::WillSendRequest(blink::WebFrame* frame,
- ui::PageTransition transition_type,
- const GURL& url,
- const GURL& first_party_for_cookies,
- GURL* new_url) {
- wrt_widget_->ParseUrl(url, *new_url);
- return true;
-}
-
-void ContentRendererClientEfl::SetWidgetInfo(int widgetHandle,
- double scaleFactor,
- const std::string &encodedBundle,
- const std::string &theme) {
- wrt_widget_->SetWidgetInfo(widgetHandle, scaleFactor, encodedBundle, theme);
-}
-
-void ContentRendererClientEfl::WrtMessageReceived(const tizen_webview::WrtIpcMessageData& data) {
- wrt_widget_->messageReceived(data);
-}
-
void ContentRendererClientEfl::DidCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
virtual void RenderViewCreated(content::RenderView* render_view);
- void SetWidgetInfo(int widgetHandle,
- double scaleFactor,
- const std::string &encodedBundle,
- const std::string &theme);
-
- void WrtMessageReceived(const tizen_webview::WrtIpcMessageData& data);
-
virtual void DidCreateScriptContext(blink::WebFrame* frame,
v8::Handle<v8::Context> context,
int extension_group,
blink::WebNavigationPolicy default_policy,
bool is_redirect) override;
- virtual bool WillSendRequest(blink::WebFrame* frame,
- ui::PageTransition transition_type,
- const GURL& url,
- const GURL& first_party_for_cookies,
- GURL* new_url);
-
virtual void GetNavigationErrorStrings(
content::RenderView* render_view,
blink::WebFrame* frame,
IPC_MESSAGE_HANDLER(EflViewMsg_ClearCache, OnClearCache)
IPC_MESSAGE_HANDLER(EflViewMsg_SetCache, OnSetCache)
IPC_MESSAGE_HANDLER(EwkViewMsg_PurgeMemory, OnPurgeMemory)
- IPC_MESSAGE_HANDLER(EwkViewMsg_SetWidgetInfo, OnWidgetInfo)
- IPC_MESSAGE_HANDLER(EwkViewMsg_SendWrtMessage, OnWrtMessage)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void RenderProcessObserverEfl::OnWidgetInfo(int widget_id,
- double scale,
- const std::string &theme,
- const std::string &encoded_bundle)
-{
- content_client_->SetWidgetInfo(widget_id, scale, encoded_bundle, theme);
-}
-
-void RenderProcessObserverEfl::OnWrtMessage(const tizen_webview::WrtIpcMessageData& data)
-{
- content_client_->WrtMessageReceived(data);
-}
-
void RenderProcessObserverEfl::WebKitInitialized()
{
webkit_initialized_ = true;
class Message;
}
-namespace tizen_webview {
-class WrtIpcMessageData;
-}
-
class ContentRendererClientEfl;
class RenderProcessObserverEfl : public content::RenderProcessObserver {
void OnPurgeMemory();
private:
- void OnWidgetInfo(int widget_id,
- double scale,
- const std::string &theme,
- const std::string &encoded_bundle);
void OnSetCache(const CacheParamsEfl& params);
- void OnWrtMessage(const tizen_webview::WrtIpcMessageData& data);
ContentRendererClientEfl* content_client_;
bool webkit_initialized_;
CacheParamsEfl pending_cache_params_;
#include "eweb_context.h"
#include "http_user_agent_settings_efl.h"
+#include "wrt/wrt_file_protocol_handler.h"
namespace content {
bool set_protocol = job_factory->SetProtocolHandler(
url::kDataScheme, new net::DataProtocolHandler);
DCHECK(set_protocol);
+ // TODO(z.kostrzewa) When WrtWidgetHost::Get()->InWrt() will be able to
+ // discover early enough that it is a WRT-originated launch then attach
+ // GetWrtFileProtocolHandler() for WRT and FileProtocolHandler otherwise
set_protocol = job_factory->SetProtocolHandler(
url::kFileScheme,
- new net::FileProtocolHandler(
- BrowserThread::GetBlockingPool()->
- GetTaskRunnerWithShutdownBehavior(
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)));
+ GetWrtFileProtocolHandler());
DCHECK(set_protocol);
// Set up interceptors in the reverse order.
--- /dev/null
+// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt_file_protocol_handler.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/sequenced_worker_pool.h"
+#include "content/public/browser/browser_thread.h"
+#include "net/base/filename_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/url_request/url_request_error_job.h"
+#include "net/url_request/url_request_file_dir_job.h"
+#include "net/url_request/url_request_file_job.h"
+#include "url/url_util.h"
+#include "wrt/dynamicplugin.h"
+#include "wrt/wrt_widget_host.h"
+
+using content::BrowserThread;
+
+namespace {
+class WrtURLRequestJob : public net::URLRequestFileJob {
+ public:
+ WrtURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const base::FilePath& file_path,
+ const scoped_refptr<base::TaskRunner>& file_task_runner)
+ : net::URLRequestFileJob(
+ request, network_delegate, file_path, file_task_runner),
+ weak_factory_(this) {
+ }
+
+ virtual void Start() {
+ // TODO(z.kostrzewa) This should be resolved by adding WrtFileProtocolHandler
+ // only for WRT-originated launch (see url_request_context_getter_efl.cc)
+ if (WrtWidgetHost::Get()->InWrt()) {
+ // Load WRT injected bundle here to be able access WRT's URL parsing.
+ // It is not possible to ask the render process to do the URL parsing as
+ // some resource requests are requested via sync messages from the render
+ // process. In such case the render process blocks and is unable to
+ // process the URL parsing request.
+ // Loading WRT's injected bundle in the browser process is potentially
+ // dagerous as it expects to be loaded in the render process.
+ std::string old_url = request()->url().possibly_invalid_spec();
+ std::string s_new_url;
+ DynamicPlugin::instance().parseURL(
+ &old_url, &s_new_url, WrtWidgetHost::Get()->WidgetId());
+ OnUrlRetrieved(GURL(s_new_url));
+ } else {
+ URLRequestFileJob::Start();
+ }
+ }
+
+ // TODO(z.kostrzewa) Shouldn't it be forwarded to a different thread?
+ void OnUrlRetrieved(const GURL& url) {
+ net::FileURLToFilePath(url, &file_path_);
+ if (file_path_.empty())
+ NotifyHeadersComplete();
+ else
+ URLRequestFileJob::Start();
+ }
+
+ private:
+ virtual ~WrtURLRequestJob() {}
+
+ base::WeakPtrFactory<WrtURLRequestJob> weak_factory_;
+};
+
+class WrtFileProtocolHandler :
+ public net::URLRequestJobFactory::ProtocolHandler {
+ public:
+ explicit WrtFileProtocolHandler(
+ const scoped_refptr<base::TaskRunner>& file_task_runner);
+ virtual ~WrtFileProtocolHandler();
+ virtual net::URLRequestJob* MaybeCreateJob(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) const;
+ virtual bool IsSafeRedirectTarget(const GURL& location) const;
+
+ private:
+ const scoped_refptr<base::TaskRunner> file_task_runner_;
+ DISALLOW_COPY_AND_ASSIGN(WrtFileProtocolHandler);
+};
+
+WrtFileProtocolHandler::WrtFileProtocolHandler(
+ const scoped_refptr<base::TaskRunner>& file_task_runner)
+ : file_task_runner_(file_task_runner) {}
+
+WrtFileProtocolHandler::~WrtFileProtocolHandler() {}
+
+net::URLRequestJob* WrtFileProtocolHandler::MaybeCreateJob(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
+ base::FilePath file_path;
+ const bool is_file = net::FileURLToFilePath(request->url(), &file_path);
+
+ // Check file access permissions.
+ if (!network_delegate ||
+ !network_delegate->CanAccessFile(*request, file_path)) {
+ return new net::URLRequestErrorJob(request, network_delegate, net::ERR_ACCESS_DENIED);
+ }
+
+ // We need to decide whether to create URLRequestFileJob for file access or
+ // URLRequestFileDirJob for directory access. To avoid accessing the
+ // filesystem, we only look at the path string here.
+ // The code in the URLRequestFileJob::Start() method discovers that a path,
+ // which doesn't end with a slash, should really be treated as a directory,
+ // and it then redirects to the URLRequestFileDirJob.
+ if (is_file &&
+ file_path.EndsWithSeparator() &&
+ file_path.IsAbsolute()) {
+ return new net::URLRequestFileDirJob(request, network_delegate, file_path);
+ }
+
+ // Use WRT file request job for all non-directories (including invalid
+ // file names).
+ return new WrtURLRequestJob(request,
+ network_delegate,
+ file_path,
+ file_task_runner_);
+}
+
+bool WrtFileProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
+ return false;
+}
+} // namespace
+
+net::URLRequestJobFactory::ProtocolHandler*
+GetWrtFileProtocolHandler() {
+ return
+ new WrtFileProtocolHandler(BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN));
+}
--- /dev/null
+// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_FILE_PROTOCOL_HANDLER
+#define WRT_FILE_PROTOCOL_HANDLER
+
+#include "net/url_request/url_request_job_factory.h"
+
+net::URLRequestJobFactory::ProtocolHandler* GetWrtFileProtocolHandler();
+
+#endif // WRT_FILE_PROTOCOL_HANDLER
--- /dev/null
+// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "wrt_widget_host.h"
+
+#include "base/lazy_instance.h"
+#include "common/render_messages_efl.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_request_info.h"
+#include "ipc/ipc_message_macros.h"
+#include "net/url_request/url_request.h"
+#include "tizen_webview/public/tw_wrt.h"
+#include "url/gurl.h"
+
+namespace {
+// TODO(z.kostrzewa) I would prefer not make it a singleton, check out
+// if it can't be a member of ContentMainDelegateEfl (but keep the static
+// getter, maybe?).
+base::LazyInstance<scoped_ptr<WrtWidgetHost> > g_wrt_widget_host =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool SendToAllRenderers(IPC::Message* message) {
+ bool result = false;
+ content::RenderProcessHost::iterator it =
+ content::RenderProcessHost::AllHostsIterator();
+ while (!it.IsAtEnd()) {
+ if (it.GetCurrentValue()->Send(message))
+ result = true;
+ it.Advance();
+ }
+ return result;
+}
+
+bool SendToRenderer(int renderer_id, IPC::Message* message) {
+ return content::RenderProcessHost::FromID(renderer_id)->Send(message);
+}
+}
+
+WrtWidgetHost* WrtWidgetHost::Get() {
+ // TODO(z.kostrzewa) LazyInstance is thread-safe but creating
+ // WrtWidgetHost is not - make it thread-safe.
+ if (!g_wrt_widget_host.Get().get())
+ g_wrt_widget_host.Get().reset(new WrtWidgetHost);
+ return g_wrt_widget_host.Get().get();
+}
+
+WrtWidgetHost::WrtWidgetHost()
+ : in_wrt_(false),
+ widget_id_(0) {
+}
+
+void WrtWidgetHost::GetUrlForRequest(
+ net::URLRequest* request,
+ base::Callback<void(const GURL&)> callback) {
+ // TODO(z.kostrzewa) Check on which thread(s) callbacks_ is touched
+ // and provide synchronization if required (either via a lock or
+ // by assuring that it is referenced only on one thread)
+ int callback_id = callback_id_generator_.GetNext();
+ callbacks_[callback_id] = callback;
+
+ int renderer_id, frame_id;
+ if (content::ResourceRequestInfo::GetRenderFrameForRequest(request, &renderer_id,
+ &frame_id))
+ if (SendToRenderer(renderer_id, new WrtMsg_ParseUrl(callback_id, request->url())))
+ return;
+
+ callbacks_.erase(callback_id);
+ callback.Run(GURL());
+}
+
+void WrtWidgetHost::SetWidgetInfo(int widget_id,
+ double scale,
+ const std::string& theme,
+ const std::string& encoded_bundle) {
+ // TODO shouldn't it be confirmed by WRT that this is really a launch
+ // of the widget identified by widget_id?
+ if (SendToAllRenderers(
+ new WrtMsg_SetWidgetInfo(widget_id, scale, theme, encoded_bundle))) {
+ // TODO(z.kostrzewa) This should be determined (somehow) on application
+ // startup. Can it be done via Application Framework/Package Manager?
+ in_wrt_ = true;
+ widget_id_ = widget_id;
+ }
+}
+
+void WrtWidgetHost::SendWrtMessage(
+ const tizen_webview::WrtIpcMessageData& message) {
+ SendToAllRenderers(new WrtMsg_SendWrtMessage(message));
+}
+
+bool WrtWidgetHost::InWrt() const {
+ return in_wrt_;
+}
+
+int WrtWidgetHost::WidgetId() const {
+ return widget_id_;
+}
+
+void WrtWidgetHost::OnUrlRetrieved(int callback_id, const GURL& url) {
+ callbacks_type::iterator it = callbacks_.find(callback_id);
+ if (callbacks_.end() == it)
+ return;
+
+ callbacks_type::mapped_type callback = it->second;
+ callbacks_.erase(callback_id);
+ callback.Run(url);
+}
+
--- /dev/null
+// Copyright (c) 2014,2015 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef WRT_HOST_H
+#define WRT_HOST_H
+
+#include <map>
+#include <string>
+
+#include "base/atomic_sequence_num.h"
+#include "base/callback.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace net {
+class URLRequest;
+}
+
+namespace tizen_webview {
+class WrtIpcMessageData;
+}
+
+class GURL;
+
+class WrtWidgetHost {
+ public:
+ static WrtWidgetHost* Get();
+
+ content::BrowserMessageFilter* GetMessageFilter() const;
+
+ void GetUrlForRequest(net::URLRequest* request,
+ base::Callback<void(const GURL&)> callback);
+
+ void SetWidgetInfo(int widget_id, double scale, const std::string& theme,
+ const std::string& encoded_bundle);
+
+ void SendWrtMessage(const tizen_webview::WrtIpcMessageData& message);
+
+ bool InWrt() const;
+
+ int WidgetId() const;
+
+ private:
+ typedef std::map<int, base::Callback<void(const GURL&)> > callbacks_type;
+
+ WrtWidgetHost();
+
+ DISALLOW_COPY_AND_ASSIGN(WrtWidgetHost);
+
+ void OnUrlRetrieved(int callback_id, const GURL& url);
+
+ base::AtomicSequenceNumber callback_id_generator_;
+ callbacks_type callbacks_;
+ bool in_wrt_;
+ int widget_id_;
+};
+
+
+#endif
-// Copyright 2014 Samsung Electronics. All rights reserved.
+// Copyright 2014,2015 Samsung Electronics. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "wrtwidget.h"
+#include "common/render_messages_efl.h"
+#include "content/public/renderer/render_thread.h"
+#include "ipc/ipc_sync_channel.h"
#include "wrt/dynamicplugin.h"
-#include <base/logging.h>
+// TODO(z.kostrzewa) Why it can't be implemented as IPC::ChannelProxy::MessageFilter (?)
+// Tried that and it seems that Observer starts receiving messages earlier than
+// MessageFilter what is crucial for message that sets widget handle
WrtWidget::WrtWidget()
: widgetHandle_(-1) {
}
+WrtWidget::~WrtWidget() {
+}
+
void WrtWidget::SetWidgetInfo(int widgetHandle,
double scaleFactor,
const std::string& encodedBundle,
-// Copyright 2014 Samsung Electronics. All rights reserved.
+// Copyright 2014,2015 Samsung Electronics. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#define WRTWIDGET_H
#include <string>
+
+#include "content/public/renderer/render_process_observer.h"
#include "url/gurl.h"
#include "v8/include/v8.h"
class WrtIpcMessageData;
}
+class WrtRenderThreadObserver;
+
+// Have to be created on the RenderThread.
class WrtWidget {
public:
WrtWidget();
+ ~WrtWidget();
void SetWidgetInfo(int widgetHandle,
double scaleFactor,
double scale_;
std::string theme_;
std::string encodedBundle_;
+ WrtRenderThreadObserver* observer_;
};
#endif // WRTWIDGET_H