Implement content_shell app on top of chromium-efl library.
authorKamil Klimek <k.klimek@partner.samsung.com>
Thu, 13 Nov 2014 08:39:56 +0000 (09:39 +0100)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
This is an uglier, but faster solution to get content_shell
running on top of EFL chromium port. Instead of splitting
EFL port into content-EFL/EWK implementation parts it
it creates an efl specific content_shell_efl target that
depends on both original content_shell_lib and chromium-efl.
In essence it builds content_shell on top of both EFL content
API port and EWK specific content implementations.

Although the solution abuses chromium module boundaries and
introduces a lot of potentially invalid objects into
content_shell app it allows content_shell to work
with current M34 code base without refactoring it. The main
goal is to get something working fast without breaking
chromim-efl.

Long term, the EFL specific implementations of internal content
interfaces (RenderWidgetHostView, WebContentsView) should be
separated from EWK specific parts, moved into content module or
it's dependencies and original content_shell app should be used.
As it is right now the EWK specific objects like EWebView or
EWebContext will be invalid in cases where the content API is
initialized by content_shell app.

Added M40 Fixes

Original patch: http://165.213.202.130:8080/#/c/68602/
Original author: Piotr Tworek <p.tworek@samsung.com>

Bug: http://107.108.218.239/bugzilla/show_bug.cgi?id=5594

Change-Id: Ifc8c3ba660245d8637a49643239f111ecd3f0480
Signed-off-by: Kamil Klimek <k.klimek@partner.samsung.com>
19 files changed:
tizen_src/README.md
tizen_src/build/build_desktop.sh
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.cc
tizen_src/impl/browser/renderer_host/render_widget_host_view_efl.h
tizen_src/impl/browser/web_contents/web_contents_view_efl.cc
tizen_src/impl/browser/web_contents/web_contents_view_efl.h
tizen_src/impl/chromium-efl.gyp
tizen_src/impl/eweb_context.cc
tizen_src/impl/eweb_context.h
tizen_src/impl/eweb_view.cc
tizen_src/impl/gl/gl_shared_context_efl.cc
tizen_src/impl/shell/message_pump_efl.cc [new file with mode: 0644]
tizen_src/impl/shell/message_pump_efl.h [new file with mode: 0644]
tizen_src/impl/shell/shell_efl.cc [new file with mode: 0644]
tizen_src/impl/shell/shell_main.cc [new file with mode: 0644]
tizen_src/impl/shell/shell_web_contents_view_delegate_efl.cc [new file with mode: 0644]
tizen_src/packaging/chromium-efl.spec
tizen_src/packaging/content_shell.in [new file with mode: 0644]
tizen_src/scripts/run-layout-tests [new file with mode: 0755]

index 0d6c92c..c65e8f0 100755 (executable)
@@ -12,14 +12,14 @@ Building
 
 ### For Desktop build
 
-    $ ./build/build_desktop.sh [-h|--help] [--skip-gyp] [--skip-ninja] [--ccache] [--debug]
+    $ ./build/build_desktop.sh [-h|--help] [--skip-gyp] [--skip-ninja] [--ccache] [--debug] [--content_shell]
 
 ### For Mobile build
 Before Tizen build You need to install GBS.
 Please refer to (https://developer.tizen.org/help/index.jsp?topic=%2Forg.tizen.
 platform.development%2Fhtml%2Fplatform_dev_env%2Fgit_build_system.htm)
 
-    $ build/build_mobile.sh [--clean] [--define '_debug_mode 1'] [--define '_skip_gyp 1'] [--define 'nodebug 1']
+    $ build/build_mobile.sh [--clean] [--define '_debug_mode 1'] [--define '_skip_gyp 1'] [--define 'nodebug 1'] [--define '_enable_content_shell 1']
                             [--ccache]
 
       [--define '_debug_mode 1']   excute debug build (default : release)
@@ -97,3 +97,36 @@ Coding style
 
 Internally we use the chromium coding style: http://www.chromium.org/developers/coding-style.
 For public headers we follow efl style.
+
+Running content shell
+-----------
+
+### For Desktop build
+    $ ./out.x64/{Debug,Release}/content_shell_efl --no-sandbox --use-gl=egl [command line flags]
+
+Full list of chromium command line switches can be found at: http://peter.sh/experiments/chromium-co
+mmand-line-switches/
+
+Testing
+-----------
+
+### Layout tests - Desktop
+Chromium unit tests need functional content_shell app. Before trying to run them make sure content_s
+hell
+is compiled and working.
+
+More information about chromium layout tests can be found at: http://www.chromium.org/developers/tes
+ting/webkit-layout-tests
+
+1. Install necessary dependencies. On some ubuntu boxes this can be done running the following scrip
+t:
+    $ ./src/build/install-build-deps.sh
+2. Execute webkit test runner:
+    $ ./scripts/run-layout-tests <optional arguments>
+
+run-layout-tests script can take multiple extra parameters. The ones listed above are required to ru
+n tests in release
+mode on Ubuntu. Some other useful switches include:
+    --debug               Run tests on debug build of chromium
+    --nocheck-sys-deps    Do not check if necessary dependencies have been installed on target system. Useful when not using supported ubuntu version
+    --help                Display full list of supported command line options
index 74b66d2..28af5af 100755 (executable)
@@ -58,6 +58,10 @@ if echo "$@" | grep -cq '\-\-build-ewk-unittests'; then
   BUILD_EWK_UNITTESTS=1
 fi
 
