### 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)
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
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() {
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
}
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));
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)
}
void RenderWidgetHostViewEfl::OnSelectionTextStyleState(const SelectionStylePrams& params) {
- web_view_->OnQuerySelectionStyleReply(params);
+ if (web_view_)
+ web_view_->OnQuerySelectionStyleReply(params);
}
#if 0
}
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) {
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
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();
+ }
}
}
}
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(
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())
#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) {
#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
}
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) {
// 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();
}
}
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) {
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_) {
} 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
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)
}
SelectionControllerEfl* RenderWidgetHostViewEfl::GetSelectionController() {
- return web_view_->GetSelectionController();
+ if (web_view_)
+ return web_view_->GetSelectionController();
+
+ return NULL;
}
void RenderWidgetHostViewEfl::SetComposition(const ui::CompositionText& composition_text) {
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_; }
#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"
WebContentsViewEfl::WebContentsViewEfl(WebContents* contents,
WebContentsViewDelegate* delegate)
: delegate_(delegate)
+ , native_view_(NULL)
, drag_dest_delegate_(NULL)
, web_contents_(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();
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;
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) {
}
#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
#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;
#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.
'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',
+ ],
+ }],
+ ],
+ },
],
}
EWebContext::EWebContext(bool incognito)
: m_pixmap(0),
- initialized_(false),
incognito_(incognito) {
EwkGlobalData::Ensure();
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();
}
void ClearCandidateData();
void ClearPasswordData();
- void InitializeGLSharedContext(Evas_Object* object);
#if defined(OS_TIZEN_TV)
FaviconDatabase* GetFaviconDatabase();
#endif
std::string proxy_uri_;
scoped_ptr<EwkDidStartDownloadCallback> start_download_callback_;
int m_pixmap;
- bool initialized_;
bool incognito_;
};
renderer_crashed_(false),
#endif
is_initialized_(false) {
- context->GetImpl()->InitializeGLSharedContext(object);
}
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));
#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"
if (GLSharedContextEflPrivate::instance().get())
return;
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
GLSharedContextEflPrivate::instance() =
new GLSharedContextEflPrivate(object);
}
--- /dev/null
+// 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
--- /dev/null
+// 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_
--- /dev/null
+// 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
--- /dev/null
+// 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);
+}
--- /dev/null
+// 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
License: LGPLv2.1 or BSD
Source0: %{name}-%{version}.tar.gz
+Source1: content_shell.in
Requires(post): /sbin/ldconfig
Requires(post): xkeyboard-config
%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
%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
%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
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
%{_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,-)
--- /dev/null
+#!/bin/sh
+exec @binary@ \
+ --use-gl=egl \
+ --no-sandbox \
+ "$@"
--- /dev/null
+#!/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 \
+ "$@"