+if echo "$@" | grep -cq '\-\-content_shell'; then
+  BUILD_CONTENT_SHELL=1
+fi
+
 JHBUILD_STAMPFILE="${GYP_GENERATOR_OUTPUT}/Dependencies/Root/jhbuild.stamp"
 
 shouldForceJHBuild() {
@@ -124,5 +128,9 @@ if [ "$SKIP_NINJA" == "0" ]; then
     TARGETS="$TARGETS ewk_unittests"
   fi
 
+  if [ "$BUILD_CONTENT_SHELL" == "1" ]; then
+    TARGETS="$TARGETS content_shell_efl"
+  fi
+
   ninja -C ${GYP_GENERATOR_OUTPUT}/${BUILD_SUBDIRECTORY} ${JOBS} ${TARGETS}
 fi
index 1928bdc..5644595 100755 (executable)
@@ -135,6 +135,27 @@ RenderWidgetHostViewEfl::RenderWidgetHostViewEfl(RenderWidgetHost* widget, EWebV
   }
 
   gesture_recognizer_->AddGestureEventHelper(this);
+}
+
+void RenderWidgetHostViewEfl::Init(Evas_Object* view) {
+  DCHECK(view);
+  content_image_ = view;
+  evas_ = evas_object_evas_get(view);
+
+  // IMContext calls evas() getter on 'this' so it needs to be
+  // initialized after evas_ is valid
+  im_context_ = IMContextEfl::Create(this);
+
+  if (is_hw_accelerated_) {
+    gfx::Rect bounds = GetViewBoundsInPix();
+    if (!bounds.IsEmpty()) {
+      Init_EvasGL(bounds.width(), bounds.height());
+    } else {
+      int w, h;
+      evas_object_image_size_get(content_image_, &w, &h);
+      Init_EvasGL(w, h);
+    }
+  }
 
 #if defined(OS_TIZEN_MOBILE)
   disambiguation_popup_.reset(new DisambiguationPopupEfl(content_image_, this));
@@ -393,26 +414,6 @@ void RenderWidgetHostViewEfl::Init_EvasGL(int width, int height) {
   m_IsEvasGLInit = 1;
 }
 
-void RenderWidgetHostViewEfl::set_eweb_view(EWebView* view) {
-  web_view_ = view;
-  evas_ = web_view_->GetEvas();
-  DCHECK(evas_);
-
-  content_image_ = web_view_->GetContentImageObject();
-  DCHECK(content_image_);
-
-  if (is_hw_accelerated_) {
-    gfx::Rect bounds = GetViewBoundsInPix();
-    if (bounds.width() == 0 && bounds.height() == 0) {
-      LOG(ERROR)<<"set_eweb_view -- view width and height set to '0' --> skip to configure evasgl";
-    } else {
-      Init_EvasGL(bounds.width(), bounds.height());
-    }
-  }
-
-  im_context_ = IMContextEfl::Create(this);
-}
-
 bool RenderWidgetHostViewEfl::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewEfl, message)
@@ -444,7 +445,8 @@ bool RenderWidgetHostViewEfl::Send(IPC::Message* message) {
 }
 
 void RenderWidgetHostViewEfl::OnSelectionTextStyleState(const SelectionStylePrams& params) {
-  web_view_->OnQuerySelectionStyleReply(params);
+  if (web_view_)
+    web_view_->OnQuerySelectionStyleReply(params);
 }
 
 #if 0
@@ -580,12 +582,16 @@ void RenderWidgetHostViewEfl::WasHidden() {
 }
 
 void RenderWidgetHostViewEfl::Focus() {
-  web_view_->SetFocus(EINA_TRUE);
+  if (web_view_)
+    web_view_->SetFocus(EINA_TRUE);
   host_->Focus();
 }
 
 bool RenderWidgetHostViewEfl::HasFocus() const {
-  return web_view_->HasFocus();
+  if (web_view_)
+    return web_view_->HasFocus();
+
+  return evas_object_focus_get(content_image_) == EINA_TRUE;
 }
 
 void RenderWidgetHostViewEfl::MovePluginContainer(const WebPluginGeometry& move) {
@@ -660,7 +666,9 @@ void RenderWidgetHostViewEfl::OnTextInputStateChanged(
   if (im_context_) {
     im_context_->UpdateInputMethodState(params.type, params.can_compose_inline,
                                         params.show_ime_if_needed);
-    web_view_->QuerySelectionStyle();
+
+    if (web_view_)
+      web_view_->QuerySelectionStyle();
 
     // Obsolete TextInputTypeChanged was doing it in similar code block
     // Probably also required here
@@ -691,18 +699,22 @@ void RenderWidgetHostViewEfl::OnTextInputInFormStateChanged(bool is_in_form_tag)
 void RenderWidgetHostViewEfl::ImeCompositionRangeChanged(
   const gfx::Range& range,
   const std::vector<gfx::Rect>& character_bounds) {
-  SelectionControllerEfl* controller = web_view_->GetSelectionController();
-  if (controller) {
-    controller->SetCaretSelectionStatus(false);
-    controller->HideHandleAndContextMenu();
+  if (web_view_) {
+    SelectionControllerEfl* controller = web_view_->GetSelectionController();
+    if (controller) {
+      controller->SetCaretSelectionStatus(false);
+      controller->HideHandleAndContextMenu();
+    }
   }
 }
 
 void RenderWidgetHostViewEfl::FocusedNodeChanged(bool is_editable_node) {
-  SelectionControllerEfl* controller = web_view_->GetSelectionController();
-  if (controller) {
-    controller->SetCaretSelectionStatus(false);
-    controller->HideHandleAndContextMenu();
+  if (web_view_) {
+    SelectionControllerEfl* controller = web_view_->GetSelectionController();
+    if (controller) {
+      controller->SetCaretSelectionStatus(false);
+      controller->HideHandleAndContextMenu();
+    }
   }
 }
 
@@ -711,15 +723,18 @@ void RenderWidgetHostViewEfl::Destroy() {
 }
 
 void RenderWidgetHostViewEfl::SetTooltipText(const base::string16& text) {
-  web_view_->SmartCallback<EWebViewCallbacks::TooltipTextSet>().call(UTF16ToUTF8(text).c_str());
+  if (web_view_)
+    web_view_->SmartCallback<EWebViewCallbacks::TooltipTextSet>().call(UTF16ToUTF8(text).c_str());
 }
 
 void RenderWidgetHostViewEfl::SelectionChanged(const base::string16& text,
   size_t offset,
   const gfx::Range& range) {
-  SelectionControllerEfl* controller = web_view_->GetSelectionController();
-  if (controller)
-    controller->UpdateSelectionData(text);
+  if (web_view_) {
+    SelectionControllerEfl* controller = web_view_->GetSelectionController();
+    if (controller)
+      controller->UpdateSelectionData(text);
+  }
 }
 
 void RenderWidgetHostViewEfl::SelectionBoundsChanged(
@@ -738,7 +753,8 @@ void RenderWidgetHostViewEfl::SelectionBoundsChanged(
 
 void RenderWidgetHostViewEfl::DidStopFlinging() {
 #ifdef TIZEN_EDGE_EFFECT
-  web_view_->edgeEffect()->hide();
+  if (web_view_)
+    web_view_->edgeEffect()->hide();
 #endif
   // Unhide Selection UI when scrolling with fling gesture
   if (GetSelectionController() && GetSelectionController()->GetScrollStatus())
@@ -763,7 +779,8 @@ void RenderWidgetHostViewEfl::DispatchGestureEvent(ui::GestureEvent* event) {
 
 #ifdef OS_TIZEN
 void RenderWidgetHostViewEfl::SetRectSnapshot(const SkBitmap& bitmap) {
-  web_view_->UpdateMagnifierScreen(bitmap);
+  if (web_view_)
+    web_view_->UpdateMagnifierScreen(bitmap);
 }
 
 void RenderWidgetHostViewEfl::GetSnapshotForRect(gfx::Rect& rect) {
@@ -812,23 +829,26 @@ void RenderWidgetHostViewEfl::EndFrameSubscription() {
 
 #ifdef TIZEN_EDGE_EFFECT
 void RenderWidgetHostViewEfl::DidOverscroll(const DidOverscrollParams& params) {
-  const gfx::Vector2dF& accumulated_overscroll = params.accumulated_overscroll;
-  const gfx::Vector2dF& latest_overscroll_delta = params.latest_overscroll_delta;
-
-  if (latest_overscroll_delta.x() < 0 && (int)accumulated_overscroll.x() < 0)
-    web_view_->edgeEffect()->show("edge,left");
-  if (latest_overscroll_delta.x() > 0 && (int)accumulated_overscroll.x() > 0)
-    web_view_->edgeEffect()->show("edge,right");
-  if (latest_overscroll_delta.y() < 0 && (int)accumulated_overscroll.y() < 0)
-    web_view_->edgeEffect()->show("edge,top");
-  if (latest_overscroll_delta.y() > 0 && (int)accumulated_overscroll.y() > 0)
-    web_view_->edgeEffect()->show("edge,bottom");
+  if (web_view_) {
+    const gfx::Vector2dF& accumulated_overscroll = params.accumulated_overscroll;
+    const gfx::Vector2dF& latest_overscroll_delta = params.latest_overscroll_delta;
+
+    if (latest_overscroll_delta.x() < 0 && (int)accumulated_overscroll.x() < 0)
+      web_view_->edgeEffect()->show("edge,left");
+    if (latest_overscroll_delta.x() > 0 && (int)accumulated_overscroll.x() > 0)
+      web_view_->edgeEffect()->show("edge,right");
+    if (latest_overscroll_delta.y() < 0 && (int)accumulated_overscroll.y() < 0)
+      web_view_->edgeEffect()->show("edge,top");
+    if (latest_overscroll_delta.y() > 0 && (int)accumulated_overscroll.y() > 0)
+      web_view_->edgeEffect()->show("edge,bottom");
+  }
 }
 #endif
 
 #ifdef TIZEN_CONTENTS_DETECTION
 void RenderWidgetHostViewEfl::OnContentsDetected(const char* message) {
-  web_view_->ShowContentsDetectedPopup(message);
+  if (web_view_)
+    web_view_->ShowContentsDetectedPopup(message);
 }
 #endif
 
@@ -1048,7 +1068,8 @@ gfx::GLSurfaceHandle RenderWidgetHostViewEfl::GetCompositingSurface() {
 }
 
 void RenderWidgetHostViewEfl::ResizeCompositingSurface(const gfx::Size& size) {
-  web_view_->DidChangeContentsArea(size.width(), size.height());
+  if (web_view_)
+    web_view_->DidChangeContentsArea(size.width(), size.height());
 }
 
 void RenderWidgetHostViewEfl::RenderProcessGone(base::TerminationStatus, int error_code) {
@@ -1056,7 +1077,8 @@ void RenderWidgetHostViewEfl::RenderProcessGone(base::TerminationStatus, int err
   // It expects RenderWidgetHostView to delete itself.
   // We only inform |web_view_| that renderer has crashed.
   // and in "process,crashed" callback, app is expected to delete the view.
-  web_view_->set_renderer_crashed();
+  if (web_view_)
+    web_view_->set_renderer_crashed();
   Destroy();
 }
 
@@ -1099,19 +1121,19 @@ void RenderWidgetHostViewEfl::set_magnifier(bool status) {
 }
 
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Mouse_Down* event) {
-  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(web_view_->GetEvas(), web_view_->evas_object(), event, device_scale_factor_));
+  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(evas_, content_image_, event, device_scale_factor_));
 }
 
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Mouse_Up* event) {
-  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(web_view_->GetEvas(), web_view_->evas_object(), event, device_scale_factor_));
+  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(evas_, content_image_, event, device_scale_factor_));
 }
 
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Mouse_Move* event) {
-  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(web_view_->GetEvas(), web_view_->evas_object(), event, device_scale_factor_));
+  host_->ForwardMouseEvent(WebEventFactoryEfl::toWebMouseEvent(evas_, content_image_, event, device_scale_factor_));
 }
 
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Mouse_Wheel* event) {
-  host_->ForwardWheelEvent(WebEventFactoryEfl::toWebMouseEvent(web_view_->GetEvas(), web_view_->evas_object(), event, device_scale_factor_));
+  host_->ForwardWheelEvent(WebEventFactoryEfl::toWebMouseEvent(evas_, content_image_, event, device_scale_factor_));
 }
 
 void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Key_Down* event) {
@@ -1129,19 +1151,21 @@ void RenderWidgetHostViewEfl::HandleEvasEvent(const Evas_Event_Key_Down* event)
     host_->WasHidden();
   }
 
+  if (web_view_) {
 #ifdef TIZEN_CONTENTS_DETECTION
-  if (!strcmp(event->key, "XF86Stop")) {
-    PopupControllerEfl* popup_controller = web_view_->GetPopupController();
-    if (popup_controller)
-      popup_controller->closePopup();
-  }
+    if (!strcmp(event->key, "XF86Stop")) {
+      PopupControllerEfl* popup_controller = web_view_->GetPopupController();
+      if (popup_controller)
+        popup_controller->closePopup();
+    }
 #endif
 
-  //if (!strcmp(event->key, "XF86Stop") || !strcmp(event->key, "BackSpace")) {
-  if (!strcmp(event->key, "BackSpace")) {
-    SelectionControllerEfl* controller = web_view_->GetSelectionController();
-    if (controller)
-      controller->HideHandleAndContextMenu();
+    //if (!strcmp(event->key, "XF86Stop") || !strcmp(event->key, "BackSpace")) {
+    if (!strcmp(event->key, "BackSpace")) {
+      SelectionControllerEfl* controller = web_view_->GetSelectionController();
+      if (controller)
+        controller->HideHandleAndContextMenu();
+    }
   }
 
   if (im_context_) {
@@ -1320,22 +1344,27 @@ void RenderWidgetHostViewEfl::HandleGesture(ui::GestureEvent* event) {
   } else if (event->type() == ui::ET_GESTURE_END) {
     // Gesture end event is received (1) After scroll end (2) After Fling start
 #ifdef TIZEN_EDGE_EFFECT
-    web_view_->edgeEffect()->hide();
+    if (web_view_)
+      web_view_->edgeEffect()->hide();
 #endif
   }
 #ifdef TIZEN_EDGE_EFFECT
   else if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) {
-    if (gesture.data.scrollUpdate.deltaX < 0)
-      web_view_->edgeEffect()->hide("edge,left");
-    else if (gesture.data.scrollUpdate.deltaX > 0)
-      web_view_->edgeEffect()->hide("edge,right");
-    if (gesture.data.scrollUpdate.deltaY < 0)
-      web_view_->edgeEffect()->hide("edge,top");
-    else if (gesture.data.scrollUpdate.deltaY > 0)
-      web_view_->edgeEffect()->hide("edge,bottom");
+    if (web_view_) {
+      if (gesture.data.scrollUpdate.deltaX < 0)
+        web_view_->edgeEffect()->hide("edge,left");
+      else if (gesture.data.scrollUpdate.deltaX > 0)
+        web_view_->edgeEffect()->hide("edge,right");
+      if (gesture.data.scrollUpdate.deltaY < 0)
+        web_view_->edgeEffect()->hide("edge,top");
+      else if (gesture.data.scrollUpdate.deltaY > 0)
+        web_view_->edgeEffect()->hide("edge,bottom");
+    }
   } else if (event->type() == ui::ET_GESTURE_PINCH_BEGIN) {
+    if (web_view_)
       web_view_->edgeEffect()->disable();
   } else if (event->type() == ui::ET_GESTURE_PINCH_END) {
+    if (web_view_)
       web_view_->edgeEffect()->enable();
   }
 #endif
@@ -1449,7 +1478,8 @@ void RenderWidgetHostViewEfl::OnWebAppIconUrlsGet(const std::map<std::string, st
 
 void RenderWidgetHostViewEfl::OnDidChangeContentsSize(int width, int height) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  web_view_->DidChangeContentsSize(width, height);
+  if (web_view_)
+    web_view_->DidChangeContentsSize(width, height);
   host_->ScrollFocusedEditableNodeIntoRect(gfx::Rect(0, 0, 0, 0));
 
   if (is_hw_accelerated_ && !m_IsEvasGLInit)
@@ -1494,7 +1524,10 @@ void RenderWidgetHostViewEfl::OnDidChangePageScaleRange(double min_scale, double
 }
 
 SelectionControllerEfl* RenderWidgetHostViewEfl::GetSelectionController() {
-  return web_view_->GetSelectionController();
+  if (web_view_)
+    return web_view_->GetSelectionController();
+
+  return NULL;
 }
 
 void RenderWidgetHostViewEfl::SetComposition(const ui::CompositionText& composition_text) {
index 2d8d40f..6bf74f6 100755 (executable)
@@ -187,8 +187,9 @@ class RenderWidgetHostViewEfl
   void set_magnifier(bool status);
 
   void Init_EvasGL(int width, int height);
+  void Init(Evas_Object* view);
 
-  void set_eweb_view(EWebView*);
+  void set_eweb_view(EWebView* webview) { web_view_ = webview; }
   EWebView* eweb_view() const { return web_view_; }
   RenderWidgetHostImpl* host() const { return host_; }
   IMContextEfl* im_context() const { return im_context_; }
index dd8b485..9cf2be3 100644 (file)
@@ -10,6 +10,7 @@
 #include "browser/renderer_host/render_widget_host_view_efl.h"
 #include "eweb_context.h"
 #include "eweb_view.h"
+#include "gl/gl_shared_context_efl.h"
 #include "web_contents_delegate_efl.h"
 #include "content/public/browser/web_contents_view_delegate.h"
 
@@ -27,6 +28,7 @@ WebContentsView* CreateWebContentsView(
 WebContentsViewEfl::WebContentsViewEfl(WebContents* contents,
     WebContentsViewDelegate* delegate)
     : delegate_(delegate)
+    , native_view_(NULL)
     , drag_dest_delegate_(NULL)
     , web_contents_(contents) {}
 
@@ -36,6 +38,8 @@ WebContentsViewEfl::WebContentsViewEfl(WebContents* contents,
 void WebContentsViewEfl::CreateView(const gfx::Size& initial_size,
                                     gfx::NativeView context) {
   requested_size_ = initial_size;
+  native_view_ = static_cast<Evas_Object*>(context);
+  GLSharedContextEfl::Initialize(native_view_);
 
   if (delegate_)
     drag_dest_delegate_ = delegate_->GetDragDestDelegate();
@@ -43,16 +47,8 @@ void WebContentsViewEfl::CreateView(const gfx::Size& initial_size,
 
 RenderWidgetHostViewBase* WebContentsViewEfl::CreateViewForWidget(
     RenderWidgetHost* render_widget_host, bool is_guest_view_hack) {
-  WebContentsDelegateEfl* delegate =
-      static_cast<WebContentsDelegateEfl*>(web_contents_->GetDelegate());
-  if (!delegate) {
-    // If web_contents_ was created internally we do not have our delegate
-    // set up yet. This is the case for popups. We will create
-    // RenderWidgetHostView and the delegate when EWebView is created.
-    return NULL;
-  }
-
-  RenderWidgetHostViewEfl* view = new RenderWidgetHostViewEfl(render_widget_host, delegate->web_view());
+  RenderWidgetHostViewEfl* view = new RenderWidgetHostViewEfl(render_widget_host, GetEWebView());
+  view->Init(native_view_);
   view->Show();
 
   return view;
@@ -60,15 +56,12 @@ RenderWidgetHostViewBase* WebContentsViewEfl::CreateViewForWidget(
 
 RenderWidgetHostViewBase* WebContentsViewEfl::CreateViewForPopupWidget(
     RenderWidgetHost* render_widget_host) {
-  WebContentsDelegateEfl* delegate =
-      static_cast<WebContentsDelegateEfl*>(web_contents_->GetDelegate());
-  return new RenderWidgetHostViewEfl(render_widget_host, delegate->web_view());
+  return new RenderWidgetHostViewEfl(render_widget_host, GetEWebView());
 }
 
 void WebContentsViewEfl::SetPageTitle(const base::string16& title) {
-  WebContentsDelegateEfl* delegate = static_cast<WebContentsDelegateEfl*>(web_contents_->GetDelegate());
-  if (delegate)
-    delegate->web_view()->SmartCallback<EWebViewCallbacks::TitleChange>().call(base::UTF16ToUTF8(title).c_str());
+  if (GetEWebView())
+    GetEWebView()->SmartCallback<EWebViewCallbacks::TitleChange>().call(base::UTF16ToUTF8(title).c_str());
 }
 
 void WebContentsViewEfl::UpdateDragDest(RenderViewHost* host) {
@@ -201,4 +194,17 @@ void WebContentsViewEfl::ShowPopupMenu(RenderFrameHost* render_frame_host,
 }
 #endif
 
+EWebView* WebContentsViewEfl::GetEWebView() const {
+  // TODO: not best way, but until we merge 5486351bf10375c64ec997e613a2155ca3a24cc7
+  // this is the only way to make it work. Fixup ca5b85c82985e02ee7e908952ba894ef7b7d2a32
+  // should be merged too.
+  WebContentsDelegateEfl* delegate =
+      reinterpret_cast<WebContentsDelegateEfl*>(web_contents_->GetDelegate());
+
+  if (delegate)
+    return delegate->web_view();
+
+  return NULL;
+}
+
 } // namespace content
index 54051ab..2a3ba8a 100644 (file)
 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
 #include "content/browser/web_contents/web_contents_view.h"
 
+#include <Evas.h>
+
+class EWebView;
+
 namespace content {
 
 class WebContents;
@@ -59,9 +63,15 @@ class WebContentsViewEfl
 #endif
   void UpdateDragDest(RenderViewHost* host);
 
+private:
+  EWebView* GetEWebView() const;
+
   // Our optional views wrapper.
   scoped_ptr<WebContentsViewDelegate> delegate_;
 
+  // Native EFL widget responsible for handling input and drawing
+  Evas_Object* native_view_;
+
   WebDragDestDelegate* drag_dest_delegate_;
 
   // The size we want the view to be.
index 36d0771..02f345f 100644 (file)
       'chromium-efl',
     ],
   },
+  {
+    'target_name': 'content_shell_efl',
+    'type': 'executable',
+    'dependencies': [
+      'chromium-efl-deps.gyp:efl',
+      'theme/theme.gyp:tizen_theme',
+      '<(chrome_src_dir)/content/content_shell_and_tests.gyp:content_shell_lib',
+      '<(chrome_src_dir)/content/content_shell_and_tests.gyp:content_shell_pak',
+      '<(chrome_src_dir)/breakpad/breakpad.gyp:minidump_stackwalk',
+      '<(chrome_src_dir)/breakpad/breakpad.gyp:dump_syms',
+      '<(chrome_src_dir)/tools/imagediff/image_diff.gyp:image_diff',
+      '<(chrome_src_dir)/base/allocator/allocator.gyp:allocator',
+      '<(chrome_src_dir)/sandbox/sandbox.gyp:sandbox',
+      'chromium-efl',
+    ],
+    'sources': [
+      'shell/shell_efl.cc',
+      'shell/shell_main.cc',
+      'shell/shell_web_contents_view_delegate_efl.cc',
+      'shell/message_pump_efl.h',
+      'shell/message_pump_efl.cc',
+    ],
+    'include_dirs': [
+      '.',
+    ],
+    'conditions': [
+      ['prebuilt_ld_gold_dir!=""', {
+        'ldflags': [
+          '-B<(prebuilt_ld_gold_dir)',
+        ],
+      } , { # prebuild_ld_gold_dir == ""
+        'ldflags': [
+          # Building the RPM in the GBS chroot fails with errors such as
+          # [  XXs] error: create archive failed on file /<path>/libchromium-efl.so: cpio: Bad magic
+          # [  XXs] RPM build errors:
+          # [  XXs]     create archive failed on file /<path>/libchromium-efl.so: cpio: Bad magic
+          # For now, work around it by passing a GNU ld-specific flag that optimizes the
+          # linker for memory usage.
+          # http://107.108.218.239/bugzilla/show_bug.cgi?id=6457
+          '-Wl,--no-keep-memory',
+        ],
+      }],
+    ],
+  },
   ],
 }
index a66c020..202fd4c 100644 (file)
@@ -230,7 +230,6 @@ bool EWebContext::ShouldOverrideMimeForURL(
 
 EWebContext::EWebContext(bool incognito)
     : m_pixmap(0),
-      initialized_(false),
       incognito_(incognito) {
   EwkGlobalData::Ensure();
 
@@ -240,15 +239,6 @@ EWebContext::EWebContext(bool incognito)
   web_cache_manager_.reset(new WebCacheManagerEfl(browser_context_.get()));
 }
 
-void EWebContext::InitializeGLSharedContext(Evas_Object* object) {
-  if (initialized_)
-    return;
-
-  initialized_ = true;
-
-  GLSharedContextEfl::Initialize(object);
-}
-
 EWebContext::~EWebContext() {
   VibrationProviderClient::DeleteInstance();
 }
index 83504e3..d672f44 100644 (file)
@@ -95,7 +95,6 @@ class EWebContext {
 
   void ClearCandidateData();
   void ClearPasswordData();
-  void InitializeGLSharedContext(Evas_Object* object);
 #if defined(OS_TIZEN_TV)
   FaviconDatabase* GetFaviconDatabase();
 #endif
@@ -113,7 +112,6 @@ class EWebContext {
   std::string proxy_uri_;
   scoped_ptr<EwkDidStartDownloadCallback> start_download_callback_;
   int m_pixmap;
-  bool initialized_;
   bool incognito_;
 };
 
index 8e80270..4ecb327 100644 (file)
@@ -286,7 +286,6 @@ EWebView::EWebView(tizen_webview::WebView* owner, tizen_webview::WebContext* con
       renderer_crashed_(false),
 #endif
       is_initialized_(false) {
-  context->GetImpl()->InitializeGLSharedContext(object);
 }
 
 void EWebView::Initialize() {
@@ -308,6 +307,7 @@ void EWebView::Initialize() {
     contents_for_new_window_ = NULL;
   } else {
     WebContents::CreateParams params(context_->browser_context());
+    params.context = GetContentImageObject();
     web_contents_.reset(WebContents::Create(params));
   }
   web_contents_delegate_.reset(new WebContentsDelegateEfl(this));
index 0c2edb6..beaeef6 100644 (file)
@@ -4,6 +4,7 @@
 
 #include "gl/gl_shared_context_efl.h"
 
+#include "base/threading/thread_restrictions.h"
 #include "gpu/command_buffer/service/mailbox_manager_impl.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_share_group.h"
@@ -102,6 +103,7 @@ void GLSharedContextEfl::Initialize(Evas_Object* object) {
   if (GLSharedContextEflPrivate::instance().get())
     return;
 
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
   GLSharedContextEflPrivate::instance() =
       new GLSharedContextEflPrivate(object);
 }
diff --git a/tizen_src/impl/shell/message_pump_efl.cc b/tizen_src/impl/shell/message_pump_efl.cc
new file mode 100644 (file)
index 0000000..d40de1c
--- /dev/null
@@ -0,0 +1,123 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 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 "message_pump_efl.h"
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+
+// EFL version 1.8 and later don't define the function
+// in the Ecore.h. It's still defined and visible however.
+extern "C" {
+int ecore_main_loop_iterate_may_block(int);
+}
+
+namespace base {
+
+namespace {
+void PipeCallback(void *data, void*, unsigned int) {
+  static_cast<MessagePumpEfl*>(data)->HandleScheduledWork();
+}
+}
+
+struct MessagePumpEfl::RunState {
+  Delegate* delegate;
+  bool should_quit;
+  int run_depth;
+};
+
+MessagePumpEfl::MessagePumpEfl()
+  : state_(NULL)
+  , pipe_(ecore_pipe_add(&PipeCallback, this))
+  , work_scheduled_(false) {
+}
+
+MessagePumpEfl::~MessagePumpEfl() {
+  ecore_pipe_del(pipe_);
+  pipe_ = NULL;
+}
+
+void MessagePumpEfl::Run(Delegate* delegate) {
+  RunState state;
+  state.delegate = delegate;
+  state.should_quit = false;
+  state.run_depth = state_ ? state_->run_depth + 1 : 1;
+
+  RunState* previous_state = state_;
+  state_ = &state;
+
+  bool more_work_is_plausible = true;
+  for (;;) {
+    bool block = !more_work_is_plausible;
+
+    more_work_is_plausible = ecore_main_loop_iterate_may_block(block);
+    if (state_->should_quit)
+      break;
+
+    more_work_is_plausible |= state_->delegate->DoWork();
+    if (state_->should_quit)
+      break;
+
+    more_work_is_plausible |=
+        state_->delegate->DoDelayedWork(&delayed_work_time_);
+    if (state_->should_quit)
+      break;
+
+    if (more_work_is_plausible)
+      continue;
+
+    more_work_is_plausible = state_->delegate->DoIdleWork();
+    if (state_->should_quit)
+      break;
+  }
+
+  state_ = previous_state;
+}
+
+void MessagePumpEfl::Quit() {
+  if (state_) {
+    state_->should_quit = true;
+  } else {
+    NOTREACHED() << "Quit called outside Run!";
+  }
+}
+
+void MessagePumpEfl::ScheduleWork() {
+  {
+    base::AutoLock locker(schedule_work_lock_);
+    if (work_scheduled_)
+      return;
+    work_scheduled_ = true;
+  }
+
+  static const char msg[] = "!";
+  if (!ecore_pipe_write(pipe_, msg, sizeof(msg))) {
+    NOTREACHED() << "Could not write to the UI message loop wakeup pipe!";
+  }
+}
+
+void MessagePumpEfl::ScheduleDelayedWork(const TimeTicks& delayed_work_time) {
+  delayed_work_time_ = delayed_work_time;
+  ScheduleWork();
+}
+
+void MessagePumpEfl::HandleScheduledWork() {
+  {
+    base::AutoLock locker(schedule_work_lock_);
+    DCHECK(work_scheduled_);
+    work_scheduled_ = false;
+  }
+
+  if (state_->delegate->DoWork()) {
+    ScheduleWork();
+  }
+
+  if (state_->should_quit)
+    return;
+
+  state_->delegate->DoDelayedWork(&delayed_work_time_);
+}
+
+} // namespace base
diff --git a/tizen_src/impl/shell/message_pump_efl.h b/tizen_src/impl/shell/message_pump_efl.h
new file mode 100644 (file)
index 0000000..c4316cf
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 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 BASE_MESSAGE_LOOP_MESSAGE_PUMP_EFL_H_
+#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_EFL_H_
+
+#include "base/base_export.h"
+#include "base/basictypes.h"
+#include "base/message_loop/message_pump.h"
+#include "base/threading/non_thread_safe.h"
+
+#include <Ecore.h>
+
+namespace base {
+
+class TimeTicks;
+
+class BASE_EXPORT MessagePumpEfl : public MessagePump {
+ public:
+  MessagePumpEfl();
+  virtual ~MessagePumpEfl();
+
+  virtual void Run(Delegate* delegate) override;
+  virtual void Quit() override;
+  virtual void ScheduleWork() override;
+  virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override;
+
+  void HandleScheduledWork();
+
+private:
+  // We may make recursive calls to Run, so we save state that needs to be
+  // separate between them in this structure type.
+  struct RunState;
+  RunState* state_;
+
+  // This is the time when we need to do delayed work.
+  TimeTicks delayed_work_time_;
+
+  Ecore_Pipe* pipe_;
+  base::Lock schedule_work_lock_;
+  bool work_scheduled_;
+};
+
+}  // namespace base
+
+#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_EFL_H_
diff --git a/tizen_src/impl/shell/shell_efl.cc b/tizen_src/impl/shell/shell_efl.cc
new file mode 100644 (file)
index 0000000..983b40f
--- /dev/null
@@ -0,0 +1,281 @@
+// Copyright 2014 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 "content/shell/browser/shell.h"
+
+#include <Evas.h>
+#include <Ecore_Evas.h>
+#include <Elementary.h>
+
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/browser/render_view_host.h"
+#include "ui/gl/gl_switches.h"
+#include "cc/base/switches.h"
+
+namespace content {
+
+Evas_Object* Shell::native_view_ = NULL;
+Shell::Impl* Shell::impl_ = NULL;
+
+class Shell::Impl {
+ public:
+  Impl(gfx::Size size)
+      : url_bar_(NULL), web_view_(NULL)
+      , refresh_btn_(NULL), stop_btn_(NULL), back_btn_(NULL)
+      , forward_btn_(NULL), exit_handler_(NULL), shell_(NULL) {
+    Evas_Object *icon = NULL;
+
+    elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED);
+    elm_config_preferred_engine_set("opengl_x11");
+    window_ = elm_win_util_standard_add(
+        "content_shell_efl", "Content Shell EFL");
+    elm_win_autodel_set(window_, EINA_TRUE);
+    evas_object_resize(window_, size.width(), size.height());
+
+    Evas_Object *box = elm_box_add(window_);
+    evas_object_size_hint_align_set(box, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_size_hint_weight_set(box, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    //elm_box_padding_set(box, 20, 20);
+    elm_win_resize_object_add(window_, box);
+    evas_object_show(box);
+
+    url_bar_ = elm_entry_add(box);
+    elm_entry_single_line_set(url_bar_, EINA_TRUE);
+    elm_entry_scrollable_set(url_bar_, EINA_TRUE);
+    elm_entry_input_panel_layout_set(url_bar_, ELM_INPUT_PANEL_LAYOUT_URL);
+    evas_object_size_hint_weight_set(url_bar_, EVAS_HINT_EXPAND, 0.0f);
+    evas_object_size_hint_align_set(url_bar_, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_smart_callback_add(url_bar_, "activated", OnURLEntered, this);
+    elm_box_pack_end(box, url_bar_);
+    evas_object_show(url_bar_);
+
+    Evas_Object *button_box = elm_box_add(box);
+    elm_box_horizontal_set(button_box, EINA_TRUE);
+
+    back_btn_ = elm_button_add(button_box);
+    icon = elm_icon_add(button_box);
+    elm_icon_standard_set(icon, "arrow_left");
+    elm_object_part_content_set(back_btn_, "icon", icon);
+    evas_object_smart_callback_add(back_btn_, "clicked", OnBack, this);
+    elm_box_pack_end(button_box, back_btn_);
+    evas_object_show(back_btn_);
+
+    forward_btn_ = elm_button_add(button_box);
+    icon = elm_icon_add(button_box);
+    elm_icon_standard_set(icon, "arrow_right");
+    elm_object_part_content_set(forward_btn_, "icon", icon);
+    evas_object_smart_callback_add(forward_btn_, "clicked", OnForward, this);
+    elm_box_pack_end(button_box, forward_btn_);
+    evas_object_show(forward_btn_);
+
+    refresh_btn_ = elm_button_add(button_box);
+    icon = elm_icon_add(button_box);
+    elm_icon_standard_set(icon, "refresh");
+    elm_object_part_content_set(refresh_btn_, "icon", icon);
+    evas_object_smart_callback_add(refresh_btn_, "clicked", OnRefresh, this);
+    elm_box_pack_end(button_box, refresh_btn_);
+    evas_object_show(refresh_btn_);
+
+    stop_btn_ = elm_button_add(button_box);
+    icon = elm_icon_add(button_box);
+    elm_icon_standard_set(icon, "close");
+    elm_object_part_content_set(stop_btn_, "icon", icon);
+    evas_object_smart_callback_add(stop_btn_, "clicked", OnStop, this);
+    elm_box_pack_end(button_box, stop_btn_);
+    evas_object_show(stop_btn_);
+
+#if !defined(OS_TIZEN)
+    elm_object_text_set(back_btn_, "Back");
+    elm_object_text_set(forward_btn_, "Forward");
+    elm_object_text_set(refresh_btn_, "Refresh");
+    elm_object_text_set(stop_btn_, "Stop");
+#endif
+
+    evas_object_show(button_box);
+    elm_object_part_content_set(url_bar_, "icon", button_box);
+
+    Evas* evas = evas_object_evas_get(window_);
+    web_view_ = evas_object_image_filled_add(evas);
+    evas_object_image_size_set(web_view_, size.width(), size.height());
+    evas_object_size_hint_align_set(web_view_, EVAS_HINT_FILL, EVAS_HINT_FILL);
+    evas_object_size_hint_weight_set(web_view_, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+    elm_box_pack_end(box, web_view_);
+    evas_object_show(web_view_);
+
+    evas_object_event_callback_add(web_view_, EVAS_CALLBACK_RESIZE, OnResize, this);
+    exit_handler_ = ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT, &OnExit, this);
+    evas_object_smart_callback_add(window_, "delete,request", OnWindowDelRequest, this);
+  }
+
+  void SetAddressBarURL(const char* url) {
+    // XXX: Check unnecessart when HW rendering works on desktop
+    if (url_bar_) {
+      elm_object_text_set(url_bar_, url);
+    }
+  }
+
+  Evas_Object* GetWebView() const {
+    return web_view_;
+  }
+
+  void SetShell(Shell* shell) {
+    shell_ = shell;
+  }
+
+  void ShowWindow(int width, int height) {
+    evas_object_resize(window_, width, height);
+    evas_object_show(window_);
+  }
+
+  void SetWindowTitle(const base::string16& title) {
+    elm_win_title_set(window_, UTF16ToUTF8(title).c_str());
+  }
+
+  void ToggleControl(UIControl control, bool is_enabled) {
+    // XXX: After HW rendering is fixed on desktop elm buttons
+    //      should always exist when entering this function
+    if (control == BACK_BUTTON && back_btn_) {
+      elm_object_disabled_set(back_btn_, !is_enabled);
+    } else if (control == FORWARD_BUTTON && forward_btn_) {
+      elm_object_disabled_set(forward_btn_, !is_enabled);
+    } else if (control == STOP_BUTTON && stop_btn_) {
+      elm_object_disabled_set(stop_btn_, !is_enabled);
+    }
+  }
+
+ private:
+  void Close() {
+    elm_exit();
+    shell_->Close();
+  }
+
+  static void OnResize(void* data, Evas*, Evas_Object*, void*) {
+    Shell::Impl* thiz = static_cast<Shell::Impl*>(data);
+
+    int width, height;
+    evas_object_geometry_get(thiz->web_view_, 0, 0, &width, &height);
+    evas_object_image_size_set(native_view_, width, height);
+
+    if (thiz->shell_ && thiz->shell_->web_contents()) {
+      thiz->shell_->web_contents()->GetRenderViewHost()->WasResized();
+    }
+  }
+
+  static Eina_Bool OnExit(void* data, int, void*) {
+    static_cast<Shell::Impl*>(data)->Close();
+    return 1;
+  }
+
+  static void OnWindowDelRequest(void* data, Evas_Object*, void*) {
+    Shell::Impl* thiz = static_cast<Shell::Impl*>(data);
+    thiz->window_ = NULL;
+    thiz->Close();
+  }
+
+  static void OnBack(void* data, Evas_Object*, void*) {
+    static_cast<Shell::Impl*>(data)->shell_->GoBackOrForward(-1);
+  }
+
+  static void OnForward(void* data, Evas_Object*, void*) {
+    static_cast<Shell::Impl*>(data)->shell_->GoBackOrForward(1);
+  }
+
+  static void OnRefresh(void* data, Evas_Object*, void*) {
+    static_cast<Shell::Impl*>(data)->shell_->Reload();
+  }
+
+  static void OnStop(void* data, Evas_Object*, void*) {
+    static_cast<Shell::Impl*>(data)->shell_->Stop();
+  }
+
+  static void OnURLEntered(void *data, Evas_Object *obj, void*) {
+    GURL url(elm_object_text_get(obj));
+    if (!url.has_scheme()) {
+      url = GURL(std::string("http://") + std::string(elm_object_text_get(obj)));
+      elm_object_text_set(obj, url.spec().c_str());
+    }
+    static_cast<Shell::Impl*>(data)->shell_->LoadURL(url);
+  }
+
+  Evas_Object* window_;
+  Evas_Object* url_bar_;
+  Evas_Object* web_view_;
+  Evas_Object* refresh_btn_;
+  Evas_Object* stop_btn_;
+  Evas_Object* back_btn_;
+  Evas_Object* forward_btn_;
+  Ecore_Event_Handler* exit_handler_;
+
+  Shell* shell_;
+};
+
+// static
+void Shell::PlatformInitialize(const gfx::Size& default_window_size) {
+  elm_init(0, NULL);
+
+  impl_ = new Impl(default_window_size);
+  native_view_ = impl_->GetWebView();
+
+  // This is not the best place to append port specific flags, but
+  // it works and keeps changes to upsteam sources minimal.
+  //
+  // XXX: Investigate why EFL port does not work without threaded
+  //      compositing.
+  CommandLine::ForCurrentProcess()->
+      AppendSwitch(switches::kDisableDelegatedRenderer);
+  CommandLine::ForCurrentProcess()->
+      AppendSwitch(cc::switches::kCompositeToMailbox);
+
+  LOG(INFO) << "EFL Shell platform initialized";
+}
+
+void Shell::PlatformExit() {
+  native_view_ = NULL;
+  LOG(INFO) << "EFL Shell platform exit";
+}
+
+void Shell::PlatformCleanUp() {
+  delete impl_;
+}
+
+void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
+  impl_->ToggleControl(control, is_enabled);
+}
+
+void Shell::PlatformSetAddressBarURL(const GURL& url) {
+  impl_->SetAddressBarURL(url.spec().c_str());
+}
+
+void Shell::PlatformSetIsLoading(bool loading) {
+}
+
+void Shell::PlatformCreateWindow(int width, int height) {
+  impl_->ShowWindow(width, height);
+}
+
+void Shell::PlatformSetContents() {
+  impl_->SetShell(this);
+}
+
+void Shell::PlatformResizeSubViews() {
+}
+
+void Shell::Close() {
+  LOG(INFO) << "Closing Content Shell EFL";
+  delete this;
+}
+
+void Shell::PlatformSetTitle(const base::string16& title) {
+  impl_->SetWindowTitle(title);
+}
+
+bool Shell::PlatformHandleContextMenu(
+    const content::ContextMenuParams& params) {
+  return false;
+}
+
+}  // namespace content
diff --git a/tizen_src/impl/shell/shell_main.cc b/tizen_src/impl/shell/shell_main.cc
new file mode 100644 (file)
index 0000000..ade79fc
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/app/content_main.h"
+
+#include <Ecore_Evas.h>
+#include <Ecore_X.h>
+
+#include "content/shell/app/shell_main_delegate.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "base/message_loop/message_loop.h"
+#include "gpu/gpu_thread_override_efl.h"
+#include "shell/message_pump_efl.h"
+#include "screen_efl.h"
+
+scoped_ptr<base::MessagePump> MessagePumpFactory() {
+  return scoped_ptr<base::MessagePump>(new base::MessagePumpEfl);
+}
+
+int main(int argc, const char* argv[]) {
+  ecore_init();
+  ecore_x_init(NULL);
+  eina_init();
+  evas_init();
+  if (!base::MessageLoop::InitMessagePumpForUIFactory(&MessagePumpFactory)) {
+    LOG(ERROR) << "Failed to install EFL message pump!";
+    return 1;
+  }
+
+  ui::InstallScreenInstance();
+  content::GpuProcessHost::RegisterGpuMainThreadFactory(CreateInProcessGpuThreadEfl);
+
+  content::ShellMainDelegate delegate;
+
+  content::ContentMainParams prams(&delegate);
+  prams.argc = argc;
+  prams.argv = argv;
+  return content::ContentMain(prams);
+}
diff --git a/tizen_src/impl/shell/shell_web_contents_view_delegate_efl.cc b/tizen_src/impl/shell/shell_web_contents_view_delegate_efl.cc
new file mode 100644 (file)
index 0000000..601e746
--- /dev/null
@@ -0,0 +1,14 @@
+// Copyright 2014 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 "content/shell/browser/shell_web_contents_view_delegate.h"
+
+namespace content {
+
+WebContentsViewDelegate* CreateShellWebContentsViewDelegate(
+    WebContents* web_contents) {
+  return NULL;
+}
+
+}  // namespace content
index 4389c20..e9d9a3a 100755 (executable)
@@ -18,6 +18,7 @@ Group: Applications/Internet
 License: LGPLv2.1 or BSD
 
 Source0: %{name}-%{version}.tar.gz
+Source1: content_shell.in
 
 Requires(post): /sbin/ldconfig
 Requires(post): xkeyboard-config
@@ -109,6 +110,15 @@ Requires: %{name} = %{version}-%{release}
 %description devel
 Browser Engine dev library based on Chromium EFL (developement files)
 
+%if 0%{?_enable_content_shell}
+%package shell
+Summary: Chromium EFL port of content_shell application
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+%description shell
+Chromium EFL version of content_shell application
+%endif
+
 %if 0%{?_enable_unittests}
 %package unittests
 Summary: Chromium unittests
@@ -207,6 +217,9 @@ fi
 %endif
 
 build/prebuild/ninja %{_smp_mflags} -C"%{OUTPUT_FOLDER}" \
+%if 0%{?_enable_content_shell}
+  content_shell_efl \
+%endif
 %if 0%{?build_ewk_unittests}
   ewk_unittests \
 %endif
@@ -229,6 +242,7 @@ cp src/third_party/icu/android/icudtl.dat "%{OUTPUT_FOLDER}"
 %install
 install -d "%{buildroot}"%{_sysconfdir}/smack/accesses2.d
 install -d "%{buildroot}"%{_bindir}
+install -d "%{buildroot}"%{_bindir}
 install -d "%{buildroot}"%{_libdir}/pkgconfig
 install -d "%{buildroot}"%{_includedir}/chromium-ewk
 install -d "%{buildroot}"%{_includedir}/v8
@@ -259,6 +273,11 @@ install -m 0644 "%{OUTPUT_FOLDER}"/pkgconfig/*.pc    "%{buildroot}"%{_libdir}/pk
 install -m 0644 ewk/efl_integration/public/*.h                  "%{buildroot}"%{_includedir}/chromium-ewk/
 install -m 0644 src/v8/include/*.h "%{buildroot}"%{_includedir}/v8/
 
+%if 0%{?_enable_content_shell}
+install -m 0755 "%{OUTPUT_FOLDER}"/content_shell_efl "%{buildroot}%{CHROMIUM_EXE_DIR}"/content_shell
+sed 's#@binary@#%{CHROMIUM_EXE_DIR}/content_shell#' %{SOURCE1} > "%{buildroot}"%{_bindir}/content_shell
+%endif
+
 install -d "%{buildroot}"/opt/share/packages
 install -m 0644 ewk/efl_webview_app/chromium-efl.xml "%{buildroot}"/opt/share/packages
 
@@ -338,6 +357,13 @@ fi
 %{_libdir}/pkgconfig/*.pc
 %{_includedir}/v8/*
 
+%if 0%{?_enable_content_shell}
+%files shell
+%defattr(0755,root,root,-)
+%{CHROMIUM_EXE_DIR}/content_shell
+%{_bindir}/content_shell
+%endif
+
 %if 0%{?_enable_unittests}
 %files unittests
 %defattr(-,root,root,-)
diff --git a/tizen_src/packaging/content_shell.in b/tizen_src/packaging/content_shell.in
new file mode 100644 (file)
index 0000000..dbb3608
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+exec @binary@ \
+    --use-gl=egl \
+    --no-sandbox \
+    "$@"
diff --git a/tizen_src/scripts/run-layout-tests b/tizen_src/scripts/run-layout-tests
new file mode 100755 (executable)
index 0000000..ff2783d
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+_script=$(readlink -f $0)
+_top_dir=$(dirname $_script)/..
+_runner=$_top_dir/src/third_party/WebKit/Tools/Scripts/run-webkit-tests
+_out="out.x64"
+
+echo $@ | grep -q \\-\\-help && $_runner --help
+
+echo $@ | grep -q \\-\\-debug
+[ $? -gt 0 ] && _mode="Release" || _mode="Debug"
+
+if [ ! -x $_top_dir/$_out/$_mode/content_shell_efl ]; then
+    echo "Please build content_shell_efl in $_mode mode first"
+    exit 1
+fi
+
+# The test runner expects driver binary to be called content_shell.
+ln -f $_top_dir/$_out/$_mode/content_shell_efl \
+      $_top_dir/$_out/$_mode/content_shell
+
+exec $_runner \
+    --build-directory=$_top_dir/out.x64 \
+    --additional-drt-flag=--no-sandbox \
+    --additional-drt-flag=--ignore-gpu-blacklist \
+    --additional-drt-flag=--use-gl=egl \
+    "$@"