%bcond_with wayland
Name: crosswalk
-Version: 6.35.132.0
+Version: 7.35.136.0
Release: 0
Summary: Crosswalk is an app runtime based on Chromium
License: (BSD-3-Clause and LGPL-2.1+)
'enable_xdg_shell%': '<(enable_xdg_shell)',
'conditions': [
['sysroot!=""', {
- 'pkg-config': './pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
+ 'pkg-config': '../../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
}, {
'pkg-config': 'pkg-config'
}],
chromium_crosswalk_point = 'e62582858402995e841741a28af1c418d815897f'
blink_crosswalk_point = '2c4e1889f37db55c77215de4f113748f071cb7aa'
v8_crosswalk_point = 'd27abf42d305c5ee30cabed4926783bb105953c0'
-ozone_wayland_point = 'f4faec532d7d2f482b3ffe1e52be6fa3e6fc8629'
+ozone_wayland_point = '55f39c62b461b92d3b0b912c7c80ae98d866b5a6'
deps_xwalk = {
'src': 'https://github.com/crosswalk-project/chromium-crosswalk.git@%s' % chromium_crosswalk_point,
-MAJOR=6
+MAJOR=7
MINOR=35
-BUILD=132
+BUILD=136
PATCH=0
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xwalk.app.hello.world">
- <application android:name="android.app.Application"
+ <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
android:label="XWalkAppHelloWorld" android:hardwareAccelerated="true"
android:icon="@drawable/crosswalk">
<activity android:name="org.xwalk.app.hello.world.HelloWorldActivity"
package="org.xwalk.app.template"
android:installLocation="auto">
- <application android:name="android.app.Application"
+ <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
android:label="XWalkAppTemplate" android:hardwareAccelerated="true"
android:icon="@drawable/crosswalk">
<activity android:name="org.xwalk.app.template.AppTemplateActivity"
+++ /dev/null
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.xwalk.app;
-
-import android.content.res.Resources;
-import android.graphics.drawable.Drawable;
-
-/**
- * XWalkMixedResources is used to combine the resources
- * from two different packages.
- *
- * TODO(wang16): Add more override functions (e.g. getColor/Boolean).
- */
-public class XWalkMixedResources extends Resources {
-
- private Resources mExtend;
-
- XWalkMixedResources(Resources base, Resources extend) {
- super(base.getAssets(), base.getDisplayMetrics(),
- base.getConfiguration());
- mExtend = extend;
- }
-
- @Override
- public CharSequence getText(int id) throws NotFoundException {
- try {
- return mExtend.getText(id);
- } catch (NotFoundException e) {
- return super.getText(id);
- }
- }
-
- @Override
- public Drawable getDrawable(int id) throws NotFoundException {
- try {
- return mExtend.getDrawable(id);
- } catch (NotFoundException e) {
- return super.getDrawable(id);
- }
- }
-}
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
private AlertDialog mLibraryNotFoundDialog = null;
- private XWalkMixedResources mMixedResources = null;
-
@Override
public void onCreate(Bundle savedInstanceState) {
IntentFilter intentFilter = new IntentFilter("org.xwalk.intent");
mRuntimeView.onActivityResult(requestCode, resultCode, data);
}
- @Override
- public Resources getResources() {
- if (mMixedResources == null) return super.getResources();
- return mMixedResources;
- }
-
private String getLibraryApkDownloadUrl() {
int resId = getResources().getIdentifier("xwalk_library_apk_download_url", "string", getPackageName());
if (resId == 0) return DEFAULT_LIBRARY_APK_URL;
if (mRuntimeView == null || mRuntimeView.get() == null) {
mRuntimeView = new XWalkRuntimeClient(this, null, this);
if (mRuntimeView.get() != null) {
- mMixedResources = new XWalkMixedResources(super.getResources(),
- mRuntimeView.getLibraryContext().getResources());
mShownNotFoundDialog = false;
if (mLibraryNotFoundDialog != null) mLibraryNotFoundDialog.cancel();
}
mLibCtx = ctx.createPackageContext(
LIBRARY_APK_PACKAGE_NAME,
Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ Context app = ctx.getApplicationContext();
+ assert(app instanceof XWalkRuntimeApplication);
+ XWalkRuntimeApplication xwalkApp = (XWalkRuntimeApplication) app;
+ xwalkApp.addResource(mLibCtx.getResources());
+
mTargetClass =
mLibCtx.getClassLoader().loadClass(className);
}
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.app.runtime;
+
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.TypedValue;
+
+/**
+ * XWalkMixedResources is used to combine the resources
+ * from two different packages.
+ *
+ * Chromium uses resources through:
+ * R.layout; R.id; R.string; R.dimen; R.drawable;
+ * R.attr; R.style; R.menu ; R.color
+ * R.layout and R.menu is covered by Resources.getLayout()
+ * R.string is covered by Resources.getText()
+ * R.dimen, R.drawable and R.color is covered by getValue()
+ *
+ * For R.id, if it's used like findViewById(R.id.xxx), R.id.xxx
+ * is const at compile time within library context. It works
+ * if the view in hierachy has the same id, which needs inflate
+ * with layout resource from library context. Layout is covered
+ * by getLayout(), so R.id is OK.
+ *
+ * TODO(wang16):
+ * For R.attr and R.style, I have no confidence that it's covered.
+ * But the only place use this R.attr and R.style is "select" tag
+ * which is verified working well with this MixedResources.
+ */
+public class XWalkMixedResources extends Resources {
+
+ private Resources mExtend;
+
+ XWalkMixedResources(Resources base, Resources extend) {
+ super(base.getAssets(), base.getDisplayMetrics(),
+ base.getConfiguration());
+ mExtend = extend;
+ }
+
+ @Override
+ public CharSequence getText(int id) throws NotFoundException {
+ try {
+ return mExtend.getText(id);
+ } catch (NotFoundException e) {
+ return super.getText(id);
+ }
+ }
+
+ @Override
+ public XmlResourceParser getLayout(int id) throws NotFoundException {
+ try {
+ return mExtend.getLayout(id);
+ } catch (NotFoundException e) {
+ return super.getLayout(id);
+ }
+ }
+
+ @Override
+ public void getValue(int id, TypedValue outValue, boolean resolveRefs) {
+ try {
+ mExtend.getValue(id, outValue, resolveRefs);
+ } catch (NotFoundException e) {
+ super.getValue(id, outValue, resolveRefs);
+ }
+ }
+
+ @Override
+ public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs) {
+ try {
+ mExtend.getValueForDensity(id, density, outValue, resolveRefs);
+ } catch (NotFoundException e) {
+ super.getValueForDensity(id, density, outValue, resolveRefs);
+ }
+ }
+
+ @Override
+ public int getIdentifier(String name, String defType, String defPackage) {
+ int id = mExtend.getIdentifier(name, defType, defPackage);
+ return id != 0 ? id : super.getIdentifier(name, defType, defPackage);
+ }
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.app.runtime;
+
+import android.app.Application;
+import android.content.res.Resources;
+
+/**
+ * XWalkRuntimeApplication is to support cross package resource loading.
+ * It provides method to allow overriding getResources() behavior.
+ */
+public class XWalkRuntimeApplication extends Application {
+ private Resources mRes = null;
+
+ @Override
+ public Resources getResources() {
+ return mRes == null ? super.getResources() : mRes;
+ }
+
+ void addResource(Resources res) {
+ if (mRes != null) return;
+ mRes = new XWalkMixedResources(super.getResources(), res);
+ }
+}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.xwalk.runtime.client.shell">
- <application android:name="android.app.Application"
+ <application android:name="org.xwalk.app.runtime.XWalkRuntimeApplication"
android:label="XWalkRuntimeClientShell" android:hardwareAccelerated="true">
<activity android:name="org.xwalk.runtime.client.shell.XWalkRuntimeClientShellActivity"
android:theme="@android:style/Theme.Holo.Light.NoActionBar"
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import fnmatch
import os
-import stat
import subprocess
def GetJARFilename():
cur_dir = os.path.realpath(os.path.dirname(__file__))
return os.path.join(cur_dir, "libs", file_name)
-def GetFileList(path, ext, sub_dir = True):
- if os.path.exists(path):
- file_list = []
- for name in os.listdir(path):
- full_name = os.path.join(path, name)
- st = os.lstat(full_name)
- if stat.S_ISDIR(st.st_mode) and sub_dir:
- file_list += GetFileList(full_name, ext)
- elif os.path.isfile(full_name):
- if fnmatch.fnmatch(full_name, ext):
- file_list.append(full_name)
- return file_list
- else:
- return []
-
-def ExecuteCmd(path, ext):
- file_list = GetFileList(path, "*." + ext)
+
+def ExecuteCmd(file_list, ext):
for file_full_path in file_list:
if os.path.exists(file_full_path):
cmd_args = ["java", "-jar", GetJARFilename(), "--type=" + ext,
file_full_path, "-o", file_full_path]
subprocess.call(cmd_args)
-class CompressJsAndCss(object):
- def __init__(self, input_path):
- self.input_path = input_path
- def CompressJavaScript(self):
- ExecuteCmd(self.input_path, "js")
+def CompressJavaScript(file_list):
+ ExecuteCmd(file_list, "js")
+
- def CompressCss(self):
- ExecuteCmd(self.input_path, "css")
+def CompressCss(file_list):
+ ExecuteCmd(file_list, "css")
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import compress_js_and_css
+import fnmatch
import json
import optparse
import os
import re
import shutil
+import stat
import sys
from customize_launch_screen import CustomizeLaunchScreen
from handle_permissions import HandlePermissions
from xml.dom import minidom
+def VerifyAppName(value, mode='default'):
+ descrpt = 'The app'
+ sample = 'helloworld, hello_world, hello_world1'
+ regex = r'^([a-zA-Z](\w)*)+$'
+
+ if len(value) >= 128 :
+ print('To be safe, the length of package name or app name '
+ 'should be less than 128.')
+ sys.exit(6)
+ if mode == 'packagename':
+ regex = r'^[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+$'
+ descrpt = 'Each part of package'
+ sample = 'org.xwalk.example, org.xwalk.example_'
+
+ if not re.match(regex, value):
+ print('Error: %s name should be started with letters and should not '
+ 'conatin invalid characters.\n'
+ 'It may conatin letters, numbers and underscores\n'
+ 'Sample: %s' % (descrpt, sample))
+ sys.exit(6)
+
+
def ReplaceInvalidChars(value, mode='default'):
""" Replace the invalid chars with '_' for input string.
Args:
return value
-def Prepare(sanitized_name, package, app_root):
- if os.path.exists(sanitized_name):
- shutil.rmtree(sanitized_name)
- shutil.copytree('app_src', sanitized_name)
- shutil.rmtree(os.path.join(sanitized_name, 'src'))
+def GetFilesByExt(path, ext, sub_dir = True):
+ if os.path.exists(path):
+ file_list = []
+ for name in os.listdir(path):
+ full_name = os.path.join(path, name)
+ st = os.lstat(full_name)
+ if stat.S_ISDIR(st.st_mode) and sub_dir:
+ file_list += GetFilesByExt(full_name, ext)
+ elif os.path.isfile(full_name):
+ if fnmatch.fnmatch(full_name, ext):
+ file_list.append(full_name)
+ return file_list
+ else:
+ return []
+
+
+def ParseParameterForCompressor(option, value, values, parser):
+ if ((not values or values.startswith('-'))
+ and value.find('--compressor') != -1):
+ values = 'all'
+ val = values
+ if parser.rargs and not parser.rargs[0].startswith('-'):
+ val = parser.rargs[0]
+ parser.rargs.pop(0)
+ setattr(parser.values, option.dest, val)
+
+
+def CompressSourceFiles(app_root, compressor):
+ js_list = []
+ css_list = []
+ js_ext = '*.js'
+ css_ext = '*.css'
+
+ if compressor == 'all' or compressor == 'js':
+ js_list = GetFilesByExt(app_root, js_ext)
+ compress_js_and_css.CompressJavaScript(js_list)
+
+ if compressor == 'all' or compressor == 'css':
+ css_list = GetFilesByExt(app_root, css_ext)
+ compress_js_and_css.CompressCss(css_list)
+
+
+def Prepare(name, package, app_root, compressor):
+ if os.path.exists(name):
+ shutil.rmtree(name)
+ shutil.copytree('app_src', name)
+ shutil.rmtree(os.path.join(name, 'src'))
src_root = os.path.join('app_src', 'src', 'org', 'xwalk', 'app', 'template')
src_activity = os.path.join(src_root, 'AppTemplateActivity.java')
if not os.path.isfile(src_activity):
print ('Please make sure that the java file'
' of activity does exist.')
sys.exit(7)
- root_path = os.path.join(sanitized_name, 'src',
- package.replace('.', os.path.sep))
+ root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
if not os.path.exists(root_path):
os.makedirs(root_path)
- dest_activity = sanitized_name + 'Activity.java'
+ dest_activity = name + 'Activity.java'
shutil.copyfile(src_activity, os.path.join(root_path, dest_activity))
if app_root:
- assets_path = os.path.join(sanitized_name, 'assets')
+ assets_path = os.path.join(name, 'assets')
shutil.rmtree(assets_path)
os.makedirs(assets_path)
app_src_path = os.path.join(assets_path, 'www')
shutil.copytree(app_root, app_src_path)
+ if compressor:
+ CompressSourceFiles(app_src_path, compressor)
-def CustomizeStringXML(sanitized_name, description):
- strings_path = os.path.join(sanitized_name, 'res', 'values', 'strings.xml')
+def CustomizeStringXML(name, description):
+ strings_path = os.path.join(name, 'res', 'values', 'strings.xml')
if not os.path.isfile(strings_path):
print ('Please make sure strings_xml'
' exists under app_src folder.')
strings_file.close()
-def CustomizeThemeXML(sanitized_name, fullscreen, app_manifest):
- theme_path = os.path.join(sanitized_name, 'res', 'values', 'theme.xml')
+def CustomizeThemeXML(name, fullscreen, app_manifest):
+ theme_path = os.path.join(name, 'res', 'values', 'theme.xml')
if not os.path.isfile(theme_path):
print('Error: theme.xml is missing in the build tool.')
sys.exit(6)
if fullscreen:
EditElementValueByNodeName(theme_xmldoc, 'item',
'android:windowFullscreen', 'true')
- has_background = CustomizeLaunchScreen(app_manifest, sanitized_name)
+ has_background = CustomizeLaunchScreen(app_manifest, name)
if has_background:
EditElementValueByNodeName(theme_xmldoc, 'item',
'android:windowBackground',
theme_file.close()
-def CustomizeXML(sanitized_name, package, app_versionCode, app_version,
- description, name, orientation, icon_dict, fullscreen,
- icon, app_manifest, permissions, app_root):
- manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
+def CustomizeXML(package, app_versionCode, app_version, description, name,
+ orientation, icon_dict, fullscreen, icon, app_manifest,
+ permissions, app_root):
+ manifest_path = os.path.join(name, 'AndroidManifest.xml')
if not os.path.isfile(manifest_path):
print ('Please make sure AndroidManifest.xml'
' exists under app_src folder.')
sys.exit(6)
- CustomizeStringXML(sanitized_name, description)
- CustomizeThemeXML(sanitized_name, fullscreen, app_manifest)
+ CustomizeStringXML(name, description)
+ CustomizeThemeXML(name, fullscreen, app_manifest)
xmldoc = minidom.parse(manifest_path)
EditElementAttribute(xmldoc, 'manifest', 'package', package)
if app_versionCode:
"@string/description")
HandlePermissions(permissions, xmldoc)
EditElementAttribute(xmldoc, 'application', 'android:label', name)
- activity_name = package + '.' + sanitized_name + 'Activity'
+ activity_name = package + '.' + name + 'Activity'
EditElementAttribute(xmldoc, 'activity', 'android:name', activity_name)
EditElementAttribute(xmldoc, 'activity', 'android:label', name)
if orientation:
EditElementAttribute(xmldoc, 'activity', 'android:screenOrientation',
orientation)
- icon_name = CustomizeIcon(sanitized_name, app_root, icon, icon_dict)
+ icon_name = CustomizeIcon(name, app_root, icon, icon_dict)
if icon_name:
EditElementAttribute(xmldoc, 'application', 'android:icon',
'@drawable/%s' % icon_name)
- file_handle = open(os.path.join(sanitized_name, 'AndroidManifest.xml'), 'w')
+ file_handle = open(os.path.join(name, 'AndroidManifest.xml'), 'w')
xmldoc.writexml(file_handle, encoding='utf-8')
file_handle.close()
shutil.move(temp_file_path, file_path)
-def CustomizeJava(sanitized_name, package, app_url, app_local_path,
+def CustomizeJava(name, package, app_url, app_local_path,
enable_remote_debugging, display_as_fullscreen,
keep_screen_on):
- root_path = os.path.join(sanitized_name, 'src',
- package.replace('.', os.path.sep))
- dest_activity = os.path.join(root_path, sanitized_name + 'Activity.java')
+ root_path = os.path.join(name, 'src', package.replace('.', os.path.sep))
+ dest_activity = os.path.join(root_path, name + 'Activity.java')
ReplaceString(dest_activity, 'org.xwalk.app.template', package)
- ReplaceString(dest_activity, 'AppTemplate', sanitized_name)
- manifest_file = os.path.join(sanitized_name, 'assets/www', 'manifest.json')
+ ReplaceString(dest_activity, 'AppTemplate', name)
+ manifest_file = os.path.join(name, 'assets/www', 'manifest.json')
if os.path.isfile(manifest_file):
ReplaceString(
dest_activity,
ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
app_url)
elif app_local_path:
- if os.path.isfile(os.path.join(sanitized_name, 'assets/www',
- app_local_path)):
+ if os.path.isfile(os.path.join(name, 'assets/www', app_local_path)):
ReplaceString(dest_activity, 'file:///android_asset/www/index.html',
'app://' + package + '/' + app_local_path)
else:
shutil.copyfile(src_file, dest_file)
-def CustomizeExtensions(sanitized_name, name, extensions):
+def CustomizeExtensions(name, extensions):
"""Copy the files from external extensions and merge them into APK.
The directory of one external extension should be like:
json_output['jsapi'] = js_path_prefix + json_output['jsapi']
extension_json_list.append(json_output)
# Merge the permissions of extensions into AndroidManifest.xml.
- manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
+ manifest_path = os.path.join(name, 'AndroidManifest.xml')
xmldoc = minidom.parse(manifest_path)
if ('permissions' in json_output):
# Get used permission list to avoid repetition as "--permissions"
extension_json_file.close()
-def GenerateCommandLineFile(sanitized_name, xwalk_command_line):
+def GenerateCommandLineFile(name, xwalk_command_line):
if xwalk_command_line == '':
return
- assets_path = os.path.join(sanitized_name, 'assets')
+ assets_path = os.path.join(name, 'assets')
file_path = os.path.join(assets_path, 'xwalk-command-line')
command_line_file = open(file_path, 'w')
command_line_file.write('xwalk ' + xwalk_command_line)
-def CustomizeIconByDict(sanitized_name, app_root, icon_dict):
+def CustomizeIconByDict(name, app_root, icon_dict):
icon_name = None
drawable_dict = {'ldpi':[1, 37], 'mdpi':[37, 72], 'hdpi':[72, 96],
'xhdpi':[96, 120], 'xxhdpi':[120, 144], 'xxxhdpi':[144, 168]}
for kd, vd in drawable_dict.iteritems():
for item in icon_list:
if item[0] >= vd[0] and item[0] < vd[1]:
- drawable_path = os.path.join(sanitized_name, 'res', 'drawable-' + kd)
+ drawable_path = os.path.join(name, 'res', 'drawable-' + kd)
if not os.path.exists(drawable_path):
os.makedirs(drawable_path)
icon = os.path.join(app_root, item[1])
return icon_name
-def CustomizeIconByOption(sanitized_name, icon):
+def CustomizeIconByOption(name, icon):
if os.path.isfile(icon):
- drawable_path = os.path.join(sanitized_name, 'res', 'drawable')
+ drawable_path = os.path.join(name, 'res', 'drawable')
if not os.path.exists(drawable_path):
os.makedirs(drawable_path)
icon_file = os.path.basename(icon)
sys.exit(6)
-def CustomizeIcon(sanitized_name, app_root, icon, icon_dict):
+def CustomizeIcon(name, app_root, icon, icon_dict):
icon_name = None
if icon:
- icon_name = CustomizeIconByOption(sanitized_name, icon)
+ icon_name = CustomizeIconByOption(name, icon)
else:
- icon_name = CustomizeIconByDict(sanitized_name, app_root, icon_dict)
+ icon_name = CustomizeIconByDict(name, app_root, icon_dict)
return icon_name
display_as_fullscreen, keep_screen_on, extensions,
app_manifest, icon, package='org.xwalk.app.template',
name='AppTemplate', app_version='1.0.0',
- orientation='unspecified', xwalk_command_line=''):
- sanitized_name = ReplaceInvalidChars(name, 'apkname')
+ orientation='unspecified', xwalk_command_line='',
+ compressor=None):
try:
- Prepare(sanitized_name, package, app_root)
- CustomizeXML(sanitized_name, package, app_versionCode, app_version,
- description, name, orientation, icon_dict,
- display_as_fullscreen, icon, app_manifest, permissions,
- app_root)
- CustomizeJava(sanitized_name, package, app_url, app_local_path,
+ Prepare(name, package, app_root, compressor)
+ CustomizeXML(package, app_versionCode, app_version, description, name,
+ orientation, icon_dict, display_as_fullscreen, icon,
+ app_manifest, permissions, app_root)
+ CustomizeJava(name, package, app_url, app_local_path,
enable_remote_debugging, display_as_fullscreen,
keep_screen_on)
- CustomizeExtensions(sanitized_name, name, extensions)
- GenerateCommandLineFile(sanitized_name, xwalk_command_line)
+ CustomizeExtensions(name, extensions)
+ GenerateCommandLineFile(name, xwalk_command_line)
except SystemExit as ec:
print('Exiting with error code: %d' % ec.code)
sys.exit(ec.code)
'For example, '
'--xwalk-command-line=\'--chromium-command-1 --xwalk-command-2\'')
parser.add_option('--xwalk-command-line', default='', help=info)
-
+ info = ('Minify and obfuscate javascript and css.'
+ '--compressor: compress javascript and css.'
+ '--compressor=js: compress javascript.'
+ '--compressor=css: compress css.')
+ parser.add_option('--compressor', dest='compressor', action='callback',
+ callback=ParseParameterForCompressor,
+ type='string', nargs=0, help=info)
options, _ = parser.parse_args()
try:
icon_dict = {144: 'icons/icon_144.png',
options.fullscreen, options.keep_screen_on, options.extensions,
options.manifest, icon, options.package, options.name,
options.app_version, options.orientation,
- options.xwalk_command_line)
-
+ options.xwalk_command_line, options.compressor)
except SystemExit as ec:
print('Exiting with error code: %d' % ec.code)
return ec.code
# found in the LICENSE file.
# pylint: disable=F0401
-import compress_js_and_css
import operator
import optparse
import os
import sys
sys.path.append('scripts/gyp')
-from customize import ReplaceInvalidChars, CustomizeAll
+
+from customize import VerifyAppName, CustomizeAll, \
+ ParseParameterForCompressor
from dex import AddExeExtensions
from handle_permissions import permission_mapping_table
from manifest_json_parser import HandlePermissionList
def ParseManifest(options):
parser = ManifestJsonParser(os.path.expanduser(options.manifest))
- if not options.package:
- options.package = 'org.xwalk.' + parser.GetAppName().lower()
- if not options.name:
- options.name = parser.GetAppName()
+ app_name = parser.GetAppName()
+ if options.package:
+ VerifyAppName(options.package, 'packagename')
+ else:
+ VerifyAppName(app_name)
+ options.package = 'org.xwalk.' + app_name.lower()
+ if options.name:
+ VerifyAppName(options.name)
+ else:
+ VerifyAppName(app_name)
+ options.name = app_name
if not options.app_version:
options.app_version = parser.GetVersion()
if not options.app_versionCode and not options.app_versionCodeBase:
options.app_local_path, remote_debugging,
fullscreen_flag, options.keep_screen_on, options.extensions,
options.manifest, icon, package, name, app_version,
- orientation, options.xwalk_command_line)
+ orientation, options.xwalk_command_line, options.compressor)
-def Execution(options, sanitized_name):
+def Execution(options, name):
android_path_array = Which('android')
if not android_path_array:
print('Please install Android SDK first.')
if options.mode == 'embedded':
# Prepare the .pak file for embedded mode.
pak_src_path = os.path.join('native_libs_res', 'xwalk.pak')
- pak_des_path = os.path.join(sanitized_name, 'assets', 'xwalk.pak')
+ pak_des_path = os.path.join(name, 'assets', 'xwalk.pak')
shutil.copy(pak_src_path, pak_des_path)
# Prepare the icudtl.dat for embedded mode.
icudtl_src_path = os.path.join('native_libs_res', 'icudtl.dat')
- icudtl_des_path = os.path.join(sanitized_name, 'assets', 'icudtl.dat')
+ icudtl_des_path = os.path.join(name, 'assets', 'icudtl.dat')
shutil.copy(icudtl_src_path, icudtl_des_path)
js_src_dir = os.path.join('native_libs_res', 'jsapi')
- js_des_dir = os.path.join(sanitized_name, 'assets', 'jsapi')
+ js_des_dir = os.path.join(name, 'assets', 'jsapi')
if os.path.exists(js_des_dir):
shutil.rmtree(js_des_dir)
shutil.copytree(js_src_dir, js_des_dir)
+ os.path.join(res_xwalk_java, 'java_R', 'R.txt') + ' '
+ os.path.join(res_content_java, 'java_R', 'R.txt'))
- resource_dir = '-DRESOURCE_DIR=' + os.path.join(sanitized_name, 'res')
- manifest_path = os.path.join(sanitized_name, 'AndroidManifest.xml')
+ resource_dir = '-DRESOURCE_DIR=' + os.path.join(name, 'res')
+ manifest_path = os.path.join(name, 'AndroidManifest.xml')
cmd = ['python', os.path.join('scripts', 'gyp', 'ant.py'),
'-DAAPT_PATH=%s' % aapt_path,
res_dirs,
classpath += os.path.join(os.getcwd(), 'libs',
'xwalk_app_runtime_java.jar')
classpath += ' ' + sdk_jar_path
- src_dirs = '--src-dirs=' + os.path.join(os.getcwd(), sanitized_name, 'src') +\
+ src_dirs = '--src-dirs=' + os.path.join(os.getcwd(), name, 'src') +\
' ' + os.path.join(os.getcwd(), 'out', 'gen')
cmd = ['python', os.path.join('scripts', 'gyp', 'javac.py'),
'--output-dir=%s' % os.path.join('out', 'classes'),
'--javac-includes=',
'--chromium-code=0',
'--stamp=compile.stam']
- RunCommand(cmd)
+ RunCommand(cmd, options.verbose)
# Package resources.
- asset_dir = '-DASSET_DIR=%s' % os.path.join(sanitized_name, 'assets')
+ asset_dir = '-DASSET_DIR=%s' % os.path.join(name, 'assets')
xml_path = os.path.join('scripts', 'ant', 'apk-package-resources.xml')
cmd = ['python', os.path.join('scripts', 'gyp', 'ant.py'),
'-DAAPT_PATH=%s' % aapt_path,
'-DANDROID_SDK_JAR=%s' % sdk_jar_path,
'-DANDROID_SDK_ROOT=%s' % sdk_root_path,
'-DANT_TASKS_JAR=%s' % ant_tasks_jar_path,
- '-DAPK_NAME=%s' % sanitized_name,
+ '-DAPK_NAME=%s' % name,
'-DAPP_MANIFEST_VERSION_CODE=0',
'-DAPP_MANIFEST_VERSION_NAME=Developer Build',
asset_dir,
# Check whether external extensions are included.
extensions_string = 'xwalk-extensions'
- extensions_dir = os.path.join(os.getcwd(), sanitized_name, extensions_string)
+ extensions_dir = os.path.join(os.getcwd(), name, extensions_string)
external_extension_jars = FindExtensionJars(extensions_dir)
input_jars = []
if options.mode == 'embedded':
dex_command_list.extend(input_jars)
RunCommand(dex_command_list)
- src_dir = '-DSOURCE_DIR=' + os.path.join(sanitized_name, 'src')
+ src_dir = '-DSOURCE_DIR=' + os.path.join(name, 'src')
apk_path = '-DUNSIGNED_APK_PATH=' + os.path.join('out', 'app-unsigned.apk')
native_lib_path = '-DNATIVE_LIBS_DIR='
if options.mode == 'embedded':
cmd = ['python', 'scripts/gyp/ant.py',
'-DANDROID_SDK_ROOT=%s' % sdk_root_path,
'-DANT_TASKS_JAR=%s' % ant_tasks_jar_path,
- '-DAPK_NAME=%s' % sanitized_name,
+ '-DAPK_NAME=%s' % name,
'-DCONFIGURATION_NAME=Release',
native_lib_path,
'-DOUT_DIR=out',
apk_path = '--unsigned-apk-path=' + os.path.join('out', 'app-unsigned.apk')
final_apk_path = '--final-apk-path=' + \
- os.path.join('out', sanitized_name + '.apk')
+ os.path.join('out', name + '.apk')
cmd = ['python', 'scripts/gyp/finalize_apk.py',
'--android-sdk-root=%s' % sdk_root_path,
apk_path,
'--keystore-passcode=%s' % key_code]
RunCommand(cmd)
- src_file = os.path.join('out', sanitized_name + '.apk')
+ src_file = os.path.join('out', name + '.apk')
package_name = options.name
if options.app_version:
package_name += ('_' + options.app_version)
'Consider building for x86 as well.')
-def MakeApk(options, sanitized_name):
+def MakeApk(options):
Customize(options)
app_version = ''
+ name = options.name
if options.app_version:
app_version = options.app_version
if options.mode == 'shared':
- Execution(options, sanitized_name)
- PrintPackageInfo(options.target_dir, sanitized_name, app_version)
+ Execution(options, name)
+ PrintPackageInfo(options.target_dir, name, app_version)
elif options.mode == 'embedded':
if options.arch:
- Execution(options, sanitized_name)
- PrintPackageInfo(options.target_dir, sanitized_name,
- app_version, options.arch)
+ Execution(options, name)
+ PrintPackageInfo(options.target_dir, name, app_version, options.arch)
else:
# If the arch option is unspecified, all of available platform APKs
# will be generated.
options.arch = 'x86'
elif arch.find('arm') != -1:
options.arch = 'arm'
- Execution(options, sanitized_name)
+ Execution(options, name)
packaged_archs.append(options.arch)
else:
print('Warning: failed to create package for arch "%s" '
if len(packaged_archs) >=2:
multi_arch = True
for arch in packaged_archs:
- PrintPackageInfo(options.target_dir, sanitized_name,
- app_version, arch, multi_arch)
+ PrintPackageInfo(options.target_dir, name, app_version, arch,
+ multi_arch)
else:
print('Unknown mode for packaging the application. Abort!')
sys.exit(11)
-def parse_optional_arg(default_value):
- def func(option, value, values, parser):
- del value
- del values
- if parser.rargs and not parser.rargs[0].startswith('-'):
- val = parser.rargs[0]
- parser.rargs.pop(0)
- else:
- val = default_value
- setattr(parser.values, option.dest, val)
- return func
-
-
def main(argv):
parser = optparse.OptionParser()
parser.add_option('-v', '--version', action='store_true',
'--compressor=js: compress javascript.'
'--compressor=css: compress css.')
group.add_option('--compressor', dest='compressor', action='callback',
- callback=parse_optional_arg('all'), help=info)
+ callback=ParseParameterForCompressor, type='string', nargs=0,
+ help=info)
parser.add_option_group(group)
options, _ = parser.parse_args()
if len(argv) == 1:
options.manifest = manifest_path
if not options.manifest:
- if not options.package:
+ if options.package:
+ VerifyAppName(options.package, 'packagename')
+ else:
parser.error('The package name is required! '
'Please use "--package" option.')
- elif len(options.package) >= 128 :
- parser.error('To be safe, the length of package name '
- 'should be less than 128.')
-
- if not options.name:
+ if options.name:
+ VerifyAppName(options.name)
+ else:
parser.error('The APK name is required! Please use "--name" option.')
if not ((options.app_url and not options.app_root
and not options.app_local_path) or ((not options.app_url)
'does exist.')
sys.exit(7)
- options.name = ReplaceInvalidChars(options.name, 'apkname')
- options.package = ReplaceInvalidChars(options.package)
- sanitized_name = ReplaceInvalidChars(options.name, 'apkname')
-
if options.target_dir:
target_dir = os.path.abspath(os.path.expanduser(options.target_dir))
options.target_dir = target_dir
os.makedirs(target_dir)
try:
- compress = compress_js_and_css.CompressJsAndCss(options.app_root)
- if options.compressor == 'all':
- compress.CompressJavaScript()
- compress.CompressCss()
- elif options.compressor == 'js':
- compress.CompressJavaScript()
- elif options.compressor == 'css':
- compress.CompressCss()
- MakeApk(options, sanitized_name)
+ MakeApk(options)
except SystemExit as ec:
- CleanDir(sanitized_name)
+ CleanDir(options.name)
CleanDir('out')
- if os.path.exists(xpk_temp_dir):
- CleanDir(xpk_temp_dir)
+ CleanDir(xpk_temp_dir)
return ec.code
return 0
os.remove(name + '_' + app_version + '_arm.apk')
+def CompareSizeForCompressor(mode, original, ext, name, fun):
+ size = 0
+ compressed_size = 0
+ mode_list = ['all', 'js', 'css']
+
+ www_dir = os.path.join(name, 'assets', 'www')
+ if os.path.exists(www_dir):
+ size = GetFileSize(original)
+ compressed_file = os.path.join(www_dir, ext, 'test.' + ext)
+ compressed_size = GetFileSize(compressed_file)
+
+ if mode in mode_list:
+ fun(compressed_size < size)
+ else:
+ fun(size == compressed_size)
+ else:
+ print('Error: %s is not exist.' % www_dir)
+
+
+def GetFileSize(file_path):
+ size = 0
+ if os.path.exists(file_path):
+ size = os.path.getsize(file_path)
+ return size
+
+
def RunCommand(command):
"""Runs the command list, return the output."""
proc = subprocess.Popen(command, stdout=subprocess.PIPE,
return proc.communicate()[0]
+def GetResultWithOption(mode, manifest=None, name=None, package=None):
+ app_url = None
+ if manifest != None:
+ manifest = '--manifest=' + manifest
+ else:
+ app_url = '--app-url=http://www.intel.com'
+ if name != None:
+ name = '--name=' + name
+ if package != None:
+ package = '--package=' + package
+ cmd = ['python', 'make_apk.py',
+ '--app-version=1.0.0',
+ '%s' % manifest,
+ '%s' % name,
+ '%s' % package,
+ '%s' % app_url,
+ mode]
+ return RunCommand(cmd)
+
+
class TestMakeApk(unittest.TestCase):
@classmethod
def setUpClass(cls):
out = RunCommand(cmd)
Clean('Example', '1.0.0')
self.assertTrue(out.find('The APK name is required!') != -1)
- cmd = ['python', 'make_apk.py', '--name="Test Example"',
- '--app-version=1.0.0',
+
+ cmd = ['python', 'make_apk.py', '--name=Test_Example',
+ '--app-version=1.0.0', '--app-url=http://www.intel.com',
'--package=org.xwalk.example', self._mode]
out = RunCommand(cmd)
- Clean('Test Example', '1.0.0')
self.assertTrue(out.find('The APK name is required!') == -1)
- # The following invalid chars verification is too heavy for embedded mode,
- # and the result of verification should be the same between shared mode
- # and embedded mode. So only do the verification in the shared mode.
- if self._mode.find('shared') != -1:
- invalid_chars = '\/:.*?"<>|-'
- for c in invalid_chars:
- invalid_name = '--name=Example' + c
- cmd = ['python', 'make_apk.py', invalid_name,
- '--app-version=1.0.0', '--package=org.xwalk.example',
- '--app-url=http://www.intel.com', self._mode]
- out = RunCommand(cmd)
- Clean('Example_', '1.0.0')
- self.assertTrue(out.find('Illegal character') != -1)
+ Clean('Test_Example', '1.0.0')
+
+ invalid_chars = '\/:.*?"<>|-'
+ for c in invalid_chars:
+ invalid_name = '--name=Example' + c
+ cmd = ['python', 'make_apk.py', invalid_name,
+ '--app-version=1.0.0', '--package=org.xwalk.example',
+ '--app-url=http://www.intel.com', self._mode]
+ out = RunCommand(cmd)
+ self.assertTrue(out.find('invalid characters') != -1)
def testToolVersion(self):
cmd = ['python', 'make_apk.py', '--version']
self.executeCommandAndVerifyResult('customize.py')
-
def testTargetDir(self):
test_option = ['./', '../', '~/']
for option in test_option:
self.assertTrue(os.path.exists(apk_path))
self.checkApk(apk_path, arch)
+ def testCompressor(self):
+ app_root = os.path.join('test_data', 'compressor')
+ css_folder = os.path.join('test_data', 'compressor', 'css')
+ css_file = os.path.join(css_folder, 'test.css')
+ js_folder = os.path.join('test_data', 'compressor', 'js')
+ js_file = os.path.join(js_folder, 'test.js')
+ fun = self.assertTrue
+ name = 'Example'
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--compressor',
+ '--app-root=%s' % app_root]
+ RunCommand(cmd)
+ CompareSizeForCompressor('all', css_file, 'css', name, fun)
+ CompareSizeForCompressor('all', js_file, 'js', name, fun)
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--app-root=%s' % app_root,
+ '--compressor']
+ RunCommand(cmd)
+ CompareSizeForCompressor('all', css_file, 'css', name, fun)
+ CompareSizeForCompressor('all', js_file, 'js', name, fun)
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--compressor=js',
+ '--app-root=%s' % app_root]
+ RunCommand(cmd)
+ CompareSizeForCompressor('js', js_file, 'js', name, fun)
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--compressor=css',
+ '--app-root=%s' % app_root]
+ RunCommand(cmd)
+ CompareSizeForCompressor('css', css_file, 'css', name, fun)
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--app-root=%s' % app_root]
+ RunCommand(cmd)
+ CompareSizeForCompressor(None, css_file, 'css', name, fun)
+ CompareSizeForCompressor(None, js_file, 'js', name, fun)
+
+ cmd = ['python', 'customize.py',
+ '--name=%s' % name,
+ '--app-root=%s' % app_root,
+ '--compressor=other']
+ RunCommand(cmd)
+ CompareSizeForCompressor(None, css_file, 'css', name, fun)
+ CompareSizeForCompressor(None, js_file, 'js', name, fun)
+
+ Clean(name, '1.0.0')
+
+ def testInvalidCharacter(self):
+ version = '1.0.0'
+ start_with_letters = ' should be started with letters'
+ app_name_error = 'app name' + start_with_letters
+ package_name_error = 'package name' + start_with_letters
+ parse_error = 'parser error in manifest.json file'
+ directory = os.path.join('test_data', 'manifest', 'invalidchars')
+
+ manifest_path = os.path.join(directory, 'manifest_with_space_name.json')
+ result = GetResultWithOption(self._mode, manifest_path)
+ self.assertTrue(result.find(app_name_error) != -1)
+
+ manifest_path = os.path.join(directory, 'manifest_with_chinese_name.json')
+ result = GetResultWithOption(self._mode, manifest_path)
+ self.assertTrue(result.find(app_name_error) != -1)
+
+ manifest_path = os.path.join(directory, 'manifest_parse_error.json')
+ result = GetResultWithOption(self._mode, manifest_path)
+ self.assertTrue(result.find(parse_error) != -1)
+
+ manifest_path = os.path.join(directory, 'manifest_with_invalid_name.json')
+ result = GetResultWithOption(self._mode, manifest_path)
+ self.assertTrue(result.find(app_name_error) != -1)
+
+ package = 'org.xwalk.example'
+ name = '_hello'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(app_name_error) != -1)
+
+ name = '123hello'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(app_name_error) != -1)
+
+ name = 'hello_'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(app_name_error) == -1)
+ Clean(name, version)
+
+ name = 'xwalk'
+ package = 'org.xwalk._example'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(package_name_error) != -1)
+
+ package = 'org.xwalk.123example'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(package_name_error) != -1)
+
+ package = 'org.xwalk.example_'
+ result = GetResultWithOption(self._mode, name=name, package=package)
+ self.assertTrue(result.find(package_name_error) == -1)
+ Clean(name, version)
+
def SuiteWithModeOption():
# Gather all the tests for the specified mode option.
test_suite.addTest(TestMakeApk('testFullscreen'))
test_suite.addTest(TestMakeApk('testIconByOption'))
test_suite.addTest(TestMakeApk('testIconByManifest'))
+ test_suite.addTest(TestMakeApk('testInvalidCharacter'))
test_suite.addTest(TestMakeApk('testKeystore'))
test_suite.addTest(TestMakeApk('testManifest'))
test_suite.addTest(TestMakeApk('testManifestWithError'))
def SuiteWithEmptyModeOption():
# Gather all the tests for empty mode option.
test_suite = unittest.TestSuite()
+ test_suite.addTest(TestMakeApk('testCompressor'))
test_suite.addTest(TestMakeApk('testCustomizeFile'))
test_suite.addTest(TestMakeApk('testEmptyMode'))
test_suite.addTest(TestMakeApk('testToolVersion'))
input_src = input_file.read()
self.data_src = json.JSONDecoder().decode(input_src)
self.ret_dict = self._output_items()
- except (TypeError, ValueError, IOError):
- print('There is a parser error in manifest.json file.')
+ except (TypeError, ValueError, IOError) as error:
+ print('There is a parser error in manifest.json file: %s' % error)
sys.exit(1)
- except KeyError:
- print('There is a field error in manifest.json file.')
+ except KeyError as error:
+ print('There is a field error in manifest.json file: %s' % error)
sys.exit(1)
finally:
input_file.close()
--- /dev/null
+/*
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+#body {
+ background-color: blue;
+}
+
+#div {
+ position: absolute;
+ width: 20px;
+ height: 20px;
+ text-align: center;
+}
+
+h1 {
+ color:orange;
+ text-align:center;
+}
+
+p {
+ font-family:"Times New Roman";
+ font-size:50px;
+}
--- /dev/null
+/*
+ * Copyright (c) 2014, Intel Corporation.
+ *
+ * This program is licensed under the terms and conditions of the
+ * Apache License, version 2.0. The full text of the Apache License is at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ */
+
+function multiplication(p1, p2) {
+ return p1 * p2; // return the product of p1 and p2.
+}
+
+function testAlert() {
+ alert("hello, world");
+}
--- /dev/null
+{
+ "name": "\Example",
+ "version": "1.0.0",
+ "launch_path": "http://www.intel.com",
+ "app": {
+ "launch": {
+ "local_path": "index.html"
+ }
+ },
+ "description": "a sample description",
+ "origin": "app://app.id",
+ "default_locale": "en",
+ "fullscreen":"true"
+}
--- /dev/null
+{
+ "name": "ä½ å¥½",
+ "version": "1.0.0",
+ "launch_path": "http://www.intel.com",
+ "app": {
+ "launch": {
+ "local_path": "index.html"
+ }
+ },
+ "description": "a sample description",
+ "origin": "app://app.id",
+ "default_locale": "en",
+ "fullscreen":"true"
+}
--- /dev/null
+{
+ "name": "@*&^Example",
+ "version": "1.0.0",
+ "launch_path": "http://www.intel.com",
+ "app": {
+ "launch": {
+ "local_path": "index.html"
+ }
+ },
+ "description": "a sample description",
+ "origin": "app://app.id",
+ "default_locale": "en",
+ "fullscreen":"true"
+}
--- /dev/null
+{
+ "name": " ",
+ "version": "1.0.0",
+ "launch_path": "http://www.intel.com",
+ "app": {
+ "launch": {
+ "local_path": "index.html"
+ }
+ },
+ "description": "a sample description",
+ "origin": "app://app.id",
+ "default_locale": "en",
+ "fullscreen":"true"
+}
#include "xwalk/runtime/browser/xwalk_runner.h"
#include "xwalk/runtime/common/xwalk_common_messages.h"
-#if defined(OS_TIZEN)
-#include "xwalk/runtime/browser/ui/native_app_window.h"
-#endif
-
-#if defined(USE_OZONE) && defined(OS_TIZEN)
-#include "base/message_loop/message_pump_ozone.h"
-#include "content/public/browser/render_view_host.h"
-#include "ui/events/event.h"
-#include "ui/events/event_constants.h"
-#include "ui/events/keycodes/keyboard_codes_posix.h"
-#include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
-#endif
-
-#if defined(OS_TIZEN)
-#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
-#endif
-
namespace xwalk {
namespace keys = application_manifest_keys;
"index.xhtml",
"index.xht"};
-content::RenderProcessHost* GetHost(Runtime* runtime) {
- DCHECK(runtime);
- return runtime->web_contents()->GetRenderProcessHost();
-}
} // namespace
namespace application {
scoped_refptr<ApplicationData> data,
RuntimeContext* runtime_context,
Observer* observer)
- : runtime_context_(runtime_context),
+ : main_runtime_(NULL),
application_data_(data),
- main_runtime_(NULL),
+ is_security_mode_(false),
+ runtime_context_(runtime_context),
observer_(observer),
entry_point_used_(Default),
termination_mode_used_(Normal),
- weak_factory_(this),
- is_security_mode_(false) {
+ weak_factory_(this) {
DCHECK(runtime_context_);
DCHECK(application_data_);
DCHECK(observer_);
-#if defined(USE_OZONE) && defined(OS_TIZEN)
- base::MessagePumpOzone::Current()->AddObserver(this);
-#endif
}
Application::~Application() {
-#if defined(USE_OZONE) && defined(OS_TIZEN)
- base::MessagePumpOzone::Current()->RemoveObserver(this);
-#endif
Terminate(Immediate);
}
std::mem_fun(&Runtime::Close));
}
-#if defined(OS_TIZEN)
-void Application::Hide() {
- DCHECK(runtimes_.size());
- std::set<Runtime*>::iterator it = runtimes_.begin();
- for (; it != runtimes_.end(); ++it) {
- if ((*it)->window())
- (*it)->window()->Hide();
- }
-}
-#endif
-
Runtime* Application::GetMainDocumentRuntime() const {
return HasMainDocument() ? main_runtime_ : NULL;
}
if (application_data_->GetPackageType() != Manifest::TYPE_WGT)
return;
-#if defined(OS_TIZEN)
- // On Tizen, CSP mode has higher priority, and WARP will be disabled
- // if the application is under CSP mode.
- if (application_data_->HasCSPDefined()) {
- // Always enable security mode when under CSP mode.
- is_security_mode_ = true;
- NavigationInfo* info = static_cast<NavigationInfo*>(
- application_data_->GetManifestData(widget_keys::kAllowNavigationKey));
- if (info) {
- const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
- for (std::vector<std::string>::const_iterator it = allowed_list.begin();
- it != allowed_list.end(); ++it) {
- // If the policy start with "*.", like this: *.domain,
- // means that can access to all subdomains for 'domain',
- // otherwise, the host of request url should exactly the same
- // as policy.
- bool subdomains = ((*it).find("*.") == 0);
- std::string host = subdomains ? (*it).substr(2) : (*it);
- AddSecurityPolicy(GURL("http://" + host), subdomains);
- AddSecurityPolicy(GURL("https://" + host), subdomains);
- }
- }
- GetHost(main_runtime_)->Send(
- new ViewMsg_EnableSecurityMode(
- ApplicationData::GetBaseURLFromApplicationId(id()),
- SecurityPolicy::CSP));
- return;
- }
-#endif
const WARPInfo* info = static_cast<WARPInfo*>(
application_data_->GetManifestData(widget_keys::kAccessKey));
// FIXME(xinchao): Need to enable WARP mode by default.
is_security_mode_ = true;
}
if (is_security_mode_)
- GetHost(main_runtime_)->Send(
+ main_runtime_->GetRenderProcessHost()->Send(
new ViewMsg_EnableSecurityMode(
ApplicationData::GetBaseURLFromApplicationId(id()),
SecurityPolicy::WARP));
void Application::AddSecurityPolicy(const GURL& url, bool subdomains) {
GURL app_url = application_data_->URL();
- GetHost(main_runtime_)->Send(
+ main_runtime_->GetRenderProcessHost()->Send(
new ViewMsg_SetAccessWhiteList(
app_url, url, subdomains));
security_policy_.push_back(new SecurityPolicy(url, subdomains));
url.host() == id())
return true;
- for (int i = 0; i < security_policy_.size(); ++i) {
+ for (unsigned i = 0; i < security_policy_.size(); ++i) {
const GURL& policy = security_policy_[i]->url();
bool subdomains = security_policy_[i]->subdomains();
bool is_host_matched = subdomains ?
return false;
}
-#if defined(USE_OZONE) && defined(OS_TIZEN)
-base::EventStatus Application::WillProcessEvent(
- const base::NativeEvent& event) {
- return base::EVENT_CONTINUE;
-}
-
-void Application::DidProcessEvent(
- const base::NativeEvent& event) {
- ui::Event* eve = static_cast<ui::Event*>(event);
- if (!eve->IsKeyEvent() || eve->type() != ui::ET_KEY_PRESSED)
- return;
-
- ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(eve);
-
- // FIXME: Most Wayland devices don't have similar hardware button for 'back'
- // and 'memu' as Tizen Mobile, even that hardare buttons could be different
- // across different kinds of Wayland platforms.
- // Here use external keyboard button 'Backspace' & 'HOME' to emulate 'back'
- // and 'menu' key. Should change this if there is customized key binding.
- if (key_event->key_code() != ui::VKEY_BACK &&
- key_event->key_code() != ui::VKEY_HOME)
- return;
-
- TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
- data()->GetManifestData(widget_keys::kTizenSettingKey));
- if (info && !info->hwkey_enabled())
- return;
-
- for (std::set<xwalk::Runtime*>::iterator it = runtimes_.begin();
- it != runtimes_.end(); ++it) {
- (*it)->web_contents()->GetRenderViewHost()->Send(new ViewMsg_HWKeyPressed(
- (*it)->web_contents()->GetRoutingID(), key_event->key_code()));
- }
-}
-#endif
-
} // namespace application
} // namespace xwalk
#include "xwalk/application/common/security_policy.h"
#include "xwalk/runtime/browser/runtime.h"
-#if defined(USE_OZONE) && defined(OS_TIZEN)
-#include "base/message_loop/message_pump_observer.h"
-#endif
-
namespace xwalk {
class RuntimeContext;
// terminated.
// There's one-to-one correspondence between Application and Render Process
// Host, obtained from its "runtimes" (pages).
-class Application
- :
-#if defined(USE_OZONE) && defined(OS_TIZEN)
- public base::MessagePumpObserver,
-#endif
- public Runtime::Observer {
+class Application : public Runtime::Observer {
public:
virtual ~Application();
};
void Terminate(TerminationMode = Normal);
-#if defined(OS_TIZEN)
- void Hide();
-#endif
-
// Returns Runtime (application page) containing the application's
// 'main document'. The main document is the main entry point of
// the application to the system. This method will return 'NULL'
StoredPermission perm);
bool CanRequestURL(const GURL& url) const;
+ protected:
+ // We enforce ApplicationService ownership.
+ friend class ApplicationService;
+ Application(scoped_refptr<ApplicationData> data,
+ RuntimeContext* context,
+ Observer* observer);
+
+ virtual void InitSecurityPolicy();
+ void AddSecurityPolicy(const GURL& url, bool subdomains);
+
+ Runtime* main_runtime_;
+ std::set<Runtime*> runtimes_;
+ scoped_refptr<ApplicationData> const application_data_;
+ bool is_security_mode_;
+
private:
bool HasMainDocument() const;
// Runtime::Observer implementation.
virtual void OnRuntimeAdded(Runtime* runtime) OVERRIDE;
virtual void OnRuntimeRemoved(Runtime* runtime) OVERRIDE;
- // We enforce ApplicationService ownership.
- friend class ApplicationService;
- Application(scoped_refptr<ApplicationData> data,
- RuntimeContext* context,
- Observer* observer);
bool Launch(const LaunchParams& launch_params);
// Try to extract the URL from different possible keys for entry points in the
bool IsOnSuspendHandlerRegistered() const;
bool IsTerminating() const { return finish_observer_; }
- void InitSecurityPolicy();
- void AddSecurityPolicy(const GURL& url, bool subdomains);
-
-#if defined(USE_OZONE) && defined(OS_TIZEN)
- virtual base::EventStatus WillProcessEvent(
- const base::NativeEvent& event) OVERRIDE;
- virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
-#endif
-
RuntimeContext* runtime_context_;
- const scoped_refptr<ApplicationData> application_data_;
- Runtime* main_runtime_;
- std::set<Runtime*> runtimes_;
scoped_ptr<EventObserver> finish_observer_;
Observer* observer_;
// The entry point used as part of Launch().
LaunchEntryPoint entry_point_used_;
TerminationMode termination_mode_used_;
- base::WeakPtrFactory<Application> weak_factory_;
std::map<std::string, std::string> name_perm_map_;
// Application's session permissions.
StoredPermissionMap permission_map_;
// Security policy set.
ScopedVector<SecurityPolicy> security_policy_;
- bool is_security_mode_;
-
+ // WeakPtrFactory should be always declared the last.
+ base::WeakPtrFactory<Application> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Application);
};
#include "xwalk/runtime/common/xwalk_paths.h"
#if defined(OS_TIZEN)
+#include "xwalk/application/browser/application_tizen.h"
#include "xwalk/application/browser/installer/tizen/service_package_installer.h"
#endif
return result;
}
-bool ApplicationService::ChangeLocale(const std::string& locale) {
+void ApplicationService::ChangeLocale(const std::string& locale) {
const ApplicationData::ApplicationDataMap& apps =
application_storage_->GetInstalledApplications();
ApplicationData::ApplicationDataMap::const_iterator it;
}
event_manager_->AddEventRouterForApp(application_data);
+
+#if defined(OS_TIZEN)
+ Application* application(new ApplicationTizen(application_data,
+ runtime_context_, this));
+#else
Application* application(new Application(application_data,
- runtime_context_,
- this));
+ runtime_context_, this));
+#endif
+
ScopedVector<Application>::iterator app_iter =
applications_.insert(applications_.end(), application);
bool Install(const base::FilePath& path, std::string* id);
bool Uninstall(const std::string& id);
bool Update(const std::string& id, const base::FilePath& path);
- bool ChangeLocale(const std::string& locale);
+ void ChangeLocale(const std::string& locale);
Application* Launch(scoped_refptr<ApplicationData> application_data,
const Application::LaunchParams& launch_params);
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/application/browser/application_tizen.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/render_process_host.h"
+
+#include "xwalk/runtime/browser/ui/native_app_window.h"
+#include "xwalk/runtime/common/xwalk_common_messages.h"
+
+#if defined(USE_OZONE)
+#include "base/message_loop/message_pump_ozone.h"
+#include "content/public/browser/render_view_host.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+#include "xwalk/application/common/manifest_handlers/tizen_setting_handler.h"
+#endif
+
+#include "xwalk/application/common/application_manifest_constants.h"
+#include "xwalk/application/common/manifest_handlers/navigation_handler.h"
+
+namespace xwalk {
+
+namespace widget_keys = application_widget_keys;
+
+namespace application {
+
+namespace {
+const char kAsterisk[] = "*";
+} // namespace
+
+
+ApplicationTizen::ApplicationTizen(
+ scoped_refptr<ApplicationData> data,
+ RuntimeContext* runtime_context,
+ Application::Observer* observer)
+ : Application(data, runtime_context, observer) {
+#if defined(USE_OZONE)
+ base::MessagePumpOzone::Current()->AddObserver(this);
+#endif
+}
+
+ApplicationTizen::~ApplicationTizen() {
+#if defined(USE_OZONE)
+ base::MessagePumpOzone::Current()->RemoveObserver(this);
+#endif
+}
+
+void ApplicationTizen::Hide() {
+ DCHECK(runtimes_.size());
+ std::set<Runtime*>::iterator it = runtimes_.begin();
+ for (; it != runtimes_.end(); ++it) {
+ if ((*it)->window())
+ (*it)->window()->Hide();
+ }
+}
+
+void ApplicationTizen::InitSecurityPolicy() {
+ // On Tizen, CSP mode has higher priority, and WARP will be disabled
+ // if the application is under CSP mode.
+ if (!application_data_->HasCSPDefined()) {
+ Application::InitSecurityPolicy();
+ return;
+ }
+
+ if (application_data_->GetPackageType() != Manifest::TYPE_WGT)
+ return;
+
+ // Always enable security mode when under CSP mode.
+ is_security_mode_ = true;
+ NavigationInfo* info = static_cast<NavigationInfo*>(
+ application_data_->GetManifestData(widget_keys::kAllowNavigationKey));
+ if (info) {
+ const std::vector<std::string>& allowed_list = info->GetAllowedDomains();
+ for (std::vector<std::string>::const_iterator it = allowed_list.begin();
+ it != allowed_list.end(); ++it) {
+ // If the policy is "*", it represents that any external link is allowed
+ // to navigate to.
+ if ((*it) == kAsterisk) {
+ is_security_mode_ = false;
+ return;
+ }
+
+ // If the policy start with "*.", like this: *.domain,
+ // means that can access to all subdomains for 'domain',
+ // otherwise, the host of request url should exactly the same
+ // as policy.
+ bool subdomains = ((*it).find("*.") == 0);
+ std::string host = subdomains ? (*it).substr(2) : (*it);
+ AddSecurityPolicy(GURL("http://" + host), subdomains);
+ AddSecurityPolicy(GURL("https://" + host), subdomains);
+ }
+ }
+ main_runtime_->GetRenderProcessHost()->Send(
+ new ViewMsg_EnableSecurityMode(
+ ApplicationData::GetBaseURLFromApplicationId(id()),
+ SecurityPolicy::CSP));
+}
+
+#if defined(USE_OZONE)
+base::EventStatus ApplicationTizen::WillProcessEvent(
+ const base::NativeEvent& event) {
+ return base::EVENT_CONTINUE;
+}
+
+void ApplicationTizen::DidProcessEvent(
+ const base::NativeEvent& event) {
+ ui::Event* ui_event = static_cast<ui::Event*>(event);
+ if (!ui_event->IsKeyEvent() || ui_event->type() != ui::ET_KEY_PRESSED)
+ return;
+
+ ui::KeyEvent* key_event = static_cast<ui::KeyEvent*>(ui_event);
+
+ // FIXME: Most Wayland devices don't have similar hardware button for 'back'
+ // and 'memu' as Tizen Mobile, even that hardare buttons could be different
+ // across different kinds of Wayland platforms.
+ // Here use external keyboard button 'Backspace' & 'HOME' to emulate 'back'
+ // and 'menu' key. Should change this if there is customized key binding.
+ if (key_event->key_code() != ui::VKEY_BACK &&
+ key_event->key_code() != ui::VKEY_HOME)
+ return;
+
+ TizenSettingInfo* info = static_cast<TizenSettingInfo*>(
+ data()->GetManifestData(widget_keys::kTizenSettingKey));
+ if (info && !info->hwkey_enabled())
+ return;
+
+ for (std::set<xwalk::Runtime*>::iterator it = runtimes_.begin();
+ it != runtimes_.end(); ++it) {
+ (*it)->web_contents()->GetRenderViewHost()->Send(new ViewMsg_HWKeyPressed(
+ (*it)->web_contents()->GetRoutingID(), key_event->key_code()));
+ }
+}
+#endif
+
+} // namespace application
+} // namespace xwalk
--- /dev/null
+// Copyright (c) 2013 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef XWALK_APPLICATION_BROWSER_APPLICATION_TIZEN_H_
+#define XWALK_APPLICATION_BROWSER_APPLICATION_TIZEN_H_
+
+#include "xwalk/application/browser/application.h"
+
+#if defined(USE_OZONE)
+#include "base/message_loop/message_pump_observer.h"
+#endif
+
+namespace xwalk {
+namespace application {
+
+class ApplicationTizen : // NOLINT
+#if defined(USE_OZONE)
+ public base::MessagePumpObserver,
+#endif
+ public Application {
+ public:
+ virtual ~ApplicationTizen();
+ void Hide();
+
+ private:
+ // We enforce ApplicationService ownership.
+ friend class ApplicationService;
+ ApplicationTizen(scoped_refptr<ApplicationData> data,
+ RuntimeContext* context,
+ Application::Observer* observer);
+
+ virtual void InitSecurityPolicy() OVERRIDE;
+
+#if defined(USE_OZONE)
+ virtual base::EventStatus WillProcessEvent(
+ const base::NativeEvent& event) OVERRIDE;
+ virtual void DidProcessEvent(const base::NativeEvent& event) OVERRIDE;
+#endif
+};
+
+inline ApplicationTizen* ToApplicationTizen(Application* app) {
+ return static_cast<ApplicationTizen*>(app);
+}
+
+} // namespace application
+} // namespace xwalk
+
+#endif // XWALK_APPLICATION_BROWSER_APPLICATION_TIZEN_H_
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/exported_object.h"
+#include "xwalk/application/browser/application_tizen.h"
#include "xwalk/application/browser/linux/running_applications_manager.h"
-
namespace {
// D-Bus Interface implemented by objects that represent running
return;
}
- application_->Hide();
+ ToApplicationTizen(application_)->Hide();
scoped_ptr<dbus::Response> response =
dbus::Response::FromMethodCall(method_call);
#include "xwalk/application/common/manifest_handler.h"
#include "xwalk/application/common/manifest_handlers/main_document_handler.h"
#include "xwalk/application/common/manifest_handlers/permissions_handler.h"
+#include "xwalk/application/common/manifest_handlers/widget_handler.h"
#include "xwalk/application/common/permission_policy_manager.h"
#include "content/public/common/url_constants.h"
#include "url/url_util.h"
bool ApplicationData::SetApplicationLocale(const std::string& locale,
base::string16* error) {
+ DCHECK(thread_checker_.CalledOnValidThread());
manifest_->SetSystemLocale(locale);
if (!LoadName(error))
return false;
if (!LoadDescription(error))
return false;
+
+ // Only update when the package is wgt and we have parsed the widget handler,
+ // otherwise we can not get widget_info.
+ if (WidgetInfo* widget_info = static_cast<WidgetInfo*>(
+ GetManifestData(widget_keys::kWidgetKey))) {
+ std::string string_value;
+ if (manifest_->GetString(widget_keys::kNameKey, &string_value))
+ widget_info->SetName(string_value);
+ if (manifest_->GetString(widget_keys::kShortNameKey, &string_value))
+ widget_info->SetShortName(string_value);
+ if (manifest_->GetString(widget_keys::kDescriptionKey, &string_value))
+ widget_info->SetDescription(string_value);
+ }
return true;
}
FILE_PATH_LITERAL("messages.json");
const char kGeneratedMainDocumentFilename[] =
"_generated_main_document.html";
+const base::FilePath::CharType kCookieDatabaseFilename[] =
+ FILE_PATH_LITERAL("ApplicationCookies");
} // namespace application
} // namespace xwalk
// The filename to use for main document generated from app.main.scripts.
extern const char kGeneratedMainDocumentFilename[];
+// The name of cookies database file.
+extern const base::FilePath::CharType kCookieDatabaseFilename[];
+
} // namespace application
} // namespace xwalk
value_->Set(key, value);
}
+void WidgetInfo::SetName(const std::string& name) {
+ value_->SetString(kName, name);
+}
+
+void WidgetInfo::SetShortName(const std::string& short_name) {
+ value_->SetString(kShortName, short_name);
+}
+
+void WidgetInfo::SetDescription(const std::string& description) {
+ value_->SetString(kDecription, description);
+}
+
WidgetHandler::WidgetHandler() {}
WidgetHandler::~WidgetHandler() {}
void SetString(const std::string& key, const std::string& value);
void Set(const std::string& key, base::Value* value);
+ // Name, shrot name and description are i18n items, they will be set
+ // if their value were changed after loacle was changed.
+ void SetName(const std::string& name);
+ void SetShortName(const std::string& short_name);
+ void SetDescription(const std::string& description);
+
base::DictionaryValue* GetWidgetInfo() {
return value_.get();
}
'gio',
],
}],
- ['tizen==1 or tizen_mobile==1', {
+ ['tizen==1', {
'dependencies': [
'gio',
'../../../build/system.gyp:tizen_appcore_common'
'type': 'executable',
'product_name': 'xwalk-pkg-helper',
'conditions': [
- ['tizen==1 or tizen_mobile==1', {
+ ['tizen==1', {
'dependencies': [
'../../../build/system.gyp:tizen',
'../../../../base/base.gyp:base',
'browser/linux/running_applications_manager.h',
],
}],
- [ 'tizen == 1 or tizen_mobile == 1', {
+ ['tizen==1', {
'dependencies': [
'build/system.gyp:tizen',
'tizen/xwalk_tizen.gypi:xwalk_tizen_lib',
'../third_party/re2/re2.gyp:re2',
],
'sources': [
+ 'browser/application_tizen.cc',
+ 'browser/application_tizen.h',
'browser/installer/tizen/packageinfo_constants.cc',
'browser/installer/tizen/packageinfo_constants.h',
'browser/installer/tizen/service_package_installer.cc',
src_dir = os.path.join(out_project_dir, 'src')
if not os.path.isdir(src_dir):
os.mkdir(src_dir)
+ readme = os.path.join(src_dir, 'README.md')
+ open(readme, 'w').write(
+ "# Source folder for xwalk_core_library\n"
+ "## Why it's empty\n"
+ "xwalk_core_library doesn't contain java sources.\n"
+ "## Why put me here\n"
+ "To make archives keep the folder, "
+ "the src directory is needed to build an apk by ant.")
print 'Your Android library project has been created at %s' % (
out_project_dir)
{
'conditions': [
- [ 'tizen == 1 or tizen_mobile == 1', {
+ ['tizen==1', {
'targets': [
{
'target_name': 'tizen_geolocation',
# every .gyp file, including Chromium's).
{
'target_conditions': [
- ['tizen_mobile!=1 and tizen!=1', {
+ ['tizen!=1', {
'sources/': [
['exclude', '_tizen(_unittest)?\\.(h|cc)$'],
['exclude', '(^|/)tizen/'],
'xwalk_service_name.h',
],
'conditions': [
- [ 'tizen == 1 or tizen_mobile == 1', {
+ ['tizen==1', {
'sources': [
'dbus_manager_tizen.cc',
],
%bcond_with wayland
Name: crosswalk
-Version: 6.35.132.0
+Version: 7.35.136.0
Release: 0
Summary: Crosswalk is an app runtime based on Chromium
License: (BSD-3-Clause and LGPL-2.1+)
public void destroy() {
if (mXWalkContent == 0) return;
+ XWalkPreferences.unload(this);
// Reset existing notification service in order to destruct it.
setNotificationService(null);
// Remove its children used for page rendering from view hierarchy.
mLaunchScreenDialog.getWindow().setBackgroundDrawable(bgDrawable);
// Set foreground image
RelativeLayout root = getLaunchScreenLayout(imageBorderList);
- if (root == null) return;
- mLaunchScreenDialog.setContentView(root);
+ // The root layout can be null when there is no 'image' provided in the manifest.
+ // We can just display the background instead of no launch screen dialog displayed.
+ if (root != null) mLaunchScreenDialog.setContentView(root);
mLaunchScreenDialog.show();
// Change the layout depends on the orientation change.
import android.content.Intent;
import android.net.Uri;
import android.util.Log;
+import android.webkit.MimeTypeMap;
import org.chromium.components.navigation_interception.NavigationParams;
} else {
intent = createIntentForActionUri(url);
}
- return intent != null && startActivity(intent);
+ if (intent != null && startActivity(intent)) return true;
+
+ return handleUrlByMimeType(url);
}
protected boolean startActivity(Intent intent) {
}
return intent;
}
+
+ private boolean handleUrlByMimeType(String url) {
+ MimeTypeMap map = MimeTypeMap.getSingleton();
+ String extenstion = MimeTypeMap.getFileExtensionFromUrl(url);
+ String mimeType = map.getMimeTypeFromExtension(extenstion);
+
+ if (shouldHandleMimeType(mimeType)) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_VIEW);
+ sendIntent.setDataAndType(Uri.parse(url), mimeType);
+
+ if (sendIntent.resolveActivity(mContext.getPackageManager()) != null) {
+ startActivity(sendIntent);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean shouldHandleMimeType(String mimeType) {
+ // Currently only "application/*" MIME type should be handled.
+ // Other types (text/*, video/*, image/*, audio/*) are not handled
+ // by intent actions.
+ if (mimeType != null && mimeType.startsWith("application/")) {
+ return true;
+ }
+ return false;
+ }
}
* The direction for web page navigation.
*/
public enum Direction {
- /** the backward direction for web page navigation. */
+ /** The backward direction for web page navigation. */
BACKWARD,
- /** the forward direction for web page navigation. */
+ /** The forward direction for web page navigation. */
FORWARD
}
package org.xwalk.core;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
*/
public final class XWalkPreferences {
private static HashMap<String, Boolean> sPrefMap = new HashMap<String, Boolean>();
- private static ArrayList<KeyValueChangeListener> sListeners =
- new ArrayList<KeyValueChangeListener>();
+ // Here we use WeakReference to make sure the KeyValueChangeListener instance
+ // can be GC-ed to avoid memory leaking issue.
+ private static ArrayList<WeakReference<KeyValueChangeListener> > sListeners =
+ new ArrayList<WeakReference<KeyValueChangeListener> >();
+ private static ReferenceQueue<KeyValueChangeListener> sRefQueue =
+ new ReferenceQueue<KeyValueChangeListener>();
/**
* The key string to enable/disable remote debugging.
registerListener(listener);
}
+ static synchronized void unload(KeyValueChangeListener listener) {
+ unregisterListener(listener);
+ }
+
// Listen to value changes.
interface KeyValueChangeListener {
public void onKeyValueChanged(String key, boolean value);
}
private static synchronized void registerListener(KeyValueChangeListener listener) {
- sListeners.add(listener);
+ removeEnqueuedReference();
+ WeakReference<KeyValueChangeListener> weakListener =
+ new WeakReference<KeyValueChangeListener>(listener, sRefQueue);
+ sListeners.add(weakListener);
+ }
+
+ private static synchronized void unregisterListener(KeyValueChangeListener listener) {
+ removeEnqueuedReference();
+ for (WeakReference<KeyValueChangeListener> weakListener : sListeners) {
+ if (weakListener.get() == listener) {
+ sListeners.remove(weakListener);
+ break;
+ }
+ }
}
private static void onKeyValueChanged(String key, boolean enabled) {
- for (KeyValueChangeListener listener : sListeners) {
- listener.onKeyValueChanged(key, enabled);
+ for (WeakReference<KeyValueChangeListener> weakListener : sListeners) {
+ KeyValueChangeListener listener = weakListener.get();
+ if (listener != null) listener.onKeyValueChanged(key, enabled);
}
}
private static void checkKey(String key) throws RuntimeException {
+ removeEnqueuedReference();
if (!sPrefMap.containsKey(key)) {
throw new RuntimeException("Warning: the preference key " + key +
" is not supported by Crosswalk.");
}
}
+ /**
+ * Internal method to keep track of weak references and remove the enqueued
+ * references from listener list by polling the reference queue.
+ */
+ @SuppressWarnings("unchecked")
+ private static void removeEnqueuedReference() {
+ WeakReference<KeyValueChangeListener> toRemove;
+ while ((toRemove = (WeakReference<KeyValueChangeListener>) sRefQueue.poll()) != null) {
+ sListeners.remove(toRemove);
+ }
+ }
}
fResult.confirm();
dialog.dismiss();
}
- }).setOnKeyListener(new DialogInterface.OnKeyListener() {
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- fResult.confirm();
- return false;
- } else {
- return true;
- }
+ public void onCancel(DialogInterface dialog) {
+ fResult.cancel();
}
});
mDialog = dialogBuilder.create();
dialog.dismiss();
}
})
- .setNegativeButton(mCancelButton, null)
+ // Need to implement 'onClick' and call the dialog.cancel. Otherwise, the
+ // UI will be locked.
+ .setNegativeButton(mCancelButton, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // This will call OnCancelLisitener.onCancel().
+ dialog.cancel();
+ }
+ })
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
fResult.cancel();
}
- }).setOnKeyListener(new DialogInterface.OnKeyListener() {
- @Override
- public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_BACK) {
- fResult.confirm();
- return false;
- } else {
- return true;
- }
- }
});
mDialog = dialogBuilder.create();
mDialog.show();
dialog.dismiss();
}
})
- .setNegativeButton(mCancelButton, null)
+ // Need to implement 'onClick' and call the dialog.cancel. Otherwise, the
+ // UI will be locked.
+ .setNegativeButton(mCancelButton, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ // This will call OnCancelLisitener.onCancel().
+ dialog.cancel();
+ }
+ })
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
import org.xwalk.core.extension.XWalkExtensionManager;
/**
- * XWalkView represents an Android view for web apps/pages. Thus most of attributes
- * for Android view are true for this class. It includes an instance of
- * android.view.SurfaceView for rendering. Currently limitations for android.view.SurfaceView
- * also are applied for this class as well, like resizing, retation, transformation and
- * animation.
+ * <p>XWalkView represents an Android view for web apps/pages. Thus most of attributes
+ * for Android view are valid for this class. Since it internally uses
+ * <a href="http://developer.android.com/reference/android/view/SurfaceView.html">
+ * android.view.SurfaceView</a> for rendering web pages, it can't be resized, rotated,
+ * transformed and animated due to the limitations of SurfaceView. Besides, XWalkView won't
+ * be rendered if it's invisible.</p>
*
- * It provides 2 major callback classes, namely XWalkResourceClient and XWalkUIClient for
- * listening to the events related resource loading and UI. By default, Crosswalk has an inner
- * implementation. Callers can override them if like.
+ * <p>XWalkView needs hardware acceleration to render web pages. As a result, the
+ * AndroidManifest.xml of the caller's app must be appended with the attribute
+ * "android:hardwareAccelerated" and its value must be set as "true".</p>
+ * <pre>
+ * <application android:name="android.app.Application" android:label="XWalkUsers"
+ * android:hardwareAccelerated="true">
+ * </pre>
*
- * Unlike other Android views, this class has to listen to system events like application life
- * cycle, intents, and activity result. The web engine inside this view need to handle them.
+ * <p>Crosswalk provides 2 major callback classes, namely {@link XWalkResourceClient} and
+ * {@link XWalkUIClient} for listening to the events related to resource loading and UI.
+ * By default, Crosswalk has a default implementation. Callers can override them if needed.</p>
*
- * It already includes all newly created Web APIs from Crosswalk like Presentation,
- * DeviceCapabilities, etc..
+ * <p>Unlike other Android views, this class has to listen to system events like application life
+ * cycle, intents, and activity result. The web engine inside this view need to get and handle
+ * them. For example:</p>
+ *
+ * <pre>
+ * import android.app.Activity;
+ * import android.os.Bundle;
+ *
+ * import org.xwalk.core.XWalkResourceClient;
+ * import org.xwalk.core.XWalkUIClient;
+ * import org.xwalk.core.XWalkView;
+ *
+ * public class MyActivity extends Activity {
+ * XWalkView mXwalkView;
+ *
+ * class MyResourceClient extends XWalkResourceClient {
+ * MyResourceClient(XWalkView view) {
+ * super(view);
+ * }
+ *
+ * @Override
+ * WebResourceResponse shouldInterceptLoadRequest(XWalkView view, String url) {
+ * // Handle it here.
+ * ...
+ * }
+ * }
+ *
+ * class MyUIClient extends XWalkUIClient {
+ * MyUIClient(XWalkView view) {
+ * super(view);
+ * }
+ *
+ * @Override
+ * void onFullscreenToggled(XWalkView view, String url) {
+ * // Handle it here.
+ * ...
+ * }
+ * }
+ *
+ * @Override
+ * protected void onCreate(Bundle savedInstanceState) {
+ * mXwalkView = new XWalkView(this, null);
+ * setContentView(mXwalkView);
+ * mXwalkView.setResourceClient(new MyResourceClient(mXwalkView));
+ * mXwalkView.setUIClient(new MyUIClient(mXwalkView));
+ * mXwalkView.load("http://www.crosswalk-project.org", null);
+ * }
+ *
+ * @Override
+ * protected void onPause() {
+ * super.onPause();
+ * if (mXwalkView != null) {
+ * mXwalkView.pauseTimers();
+ * mXwalkView.onHide();
+ * }
+ * }
+ *
+ * @Override
+ * protected void onResume() {
+ * super.onResume();
+ * if (mXwalkView != null) {
+ * mXwalkView.resumeTimers();
+ * mXwalkView.onShow();
+ * }
+ * }
+ *
+ * @Override
+ * protected void onDestroy() {
+ * super.onDestroy();
+ * if (mXwalkView != null) {
+ * mXwalkView.onDestroy();
+ * }
+ * }
+ *
+ * @Override
+ * protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ * if (mXwalkView != null) {
+ * mXwalkView.onActivityResult(requestCode, resultCode, data);
+ * }
+ * }
+ *
+ * @Override
+ * protected void onNewIntent(Intent intent) {
+ * if (mXwalkView != null) {
+ * mXwalkView.onNewIntent(intent);
+ * }
+ * }
+ * }
+ * </pre>
*/
public class XWalkView extends android.widget.FrameLayout {
- protected static final String PLAYSTORE_DETAIL_URI = "market://details?id=";
+ static final String PLAYSTORE_DETAIL_URI = "market://details?id=";
private XWalkContent mContent;
private Activity mActivity;
private Context mContext;
private XWalkExtensionManager mExtensionManager;
- private boolean mIsTimerPaused;
private boolean mIsHidden;
/** Normal reload mode as default. */
}
private void initXWalkContent(Context context, AttributeSet attrs) {
- mIsTimerPaused = false;
mIsHidden = false;
mContent = new XWalkContent(context, attrs, this);
addView(mContent,
* just this XWalkView.
*/
public void pauseTimers() {
- if (mContent == null || mIsTimerPaused) return;
+ if (mContent == null) return;
checkThreadSafety();
mContent.pauseTimers();
- mIsTimerPaused = true;
}
/**
* just this XWalkView.
*/
public void resumeTimers() {
- if (mContent == null || !mIsTimerPaused) return;
+ if (mContent == null) return;
checkThreadSafety();
mContent.resumeTimers();
- mIsTimerPaused = false;
}
/**
/**
* Pass through activity result to XWalkView. Many internal facilities need this
* to handle activity result like JavaScript dialog, Crosswalk extensions, etc.
- * See android.app.Activity.onActivityResult().
+ * See <a href="http://developer.android.com/reference/android/app/Activity.html">
+ * android.app.Activity.onActivityResult()</a>.
* @param requestCode passed from android.app.Activity.onActivityResult().
* @param resultCode passed from android.app.Activity.onActivityResult().
* @param data passed from android.app.Activity.onActivityResult().
/**
* Pass through intents to XWalkView. Many internal facilities need this
* to receive the intents like web notification. See
- * android.app.Activity.onNewIntent().
+ * <a href="http://developer.android.com/reference/android/app/Activity.html">
+ * android.app.Activity.onNewIntent()</a>.
* @param intent passed from android.app.Activity.onNewIntent().
*/
public boolean onNewIntent(Intent intent) {
}
/**
- * Inherit from android.view.View. This class needs to handle some keys like
+ * Inherit from <a href="http://developer.android.com/reference/android/view/View.html">
+ * android.view.View</a>. This class needs to handle some keys like
* 'BACK'.
* @param keyCode passed from android.view.View.onKeyUp().
* @param event passed from android.view.View.onKeyUp().
notifyAvailabilityChanged(false);
// Destroy the presentation content if there is no available secondary display
// any more.
- if (mPresentationContent != null) {
- mPresentationContent.close();
- mPresentationContent = null;
- }
+ closePresentationContent();
}
}
@Override
public void onContentClosed(XWalkPresentationContent content) {
if (content == mPresentationContent) {
- mPresentationContent.close();
- mPresentationContent = null;
+ closePresentationContent();
if (mPresentationView != null) mPresentationView.cancel();
}
}
if (displays.length == 0 && mAvailableDisplayCount > 0) {
notifyAvailabilityChanged(false);
mAvailableDisplayCount = 0;
- if (mPresentationContent != null) {
- mPresentationContent.close();
- mPresentationContent = null;
- }
+ closePresentationContent();
}
// If there was no available display but right now there is at least one available
// If the presentation view is showed on another display, we need to dismiss it
// and re-create a new one.
if (mPresentationView != null && mPresentationView.getDisplay() != preferredDisplay) {
- mPresentationView.dismiss();
- mPresentationView = null;
+ dismissPresentationView();
}
// If the presentation view is not NULL and its associated display is not changed,
@Override
public void onPause() {
- if (mPresentationView != null) {
- mPresentationView.dismiss();
- mPresentationView = null;
- }
+ dismissPresentationView();
if (mPresentationContent != null) mPresentationContent.onPause();
@Override
public void onDestroy() {
+ // close the presentation content if have.
+ closePresentationContent();
+ }
+
+ private void dismissPresentationView() {
+ if (mPresentationView == null) return;
+
+ mPresentationView.dismiss();
+ mPresentationView = null;
+ }
+
+ private void closePresentationContent() {
+ if (mPresentationContent == null) return;
+
+ mPresentationContent.close();
+ mPresentationContent = null;
}
}
<category android:name="android.intent.category.SAMPLE_CODE" />
</intent-filter>
</activity>
+ <activity
+ android:name=".XWalkVersionAndAPIVersion"
+ android:label="Versions"
+ android:parentActivityName=".XWalkEmbeddedAPISample" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.SAMPLE_CODE" />
+ </intent-filter>
+ </activity>
</application>
-</manifest>
\ No newline at end of file
+</manifest>
<html>
<body>
Hello World.
- <script>alert('Hello World!')</script>
</body>
</html>
android:src="@android:drawable/ic_media_next" />
</LinearLayout>
+ <LinearLayout
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <TextView
+ android:id="@+id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FDF5E6" />
+
+ <TextView
+ android:id="@+id/text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FDF5E6" />
+
+ <TextView
+ android:id="@+id/text3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FDF5E6" />
+ </LinearLayout>
+
<org.xwalk.core.XWalkView
android:id="@+id/xwalkview"
android:layout_width="match_parent"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (c) 2014 Intel Corporation. All rights reserved.
+
+ Use of this source code is governed by a BSD-style license that can be
+ found in the LICENSE file.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:id="@+id/toolbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="#FDF5E6" />
+ </LinearLayout>
+
+ <org.xwalk.core.XWalkView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/xwalkview"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" >
+ </org.xwalk.core.XWalkView>
+
+</LinearLayout>
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
-public class LoadAppFromManifestActivity extends Activity {
+public class LoadAppFromManifestActivity extends XWalkBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xwview_layout);
- XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+ mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
// The manifest definition, please refer to the link:
// https://crosswalk-project.org/#wiki/Crosswalk-manifest
- xwalkView.loadAppFromManifest("file:///android_asset/manifest.json", null);
+ mXWalkView.loadAppFromManifest("file:///android_asset/manifest.json", null);
}
}
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
import android.widget.LinearLayout;
-public class MultiXWalkViewActivity extends Activity {
+public class MultiXWalkViewActivity extends XWalkBaseActivity {
+
+ private XWalkView mXWalkView2;
@Override
protected void onCreate(Bundle savedInstanceState) {
LinearLayout.LayoutParams.MATCH_PARENT);
params.weight = 1;
- XWalkView view1 = new XWalkView(this, this);
- parent.addView(view1, params);
+ mXWalkView = new XWalkView(this, this);
+ parent.addView(mXWalkView, params);
+
+ mXWalkView2 = new XWalkView(this, this);
+ parent.addView(mXWalkView2, params);
+
+ mXWalkView.load("http://www.intel.com", null);
+ mXWalkView2.load("http://www.baidu.com", null);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mXWalkView2 != null) {
+ mXWalkView2.onHide();
+ mXWalkView2.pauseTimers();
+ }
+ }
- XWalkView view2 = new XWalkView(this, this);
- parent.addView(view2, params);
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mXWalkView2 != null) {
+ mXWalkView2.onShow();
+ mXWalkView2.resumeTimers();
+ }
+ }
- view1.load("http://www.intel.com", null);
- view2.load("http://www.baidu.com", null);
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mXWalkView2 != null) {
+ mXWalkView2.onDestroy();
+ }
}
}
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
-public class OnHideOnShowActivity extends Activity {
-
- private XWalkView mXWalkView;
+public class OnHideOnShowActivity extends XWalkBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.xwview_layout);
mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+ // The web page below will display a video.
+ // When home button is pressed, the activity will be in background, and the video will be paused.
mXWalkView.load("http://www.w3.org/2010/05/video/mediaevents.html", null);
}
-
- @Override
- public void onPause() {
- super.onPause();
- // It will pause the video, when the app in background.
- mXWalkView.onHide();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- // Need to call onShow() when onHide() was called.
- mXWalkView.onShow();
- }
}
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
-public class PauseTimersActivity extends Activity {
+public class PauseTimersActivity extends XWalkBaseActivity {
private ImageButton mButton;
private boolean isPaused;
- XWalkView mXWalkView;
@Override
protected void onCreate(Bundle savedInstanceState) {
import org.xwalk.core.XWalkUIClient;
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.webkit.ValueCallback;
import android.webkit.WebResourceResponse;
-public class ResourceAndUIClientsActivity extends Activity {
+public class ResourceAndUIClientsActivity extends XWalkBaseActivity {
private static final String TAG = ResourceAndUIClientsActivity.class.getName();
- class ResourceCLient extends XWalkResourceClient {
+ class ResourceClient extends XWalkResourceClient {
- public ResourceCLient(XWalkView xwalkView) {
+ public ResourceClient(XWalkView xwalkView) {
super(xwalkView);
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xwview_layout);
- XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
- xwalkView.setResourceClient(new ResourceCLient(xwalkView));
- xwalkView.setUIClient(new UIClient(xwalkView));
- xwalkView.load("http://www.baidu.com", null);
+ mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+ mXWalkView.setResourceClient(new ResourceClient(mXWalkView));
+ mXWalkView.setUIClient(new UIClient(mXWalkView));
+ mXWalkView.load("http://www.baidu.com", null);
}
}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.app.Activity;
+
+public class XWalkBaseActivity extends Activity {
+ protected XWalkView mXWalkView;
+
+ /*
+ * When the activity is paused, XWalkView.onHide() and XWalkView.pauseTimers() need to be called.
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (mXWalkView != null) {
+ mXWalkView.onHide();
+ mXWalkView.pauseTimers();
+ }
+ }
+
+ /*
+ * When the activity is resumed, XWalkView.onShow() and XWalkView.resumeTimers() need to be called.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mXWalkView != null) {
+ mXWalkView.onShow();
+ mXWalkView.resumeTimers();
+ }
+ }
+
+ /*
+ * Call onDestroy on XWalkView to release native resources when the activity is destroyed.
+ */
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mXWalkView != null) {
+ mXWalkView.onDestroy();
+ }
+ }
+}
package org.xwalk.core.sample;
-import org.xwalk.core.XWalkView;
import org.xwalk.core.XWalkNavigationHistory;
+import org.xwalk.core.XWalkNavigationItem;
+import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
+import android.widget.TextView;
-public class XWalkNavigationActivity extends Activity {
+public class XWalkNavigationActivity extends XWalkBaseActivity {
private ImageButton mNextButton;
private ImageButton mPrevButton;
- private XWalkView mXWalkView;
+
+ String url, originalUrl, title;
+ TextView text1, text2, text3;
@Override
protected void onCreate(Bundle savedInstanceState) {
mNextButton = (ImageButton) findViewById(R.id.next);
mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+ text1 = (TextView) super.findViewById(R.id.text1);
+ text2 = (TextView) super.findViewById(R.id.text2);
+ text3 = (TextView) super.findViewById(R.id.text3);
+
mPrevButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mXWalkView.getNavigationHistory().navigate(
XWalkNavigationHistory.Direction.BACKWARD, 1);
}
+ XWalkNavigationItem navigationItem = mXWalkView.getNavigationHistory().getCurrentItem();
+ showNavigationItemInfo(navigationItem);
}
});
mXWalkView.getNavigationHistory().navigate(
XWalkNavigationHistory.Direction.FORWARD, 1);
}
+ XWalkNavigationItem navigationItem = mXWalkView.getNavigationHistory().getCurrentItem();
+ showNavigationItemInfo(navigationItem);
}
});
mXWalkView.load("http://www.baidu.com/", null);
}
+
+ private void showNavigationItemInfo(XWalkNavigationItem navigationItem){
+ url = navigationItem.getUrl();
+ originalUrl = navigationItem.getOriginalUrl();
+ title = navigationItem.getTitle();
+
+ text1.setText(title);
+ text2.setText(url);
+ text3.setText(originalUrl);
+ }
}
import org.xwalk.core.XWalkPreferences;
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
-public class XWalkPreferencesActivity extends Activity {
+public class XWalkPreferencesActivity extends XWalkBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xwview_layout);
- XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
+ mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
// Enable remote debugging.
// You can debug the web content via PC chrome.
XWalkPreferences.setValue(XWalkPreferences.REMOTE_DEBUGGING, true);
- xwalkView.load("http://www.baidu.com/", null);
+ mXWalkView.load("http://www.baidu.com/", null);
}
}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.sample;
+
+import org.xwalk.core.XWalkView;
+
+import android.os.Bundle;
+import android.widget.TextView;
+
+public class XWalkVersionAndAPIVersion extends XWalkBaseActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.version_layout);
+ mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+ String apiVersion = mXWalkView.getAPIVersion();
+ String xwalkVersion = mXWalkView.getXWalkVersion();
+ TextView text1 = (TextView) super.findViewById(R.id.text1);
+ text1.setText("API Version: " + apiVersion + "; XWalk Version: " + xwalkVersion);
+ mXWalkView.load("", "");
+ }
+}
import org.xwalk.core.XWalkView;
-import android.app.Activity;
import android.os.Bundle;
-public class XWalkViewWithLayoutActivity extends Activity {
+public class XWalkViewWithLayoutActivity extends XWalkBaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.xwview_layout);
- XWalkView xwalkView = (XWalkView) findViewById(R.id.xwalkview);
- xwalkView.load("http://www.baidu.com/", null);
+ mXWalkView = (XWalkView) findViewById(R.id.xwalkview);
+ mXWalkView.load("http://www.baidu.com/", null);
}
}
#include "xwalk/runtime/common/xwalk_paths.h"
#include "xwalk/runtime/renderer/xwalk_content_renderer_client.h"
+#if !defined(DISABLE_NACL) && defined(OS_LINUX)
+#include "components/nacl/common/nacl_paths.h"
+#include "components/nacl/zygote/nacl_fork_delegate_linux.h"
+#endif
+
#if defined(OS_TIZEN)
#include "xwalk/runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h"
#endif
if (process_type.empty())
SetTaskbarGroupIdForProcess();
#endif
+
+#if !defined(DISABLE_NACL) && defined(OS_LINUX)
+ nacl::RegisterPathProvider();
+#endif
+
return false;
}
return -1;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+content::ZygoteForkDelegate* XWalkMainDelegate::ZygoteStarting() {
+#if defined(DISABLE_NACL)
+ return NULL;
+#else
+ return new NaClForkDelegate();
+#endif
+}
+
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID)
+
// static
void XWalkMainDelegate::InitializeResourceBundle() {
base::FilePath pak_file;
virtual void PreSandboxStartup() OVERRIDE;
virtual int RunProcess(const std::string& process_type,
const content::MainFunctionParams& main_function_params) OVERRIDE;
+#if defined(OS_POSIX) && !defined(OS_ANDROID)
+ virtual content::ZygoteForkDelegate* ZygoteStarting();
+#endif
virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
virtual content::ContentRendererClient*
CreateContentRendererClient() OVERRIDE;
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/nacl_host/nacl_browser_delegate_impl.h"
+
+#include "base/path_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "ppapi/c/private/ppb_nacl_private.h"
+#include "xwalk/runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h"
+#include "xwalk/runtime/common/xwalk_paths.h"
+
+namespace {
+
+// Calls OnKeepaliveOnUIThread on UI thread.
+void OnKeepalive(
+ const content::BrowserPpapiHost::OnKeepaliveInstanceData& instance_data,
+ const base::FilePath& profile_data_directory) {
+ DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+}
+
+} // namespace
+
+NaClBrowserDelegateImpl::NaClBrowserDelegateImpl() {
+}
+
+NaClBrowserDelegateImpl::~NaClBrowserDelegateImpl() {
+}
+
+void NaClBrowserDelegateImpl::ShowMissingArchInfobar(int render_process_id,
+ int render_view_id) {
+}
+
+bool NaClBrowserDelegateImpl::DialogsAreSuppressed() {
+ return true;
+}
+
+bool NaClBrowserDelegateImpl::GetCacheDirectory(base::FilePath* cache_dir) {
+ return PathService::Get(xwalk::DIR_DATA_PATH, cache_dir);
+}
+
+bool NaClBrowserDelegateImpl::GetPluginDirectory(base::FilePath* plugin_dir) {
+ return PathService::Get(xwalk::DIR_INTERNAL_PLUGINS, plugin_dir);
+}
+
+bool NaClBrowserDelegateImpl::GetPnaclDirectory(base::FilePath* pnacl_dir) {
+ return PathService::Get(xwalk::DIR_PNACL_COMPONENT, pnacl_dir);
+}
+
+bool NaClBrowserDelegateImpl::GetUserDirectory(base::FilePath* user_dir) {
+ return PathService::Get(xwalk::DIR_DATA_PATH, user_dir);
+}
+
+std::string NaClBrowserDelegateImpl::GetVersionString() const {
+ return "Chrome/" CHROME_VERSION " Crosswalk/" XWALK_VERSION;
+}
+
+ppapi::host::HostFactory* NaClBrowserDelegateImpl::CreatePpapiHostFactory(
+ content::BrowserPpapiHost* ppapi_host) {
+ return new xwalk::XWalkBrowserPepperHostFactory(ppapi_host);
+}
+
+void NaClBrowserDelegateImpl::SetDebugPatterns(std::string debug_patterns) {
+}
+
+bool NaClBrowserDelegateImpl::URLMatchesDebugPatterns(
+ const GURL& manifest_url) {
+ return false;
+}
+
+// This function is security sensitive. Be sure to check with a security
+// person before you modify it.
+bool NaClBrowserDelegateImpl::MapUrlToLocalFilePath(
+ const GURL& file_url, bool use_blocking_api, base::FilePath* file_path) {
+ return false;
+}
+
+content::BrowserPpapiHost::OnKeepaliveCallback
+NaClBrowserDelegateImpl::GetOnKeepaliveCallback() {
+ return base::Bind(&OnKeepalive);
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_NACL_HOST_NACL_BROWSER_DELEGATE_IMPL_H_
+#define XWALK_RUNTIME_BROWSER_NACL_HOST_NACL_BROWSER_DELEGATE_IMPL_H_
+
+#include <string>
+
+#include "components/nacl/browser/nacl_browser_delegate.h"
+
+class NaClBrowserDelegateImpl : public NaClBrowserDelegate {
+ public:
+ NaClBrowserDelegateImpl();
+ virtual ~NaClBrowserDelegateImpl();
+
+ virtual void ShowMissingArchInfobar(int render_process_id,
+ int render_view_id) OVERRIDE;
+ virtual bool DialogsAreSuppressed() OVERRIDE;
+ virtual bool GetCacheDirectory(base::FilePath* cache_dir) OVERRIDE;
+ virtual bool GetPluginDirectory(base::FilePath* plugin_dir) OVERRIDE;
+ virtual bool GetPnaclDirectory(base::FilePath* pnacl_dir) OVERRIDE;
+ virtual bool GetUserDirectory(base::FilePath* user_dir) OVERRIDE;
+ virtual std::string GetVersionString() const OVERRIDE;
+ virtual ppapi::host::HostFactory* CreatePpapiHostFactory(
+ content::BrowserPpapiHost* ppapi_host) OVERRIDE;
+ virtual bool MapUrlToLocalFilePath(const GURL& url,
+ bool is_blocking,
+ base::FilePath* file_path) OVERRIDE;
+ virtual void SetDebugPatterns(std::string debug_patterns) OVERRIDE;
+ virtual bool URLMatchesDebugPatterns(const GURL& manifest_url) OVERRIDE;
+ virtual content::BrowserPpapiHost::OnKeepaliveCallback
+ GetOnKeepaliveCallback() OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NaClBrowserDelegateImpl);
+};
+
+#endif // XWALK_RUNTIME_BROWSER_NACL_HOST_NACL_BROWSER_DELEGATE_IMPL_H_
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h"
+
+#include "content/public/browser/browser_ppapi_host.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/host/resource_host.h"
+
+using ppapi::host::ResourceHost;
+
+namespace xwalk {
+
+XWalkBrowserPepperHostFactory::XWalkBrowserPepperHostFactory(
+ content::BrowserPpapiHost* host)
+ : host_(host) {
+}
+
+XWalkBrowserPepperHostFactory::~XWalkBrowserPepperHostFactory() {
+}
+
+scoped_ptr<ResourceHost> XWalkBrowserPepperHostFactory::CreateResourceHost(
+ ppapi::host::PpapiHost* host,
+ const ppapi::proxy::ResourceMessageCallParams& params,
+ PP_Instance instance,
+ const IPC::Message& message) {
+ DCHECK(host == host_->GetPpapiHost());
+
+ return scoped_ptr<ResourceHost>();
+}
+
+} // namespace xwalk
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_BROWSER_RENDERER_HOST_PEPPER_XWALK_BROWSER_PEPPER_HOST_FACTORY_H_
+#define XWALK_RUNTIME_BROWSER_RENDERER_HOST_PEPPER_XWALK_BROWSER_PEPPER_HOST_FACTORY_H_
+
+#include "ppapi/host/host_factory.h"
+
+namespace content {
+class BrowserPpapiHost;
+} // namespace content
+
+namespace xwalk {
+
+class XWalkBrowserPepperHostFactory : public ppapi::host::HostFactory {
+ public:
+ // Non-owning pointer to the filter must outlive this class.
+ explicit XWalkBrowserPepperHostFactory(content::BrowserPpapiHost* host);
+ virtual ~XWalkBrowserPepperHostFactory();
+
+ virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ ppapi::host::PpapiHost* host,
+ const ppapi::proxy::ResourceMessageCallParams& params,
+ PP_Instance instance,
+ const IPC::Message& message) OVERRIDE;
+
+ private:
+ // Non-owning pointer.
+ content::BrowserPpapiHost* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(XWalkBrowserPepperHostFactory);
+};
+
+} // namespace xwalk
+
+#endif // XWALK_RUNTIME_BROWSER_RENDERER_HOST_PEPPER_XWALK_BROWSER_PEPPER_HOST_FACTORY_H_
delete this;
}
-NativeAppWindow* Runtime::window() const {
- return window_;
+content::RenderProcessHost* Runtime::GetRenderProcessHost() {
+ return web_contents_->GetRenderProcessHost();
}
//////////////////////////////////////////////////////
class ColorChooser;
struct FileChooserParams;
class WebContents;
+class RenderProcessHost;
}
namespace xwalk {
void Close();
content::WebContents* web_contents() const { return web_contents_.get(); }
- NativeAppWindow* window() const;
+ NativeAppWindow* window() const { return window_; }
RuntimeContext* runtime_context() const { return runtime_context_; }
gfx::Image app_icon() const { return app_icon_; }
+ content::RenderProcessHost* GetRenderProcessHost();
+
#if defined(OS_TIZEN_MOBILE)
void CloseRootWindow();
#endif
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/worker_pool.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cookie_store_factory.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "net/cert/cert_verifier.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_storage.h"
#include "net/url_request/url_request_job_factory_impl.h"
+#include "xwalk/application/common/constants.h"
#include "xwalk/runtime/browser/runtime_network_delegate.h"
#if defined(OS_ANDROID)
#if defined(OS_ANDROID)
storage_->set_cookie_store(xwalk::GetCookieMonster());
#else
- storage_->set_cookie_store(new net::CookieMonster(NULL, NULL));
+ content::CookieStoreConfig cookie_config(base_path_.Append(
+ application::kCookieDatabaseFilename),
+ content::CookieStoreConfig::PERSISTANT_SESSION_COOKIES,
+ NULL, NULL);
+ net::CookieStore* cookie_store = content::CreateCookieStore(cookie_config);
+ const char* schemes[] = {application::kApplicationScheme,
+ content::kChromeDevToolsScheme};
+ cookie_store->GetCookieMonster()->SetCookieableSchemes(schemes, 2);
+ storage_->set_cookie_store(cookie_store);
#endif
storage_->set_server_bound_cert_service(new net::ServerBoundCertService(
new net::DefaultServerBoundCertStore(NULL),
#include "base/files/file_path.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
+#include "cc/base/switches.h"
+#include "components/nacl/browser/nacl_browser.h"
+#include "components/nacl/browser/nacl_process_host.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/main_function_params.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/common/result_codes.h"
+#include "extensions/browser/extension_system.h"
+#include "net/base/net_util.h"
+#include "ui/gl/gl_switches.h"
#include "xwalk/application/browser/application.h"
#include "xwalk/application/browser/application_system.h"
#include "xwalk/extensions/browser/xwalk_extension_service.h"
#include "xwalk/extensions/common/xwalk_extension_switches.h"
#include "xwalk/runtime/browser/devtools/remote_debugging_server.h"
+#include "xwalk/runtime/browser/nacl_host/nacl_browser_delegate_impl.h"
#include "xwalk/runtime/browser/runtime.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/browser/xwalk_runner.h"
#include "xwalk/runtime/common/xwalk_runtime_features.h"
#include "xwalk/runtime/common/xwalk_switches.h"
-#include "cc/base/switches.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/main_function_params.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/common/result_codes.h"
-#include "net/base/net_util.h"
-#include "ui/gl/gl_switches.h"
#if defined(USE_AURA) && defined(USE_X11)
#include "ui/base/ime/input_method_initializer.h"
if (extension_service_)
RegisterExternalExtensions();
+#if !defined(DISABLE_NACL)
+ NaClBrowserDelegateImpl* delegate = new NaClBrowserDelegateImpl();
+ nacl::NaClBrowser::SetDelegate(delegate);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(nacl::NaClProcessHost::EarlyStartup));
+#endif
+
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kRemoteDebuggingPort)) {
std::string port_str =
#include "base/command_line.h"
#include "base/path_service.h"
#include "base/platform_file.h"
+#include "content/public/browser/browser_child_process_host.h"
#include "content/public/browser/browser_main_parts.h"
+#include "content/public/browser/browser_ppapi_host.h"
+#include "content/public/browser/child_process_data.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/show_desktop_notification_params.h"
+#include "components/nacl/browser/nacl_browser.h"
+#include "components/nacl/browser/nacl_host_message_filter.h"
+#include "components/nacl/browser/nacl_process_host.h"
+#include "components/nacl/common/nacl_process_type.h"
#include "net/ssl/ssl_info.h"
#include "net/url_request/url_request_context_getter.h"
+#include "ppapi/host/ppapi_host.h"
#include "xwalk/extensions/common/xwalk_extension_switches.h"
#include "xwalk/runtime/browser/xwalk_browser_main_parts.h"
#include "xwalk/runtime/browser/geolocation/xwalk_access_token_store.h"
#include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
+#include "xwalk/runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h"
#include "xwalk/runtime/browser/runtime_context.h"
#include "xwalk/runtime/browser/runtime_quota_permission_context.h"
#include "xwalk/runtime/browser/speech/speech_recognition_manager_delegate.h"
#include "xwalk/runtime/browser/xwalk_render_message_filter.h"
#include "xwalk/runtime/browser/xwalk_runner.h"
+#include "xwalk/runtime/common/xwalk_paths.h"
#if defined(OS_ANDROID)
#include "base/android/path_utils.h"
#include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
#endif
+using content::BrowserChildProcessHostIterator;
+
namespace xwalk {
namespace {
void XWalkContentBrowserClient::RenderProcessWillLaunch(
content::RenderProcessHost* host) {
+#if !defined(DISABLE_NACL)
+ int id = host->GetID();
+ net::URLRequestContextGetter* context =
+ host->GetStoragePartition()->GetURLRequestContext();
+
+ host->AddFilter(new nacl::NaClHostMessageFilter(
+ id,
+ // TODO(Halton): IsOffTheRecord?
+ false,
+ host->GetBrowserContext()->GetPath(),
+ context));
+#endif
xwalk_runner_->OnRenderProcessWillLaunch(host);
host->AddFilter(new XWalkRenderMessageFilter);
}
#endif
}
+void XWalkContentBrowserClient::DidCreatePpapiPlugin(
+ content::BrowserPpapiHost* browser_host) {
+#if defined(ENABLE_PLUGINS)
+ browser_host->GetPpapiHost()->AddHostFactoryFilter(
+ scoped_ptr<ppapi::host::HostFactory>(
+ new XWalkBrowserPepperHostFactory(browser_host)));
+#endif
+}
+
+content::BrowserPpapiHost*
+ XWalkContentBrowserClient::GetExternalBrowserPpapiHost(
+ int plugin_process_id) {
+#if !defined(DISABLE_NACL)
+ BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_LOADER);
+ while (!iter.Done()) {
+ nacl::NaClProcessHost* host = static_cast<nacl::NaClProcessHost*>(
+ iter.GetDelegate());
+ if (host->process() &&
+ host->process()->GetData().id == plugin_process_id) {
+ // Found the plugin.
+ return host->browser_ppapi_host();
+ }
+ ++iter;
+ }
+#endif
+ return NULL;
+}
+
#if defined(OS_ANDROID)
void XWalkContentBrowserClient::ResourceDispatcherHostCreated() {
RuntimeResourceDispatcherHostDelegateAndroid::
bool* no_javascript_access) OVERRIDE;
#endif
+ virtual void DidCreatePpapiPlugin(
+ content::BrowserPpapiHost* browser_host) OVERRIDE;
+ virtual content::BrowserPpapiHost* GetExternalBrowserPpapiHost(
+ int plugin_process_id) OVERRIDE;
+
#if defined(OS_ANDROID)
virtual void ResourceDispatcherHostCreated();
#endif
#if defined(OS_TIZEN)
void OnOpenLinkExternal(const GURL& url);
#endif
+ virtual ~XWalkRenderMessageFilter() {}
DISALLOW_COPY_AND_ASSIGN(XWalkRenderMessageFilter);
};
#include "xwalk/runtime/common/xwalk_content_client.h"
#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/nacl/common/nacl_process_type.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/user_agent.h"
+#include "content/public/common/pepper_plugin_info.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "xwalk/application/common/constants.h"
+#include "xwalk/runtime/common/xwalk_switches.h"
+#include "xwalk/runtime/common/xwalk_paths.h"
+
+const char* const xwalk::XWalkContentClient::kNaClPluginName = "Native Client";
+
+namespace {
+
+const char kNaClPluginMimeType[] = "application/x-nacl";
+const char kNaClPluginExtension[] = "";
+const char kNaClPluginDescription[] = "Native Client Executable";
+const uint32 kNaClPluginPermissions = ppapi::PERMISSION_PRIVATE |
+ ppapi::PERMISSION_DEV;
+
+const char kPnaclPluginMimeType[] = "application/x-pnacl";
+const char kPnaclPluginExtension[] = "";
+const char kPnaclPluginDescription[] = "Portable Native Client Executable";
+
+} // namespace
namespace xwalk {
xwalk::GetUserAgent();
}
+void XWalkContentClient::AddPepperPlugins(
+ std::vector<content::PepperPluginInfo>* plugins) {
+ // Handle Native Client just like the PDF plugin. This means that it is
+ // enabled by default for the non-portable case. This allows apps installed
+ // from the Chrome Web Store to use NaCl even if the command line switch
+ // isn't set. For other uses of NaCl we check for the command line switch.
+ // Specifically, Portable Native Client is only enabled by the command line
+ // switch.
+ static bool skip_nacl_file_check = false;
+ base::FilePath path;
+ if (PathService::Get(xwalk::FILE_NACL_PLUGIN, &path)) {
+ if (skip_nacl_file_check || base::PathExists(path)) {
+ content::PepperPluginInfo nacl;
+ nacl.path = path;
+ nacl.name = XWalkContentClient::kNaClPluginName;
+ content::WebPluginMimeType nacl_mime_type(kNaClPluginMimeType,
+ kNaClPluginExtension,
+ kNaClPluginDescription);
+ nacl.mime_types.push_back(nacl_mime_type);
+ if (!CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisablePnacl)) {
+ content::WebPluginMimeType pnacl_mime_type(kPnaclPluginMimeType,
+ kPnaclPluginExtension,
+ kPnaclPluginDescription);
+ nacl.mime_types.push_back(pnacl_mime_type);
+ }
+ nacl.permissions = kNaClPluginPermissions;
+ plugins->push_back(nacl);
+
+ skip_nacl_file_check = true;
+ }
+ }
+}
+
std::string XWalkContentClient::GetProduct() const {
return std::string("Version/4.0");
}
savable_schemes->push_back(application::kApplicationScheme);
}
+std::string XWalkContentClient::GetProcessTypeNameInEnglish(int type) {
+ switch (type) {
+ case PROCESS_TYPE_NACL_LOADER:
+ return "Native Client module";
+ case PROCESS_TYPE_NACL_BROKER:
+ return "Native Client broker";
+ }
+
+ DCHECK(false) << "Unknown child process type!";
+ return "Unknown";
+}
+
} // namespace xwalk
XWalkContentClient();
virtual ~XWalkContentClient();
+ static const char* const kNaClPluginName;
+
+ virtual void AddPepperPlugins(
+ std::vector<content::PepperPluginInfo>* plugins) OVERRIDE;
virtual std::string GetProduct() const OVERRIDE;
virtual std::string GetUserAgent() const OVERRIDE;
virtual base::string16 GetLocalizedString(int message_id) const OVERRIDE;
virtual void AddAdditionalSchemes(
std::vector<std::string>* standard_schemes,
std::vector<std::string>* saveable_shemes) OVERRIDE;
+ virtual std::string GetProcessTypeNameInEnglish(int type) OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(XWalkContentClient);
#elif defined(OS_LINUX)
#include "base/environment.h"
#include "base/nix/xdg_util.h"
+#elif defined(OS_MACOSX) && !defined(OS_IOS)
+#import "base/mac/mac_util.h"
#endif
namespace xwalk {
namespace {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+
+base::FilePath GetVersionedDirectory() {
+ // Start out with the path to the running executable.
+ base::FilePath path;
+ PathService::Get(base::FILE_EXE, &path);
+
+ // One step up to MacOS, another to Contents.
+ path = path.DirName().DirName();
+ DCHECK_EQ(path.BaseName().value(), "Contents");
+
+ if (base::mac::IsBackgroundOnlyProcess()) {
+ // path identifies the helper .app's Contents directory in the browser
+ // .app's versioned directory. Go up two steps to get to the browser
+ // .app's versioned directory.
+ path = path.DirName().DirName();
+ }
+
+ return path;
+}
+
+base::FilePath GetFrameworkBundlePath() {
+ // It's tempting to use +[NSBundle bundleWithIdentifier:], but it's really
+ // slow (about 30ms on 10.5 and 10.6), despite Apple's documentation stating
+ // that it may be more efficient than +bundleForClass:. +bundleForClass:
+ // itself takes 1-2ms. Getting an NSBundle from a path, on the other hand,
+ // essentially takes no time at all, at least when the bundle has already
+ // been loaded as it will have been in this case. The FilePath operations
+ // needed to compute the framework's path are also effectively free, so that
+ // is the approach that is used here. NSBundle is also documented as being
+ // not thread-safe, and thread safety may be a concern here.
+
+ // The framework bundle is at a known path and name from the browser .app's
+ // versioned directory.
+ return GetVersionedDirectory().Append("XWalk");
+}
+#endif
+
+// File name of the internal NaCl plugin on different platforms.
+const base::FilePath::CharType kInternalNaClPluginFileName[] =
+#if defined(OS_WIN)
+ FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.dll");
+#elif defined(OS_MACOSX)
+ // TODO(noelallen) Please verify this extention name is correct.
+ FILE_PATH_LITERAL("ppGoogleNaClPluginChrome.plugin");
+#else // Linux and Chrome OS
+ FILE_PATH_LITERAL("libppGoogleNaClPluginChrome.so");
+#endif
+
#if defined(OS_LINUX)
base::FilePath GetConfigPath() {
scoped_ptr<base::Environment> env(base::Environment::Create());
return true;
}
+bool GetInternalPluginsDirectory(base::FilePath* result) {
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+ // If called from Chrome, get internal plugins from a subdirectory of the
+ // framework.
+ if (base::mac::AmIBundled()) {
+ *result = xwalk::GetFrameworkBundlePath();
+ DCHECK(!result->empty());
+ *result = result->Append("Internet Plug-Ins");
+ return true;
+ }
+ // In tests, just look in the module directory (below).
+#endif
+
+ // The rest of the world expects plugins in the module directory.
+ return PathService::Get(base::DIR_MODULE, result);
+}
+
} // namespace
bool PathProvider(int key, base::FilePath* path) {
switch (key) {
case xwalk::DIR_DATA_PATH:
return GetXWalkDataPath(path);
+ break;
+ case xwalk::DIR_INTERNAL_PLUGINS:
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+ break;
+ case xwalk::FILE_NACL_PLUGIN:
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+ cur = cur.Append(kInternalNaClPluginFileName);
+ break;
+ // Where PNaCl files are ultimately located. The default finds the files
+ // inside the InternalPluginsDirectory / build directory, as if it
+ // was shipped along with xwalk. The value can be overridden
+ // if it is installed via component updater.
+ case xwalk::DIR_PNACL_COMPONENT:
+#if defined(OS_MACOSX)
+ // PNaCl really belongs in the InternalPluginsDirectory but actually
+ // copying it there would result in the files also being shipped, which
+ // we don't want yet. So for now, just find them in the directory where
+ // they get built.
+ if (!PathService::Get(base::DIR_EXE, &cur))
+ return false;
+ if (base::mac::AmIBundled()) {
+ // If we're called from xwalk, it's beside the app (outside the
+ // app bundle), if we're called from a unittest, we'll already be
+ // outside the bundle so use the exe dir.
+ // exe_dir gave us .../Chromium.app/Contents/MacOS/Chromium.
+ cur = cur.DirName();
+ cur = cur.DirName();
+ cur = cur.DirName();
+ }
+#else
+ if (!GetInternalPluginsDirectory(&cur))
+ return false;
+#endif
+ cur = cur.Append(FILE_PATH_LITERAL("pnacl"));
+ break;
case xwalk::DIR_TEST_DATA:
if (!PathService::Get(base::DIR_SOURCE_ROOT, &cur))
return false;
}
} // namespace xwalk
-
PATH_START = 1000,
DIR_DATA_PATH = PATH_START, // Directory where the cache and local storage
// data resides.
+ DIR_INTERNAL_PLUGINS, // Directory where internal plugins reside.
+
+ FILE_NACL_PLUGIN, // Full path to the internal NaCl plugin file.
+ DIR_PNACL_COMPONENT, // Full path to the latest PNaCl version
+ // (subdir of DIR_PNACL_BASE).
DIR_TEST_DATA, // Directory where unit test data resides.
DIR_WGT_STORAGE_PATH, // Directory where widget storage data resides.
PATH_END
namespace switches {
-// Specifies the data path directory, which XWalk runtime will look for its
-// state, e.g. cache, localStorage etc.
-const char kXWalkDataPath[] = "data-path";
-
// Specifies the icon file for the app window.
const char kAppIcon[] = "app-icon";
+// Disables the usage of Portable Native Client.
+const char kDisablePnacl[] = "disable-pnacl";
+
+// Enable all the experimental features in XWalk.
+const char kExperimentalFeatures[] = "enable-xwalk-experimental-features";
+
// Specifies the window whether launched with fullscreen mode.
const char kFullscreen[] = "fullscreen";
+// Specifies install an application.
+const char kInstall[] = "install";
+
// Specifies list all installed applications.
const char kListApplications[] = "list-apps";
-// Specifies install an application.
-const char kInstall[] = "install";
+// List the command lines feature flags.
+const char kListFeaturesFlags[] = "list-features-flags";
// Specifies uninstall an application from runtime.
const char kUninstall[] = "uninstall";
// issue these requests is platform-specific.
const char kXWalkRunAsService[] = "run-as-service";
-// List the command lines feature flags.
-const char kListFeaturesFlags[] = "list-features-flags";
-
-// Enable all the experimental features in XWalk.
-const char kExperimentalFeatures[] = "enable-xwalk-experimental-features";
+// Specifies the data path directory, which XWalk runtime will look for its
+// state, e.g. cache, localStorage etc.
+const char kXWalkDataPath[] = "data-path";
} // namespace switches
// Defines all command line switches for XWalk.
namespace switches {
-extern const char kXWalkDataPath[];
-
extern const char kAppIcon[];
-
+extern const char kDisablePnacl[];
+extern const char kExperimentalFeatures[];
extern const char kFullscreen[];
-
extern const char kInstall[];
-
extern const char kListApplications[];
-
+extern const char kListFeaturesFlags[];
extern const char kUninstall[];
-
extern const char kXWalkAllowExternalExtensionsForRemoteSources[];
-
+extern const char kXWalkDataPath[];
extern const char kXWalkRunAsService[];
-extern const char kListFeaturesFlags[];
-
-extern const char kExperimentalFeatures[];
-
} // namespace switches
#endif // XWALK_RUNTIME_COMMON_XWALK_SWITCHES_H_
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/renderer/pepper/pepper_helper.h"
+
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/host/ppapi_host.h"
+#include "xwalk/runtime/renderer/pepper/xwalk_renderer_pepper_host_factory.h"
+
+PepperHelper::PepperHelper(content::RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {
+}
+
+PepperHelper::~PepperHelper() {
+}
+
+void PepperHelper::DidCreatePepperPlugin(content::RendererPpapiHost* host) {
+ host->GetPpapiHost()->AddHostFactoryFilter(
+ scoped_ptr<ppapi::host::HostFactory>(
+ new XWalkRendererPepperHostFactory(host)));
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_HELPER_H_
+#define XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_HELPER_H_
+
+#include "base/compiler_specific.h"
+#include "content/public/renderer/render_frame_observer.h"
+
+// This class listens for Pepper creation events from the RenderFrame and
+// attaches the parts required for Chrome-specific plugin support.
+class PepperHelper : public content::RenderFrameObserver {
+ public:
+ explicit PepperHelper(content::RenderFrame* render_frame);
+ virtual ~PepperHelper();
+
+ // RenderFrameObserver.
+ virtual void DidCreatePepperPlugin(content::RendererPpapiHost* host) OVERRIDE;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PepperHelper);
+};
+
+#endif // XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_HELPER_H_
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/renderer/pepper/pepper_uma_host.h"
+
+#include "base/metrics/histogram.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/host/dispatch_host_message.h"
+#include "ppapi/host/ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+PepperUMAHost::PepperUMAHost(
+ content::RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource)
+ : ResourceHost(host->GetPpapiHost(), instance, resource),
+ document_url_(host->GetDocumentURL(instance)),
+ is_plugin_in_process_(host->IsRunningInProcess()) {
+}
+
+PepperUMAHost::~PepperUMAHost() {
+}
+
+int32_t PepperUMAHost::OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) {
+ IPC_BEGIN_MESSAGE_MAP(PepperUMAHost, msg)
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomTimes,
+ OnHistogramCustomTimes);
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramCustomCounts,
+ OnHistogramCustomCounts);
+ PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration,
+ OnHistogramEnumeration);
+ IPC_END_MESSAGE_MAP()
+ return PP_ERROR_FAILED;
+}
+
+bool PepperUMAHost::IsHistogramAllowed(const std::string& histogram) {
+ return (is_plugin_in_process_ && histogram.find("NaCl.") == 0);
+}
+
+#define RETURN_IF_BAD_ARGS(_min, _max, _buckets) \
+ do { \
+ if (_min >= _max || _buckets <= 1) \
+ return PP_ERROR_BADARGUMENT; \
+ } while (0)
+
+int32_t PepperUMAHost::OnHistogramCustomTimes(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int64_t sample,
+ int64_t min,
+ int64_t max,
+ uint32_t bucket_count) {
+ if (!IsHistogramAllowed(name)) {
+ return PP_ERROR_NOACCESS;
+ }
+ RETURN_IF_BAD_ARGS(min, max, bucket_count);
+
+ base::HistogramBase* counter =
+ base::Histogram::FactoryTimeGet(
+ name,
+ base::TimeDelta::FromMilliseconds(min),
+ base::TimeDelta::FromMilliseconds(max),
+ bucket_count,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ counter->AddTime(base::TimeDelta::FromMilliseconds(sample));
+ return PP_OK;
+}
+
+int32_t PepperUMAHost::OnHistogramCustomCounts(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int32_t sample,
+ int32_t min,
+ int32_t max,
+ uint32_t bucket_count) {
+ if (!IsHistogramAllowed(name)) {
+ return PP_ERROR_NOACCESS;
+ }
+ RETURN_IF_BAD_ARGS(min, max, bucket_count);
+
+ base::HistogramBase* counter =
+ base::Histogram::FactoryGet(
+ name,
+ min,
+ max,
+ bucket_count,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ counter->Add(sample);
+ return PP_OK;
+}
+
+int32_t PepperUMAHost::OnHistogramEnumeration(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int32_t sample,
+ int32_t boundary_value) {
+ if (!IsHistogramAllowed(name)) {
+ return PP_ERROR_NOACCESS;
+ }
+ RETURN_IF_BAD_ARGS(0, boundary_value, boundary_value + 1);
+
+ base::HistogramBase* counter =
+ base::LinearHistogram::FactoryGet(
+ name,
+ 1,
+ boundary_value,
+ boundary_value + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ counter->Add(sample);
+ return PP_OK;
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_UMA_HOST_H_
+#define XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_UMA_HOST_H_
+
+#include <set>
+#include <string>
+
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_resource.h"
+#include "ppapi/host/resource_host.h"
+#include "url/gurl.h"
+
+namespace content {
+class RendererPpapiHost;
+}
+
+namespace ppapi {
+namespace host {
+struct HostMessageContext;
+} // namespace host
+} // namespace ppapi
+
+class PepperUMAHost : public ppapi::host::ResourceHost {
+ public:
+ PepperUMAHost(content::RendererPpapiHost* host,
+ PP_Instance instance,
+ PP_Resource resource);
+
+ virtual ~PepperUMAHost();
+
+ // ppapi::host::ResourceMessageHandler implementation.
+ virtual int32_t OnResourceMessageReceived(
+ const IPC::Message& msg,
+ ppapi::host::HostMessageContext* context) OVERRIDE;
+
+ private:
+ bool IsHistogramAllowed(const std::string& histogram);
+
+ int32_t OnHistogramCustomTimes(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int64_t sample,
+ int64_t min,
+ int64_t max,
+ uint32_t bucket_count);
+
+ int32_t OnHistogramCustomCounts(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int32_t sample,
+ int32_t min,
+ int32_t max,
+ uint32_t bucket_count);
+
+ int32_t OnHistogramEnumeration(
+ ppapi::host::HostMessageContext* context,
+ const std::string& name,
+ int32_t sample,
+ int32_t boundary_value);
+
+ const GURL document_url_;
+ bool is_plugin_in_process_;
+
+ // Set of origins that can use UMA private APIs from NaCl.
+ std::set<std::string> allowed_origins_;
+ // Set of histograms that can be used from this interface.
+ std::set<std::string> allowed_histograms_;
+
+ DISALLOW_COPY_AND_ASSIGN(PepperUMAHost);
+};
+
+#endif // XWALK_RUNTIME_RENDERER_PEPPER_PEPPER_UMA_HOST_H_
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "xwalk/runtime/renderer/pepper/xwalk_renderer_pepper_host_factory.h"
+
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/proxy/ppapi_messages.h"
+#include "xwalk/runtime/renderer/pepper/pepper_uma_host.h"
+
+using ppapi::host::ResourceHost;
+
+XWalkRendererPepperHostFactory::XWalkRendererPepperHostFactory(
+ content::RendererPpapiHost* host)
+ : host_(host) {
+}
+
+XWalkRendererPepperHostFactory::~XWalkRendererPepperHostFactory() {
+}
+
+scoped_ptr<ResourceHost>
+XWalkRendererPepperHostFactory::CreateResourceHost(
+ ppapi::host::PpapiHost* host,
+ const ppapi::proxy::ResourceMessageCallParams& params,
+ PP_Instance instance,
+ const IPC::Message& message) {
+ DCHECK(host == host_->GetPpapiHost());
+
+ // Make sure the plugin is giving us a valid instance for this resource.
+ if (!host_->IsValidInstance(instance))
+ return scoped_ptr<ResourceHost>();
+
+ // Permissions for the following interfaces will be checked at the
+ // time of the corresponding instance's method calls. Currently these
+ // interfaces are available only for whitelisted apps which may not have
+ // access to the other private interfaces.
+ if (message.type() == PpapiHostMsg_UMA_Create::ID) {
+ return scoped_ptr<ResourceHost>(new PepperUMAHost(
+ host_, instance, params.pp_resource()));
+ }
+
+ return scoped_ptr<ResourceHost>();
+}
--- /dev/null
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef XWALK_RUNTIME_RENDERER_PEPPER_XWALK_RENDERER_PEPPER_HOST_FACTORY_H_
+#define XWALK_RUNTIME_RENDERER_PEPPER_XWALK_RENDERER_PEPPER_HOST_FACTORY_H_
+
+#include "ppapi/host/host_factory.h"
+
+namespace content {
+class RendererPpapiHost;
+}
+
+class XWalkRendererPepperHostFactory : public ppapi::host::HostFactory {
+ public:
+ explicit XWalkRendererPepperHostFactory(content::RendererPpapiHost* host);
+ virtual ~XWalkRendererPepperHostFactory();
+
+ // HostFactory.
+ virtual scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ ppapi::host::PpapiHost* host,
+ const ppapi::proxy::ResourceMessageCallParams& params,
+ PP_Instance instance,
+ const IPC::Message& message) OVERRIDE;
+
+ private:
+ // Not owned by this object.
+ content::RendererPpapiHost* host_;
+
+ DISALLOW_COPY_AND_ASSIGN(XWalkRendererPepperHostFactory);
+};
+
+#endif // XWALK_RUNTIME_RENDERER_PEPPER_XWALK_RENDERER_PEPPER_HOST_FACTORY_H_
#include "xwalk/runtime/renderer/xwalk_content_renderer_client.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/nacl/renderer/ppb_nacl_private_impl.h"
#include "components/visitedlink/renderer/visitedlink_slave.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_frame_observer.h"
#include "xwalk/application/renderer/application_native_module.h"
#include "xwalk/extensions/renderer/xwalk_js_module.h"
#include "xwalk/runtime/common/xwalk_localized_error.h"
+#include "xwalk/runtime/renderer/pepper/pepper_helper.h"
#if defined(OS_ANDROID)
#include "xwalk/runtime/renderer/android/xwalk_permission_client.h"
#if defined(OS_ANDROID)
new XWalkPermissionClient(render_frame);
#endif
+
+#if defined(ENABLE_PLUGINS)
+ new PepperHelper(render_frame);
+#endif
}
void XWalkContentRendererClient::RenderViewCreated(
IDR_XWALK_APPLICATION_WIDGET_COMMON_API));
}
+const void* XWalkContentRendererClient::CreatePPAPIInterface(
+ const std::string& interface_name) {
+#if defined(ENABLE_PLUGINS) && !defined(DISABLE_NACL)
+ if (interface_name == PPB_NACL_PRIVATE_INTERFACE)
+ return nacl::GetNaClPrivateInterface();
+#endif
+ return NULL;
+}
+
+bool XWalkContentRendererClient::IsExternalPepperPlugin(
+ const std::string& module_name) {
+ // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
+ // We must defer certain plugin events for NaCl instances since we switch
+ // from the in-process to the out-of-process proxy after instantiating them.
+ return module_name == "Native Client";
+}
+
#if defined(OS_ANDROID)
unsigned long long XWalkContentRendererClient::VisitedLinkHash( // NOLINT
const char* canonical_url, size_t length) {
if (xwalk_render_process_observer_->IsCSPMode()) {
if (url.GetOrigin() != app_url.GetOrigin() &&
origin_url != first_party_for_cookies &&
+ !first_party_for_cookies.is_empty() &&
first_party_for_cookies.GetOrigin() != app_url.GetOrigin() &&
- !frame->document().securityOrigin().canRequest(url)) {
+ !blink::WebSecurityOrigin::create(app_url).canRequest(url)) {
LOG(INFO) << "[BLOCK] allow-navigation: " << url.spec();
content::RenderThread::Get()->Send(new ViewMsg_OpenLinkExternal(url));
*new_url = GURL();
virtual void DidCreateScriptContext(
blink::WebFrame* frame, v8::Handle<v8::Context> context,
int extension_group, int world_id) OVERRIDE;
+ virtual bool IsExternalPepperPlugin(const std::string& module_name) OVERRIDE;
+ virtual const void* CreatePPAPIInterface(
+ const std::string& interface_name) OVERRIDE;
#if defined(OS_ANDROID)
virtual unsigned long long VisitedLinkHash(const char* canonical_url, // NOLINT
size_t length) OVERRIDE;
scoped_ptr<visitedlink::VisitedLinkSlave> visited_link_slave_;
#endif
- void GetNavigationErrorStrings(
+ virtual void GetNavigationErrorStrings(
content::RenderView* render_view,
blink::WebFrame* frame,
const blink::WebURLRequest& failed_request,
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+import org.xwalk.core.JavascriptInterface;
+
+/**
+ * Test suite for addJavascriptInterface().
+ */
+public class AddJavascriptInterfaceTest extends XWalkViewTestBase {
+ final String mExpectedStr = "xwalk";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
+ }
+
+ class TestJavascriptInterface {
+ public String getTextWithoutAnnotation() {
+ return mExpectedStr;
+ }
+
+ @JavascriptInterface
+ public String getText() {
+ return mExpectedStr;
+ }
+ }
+
+ private void addJavascriptInterface() {
+ getInstrumentation().runOnMainSync(new Runnable() {
+ @Override
+ public void run() {
+ getXWalkView().addJavascriptInterface(new TestJavascriptInterface(),
+ "testInterface");
+ }
+ });
+ }
+
+ private void raisesExceptionAndSetTitle(String script) throws Throwable {
+ executeJavaScriptAndWaitForResult("try { var title = " +
+ script + ";" +
+ " document.title = title;" +
+ "} catch (exception) {" +
+ " document.title = \"xwalk\";" +
+ "}");
+ }
+
+ @SmallTest
+ @Feature({"AddJavascriptInterface"})
+ public void testAddJavascriptInterface() throws Throwable {
+ final String name = "add_js_interface.html";
+
+ addJavascriptInterface();
+ loadAssetFile(name);
+ assertEquals(mExpectedStr, getTitleOnUiThread());
+ }
+
+ @SmallTest
+ @Feature({"AddJavascriptInterface"})
+ public void testAddJavascriptInterfaceWithAnnotation() throws Throwable {
+ final String name = "index.html";
+ final String xwalkStr = "\"xwalk\"";
+ String result;
+
+ addJavascriptInterface();
+ loadAssetFile(name);
+
+ result = executeJavaScriptAndWaitForResult("testInterface.getText()");
+ assertEquals(xwalkStr, result);
+
+ raisesExceptionAndSetTitle("testInterface.getTextWithoutAnnotation()");
+
+ String title = getTitleOnUiThread();
+ assertEquals(mExpectedStr, title);
+ }
+}
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for evaluateJavascript().
+ */
+public class EvaluateJavascriptTest extends XWalkViewTestBase {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
+ }
+
+ @SmallTest
+ @Feature({"EvaluateJavascript"})
+ public void testEvaluateJavascript() throws Throwable {
+ final String expectedTitle = "xwalk";
+ final String name = "index.html";
+ final String code = "document.title=\"xwalk\"";
+
+ loadAssetFile(name);
+ executeJavaScriptAndWaitForResult(code);
+ assertEquals(expectedTitle, getTitleOnUiThread());
+ }
+}
--- /dev/null
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 Intel Corporation. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.xwalk.core.xwview.test;
+
+import android.test.suitebuilder.annotation.SmallTest;
+
+import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.Feature;
+
+/**
+ * Test suite for load().
+ */
+public class LoadTest extends XWalkViewTestBase {
+ final String expectedTitle = "The WebKit Open Source Project";
+ final String expectedLocalTitle = "Crosswalk Sample Application";
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
+ }
+
+ // TODO(hengzhi): Since the device issue, it can not access the network,
+ // so disabled this test temporarily. It will be enabled later.
+ // @SmallTest
+ // @Feature({"Load"})
+ @DisabledTest
+ public void testHttpUrl() throws Throwable {
+ final String url = "http://www.webkit.org/";
+
+ loadUrlSync(url);
+ assertEquals(expectedTitle, getTitleOnUiThread());
+ }
+
+ // TODO(hengzhi): Since the device issue, it can not access the network,
+ // so disabled this test temporarily. It will be enabled later.
+ // @SmallTest
+ // @Feature({"Load"})
+ @DisabledTest
+ public void testHttpsUrl() throws Throwable {
+ final String url = "https://www.webkit.org/";
+
+ loadUrlSync(url);
+ assertEquals(expectedTitle, getTitleOnUiThread());
+ }
+
+ @SmallTest
+ @Feature({"Load"})
+ public void testAndroidAssetUrl() throws Throwable {
+ final String url = "file:///android_asset/www/index.html";
+
+ loadUrlSync(url);
+ assertEquals(expectedLocalTitle, getTitleOnUiThread());
+ }
+
+ @SmallTest
+ @Feature({"LoadWithData"})
+ public void testWithData() throws Throwable {
+ final String name = "index.html";
+ String fileContent = getFileContent(name);
+
+ loadDataSync(null, fileContent, "text/html", false);
+ assertEquals(expectedLocalTitle, getTitleOnUiThread());
+
+ loadDataSync(name, fileContent, "text/html", false);
+ assertEquals(expectedLocalTitle, getTitleOnUiThread());
+ }
+
+ @SmallTest
+ @Feature({"ContentScheme"})
+ public void testContentUrl() throws Throwable {
+ final String resource = "content_test";
+ final String contentUrl = TestContentProvider.createContentUrl(resource);
+
+ int count =
+ TestContentProvider.getResourceRequestCount(getActivity(), resource);
+ loadUrlSync(contentUrl);
+ assertEquals(count + 1,
+ TestContentProvider.getResourceRequestCount(getActivity(), resource));
+ }
+
+ @SmallTest
+ @Feature({"Load"})
+ public void testEmpytUrlAndContent() throws Throwable {
+ loadDataAsync(null, null, "text/html", false);
+ Thread.sleep(1000);
+ assertNotNull(getTitleOnUiThread());
+ }
+}
+++ /dev/null
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Copyright (c) 2013 Intel Corporation. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.xwalk.core.xwview.test;
-
-import android.graphics.Bitmap;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.util.Log;
-
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.Feature;
-
-/**
- * Test suite for loadUrl().
- */
-public class LoadUrlTest extends XWalkViewTestBase {
- @Override
- public void setUp() throws Exception {
- super.setUp();
-
- setXWalkClient(new XWalkViewTestBase.TestXWalkClient());
- }
-
- // @SmallTest
- // @Feature({"LoadUrl"})
- // TODO(hengzhi): Since the device issue, it can not access the network,
- // so disabled this test temporarily. It will be enabled later.
- @DisabledTest
- public void testNormalUrl() throws Throwable {
- final String url = "http://www.webkit.org/";
- final String expected_title = "The WebKit Open Source Project";
- loadUrlSync(url);
- assertEquals(expected_title, getTitleOnUiThread());
- }
-
- @SmallTest
- @Feature({"LoadUrl"})
- public void testLocalUrl() throws Throwable {
- final String name = "index.html";
- final String expected_title = "Crosswalk Sample Application";
-
- loadAssetFile(name);
- assertEquals(expected_title, getTitleOnUiThread());
- }
-
- @SmallTest
- @Feature({"ContentScheme"})
- public void testContentUrl() throws Throwable {
- final String resource = "content_test";
- final String content_url = TestContentProvider.createContentUrl(resource);
-
- int count_before_load =
- TestContentProvider.getResourceRequestCount(getActivity(), resource);
- loadUrlSync(content_url);
- assertEquals(count_before_load + 1,
- TestContentProvider.getResourceRequestCount(getActivity(), resource));
- }
-}
import org.chromium.content.browser.test.util.CallbackHelper;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
+
import org.xwalk.core.XWalkClient;
import org.xwalk.core.XWalkNavigationHistory;
import org.xwalk.core.XWalkResourceClient;
--- /dev/null
+<html>
+<head>
+<script type="text/javascript">
+ function setTitle()
+ {
+ document.title = testInterface.getText();
+ }
+</script>
+<title></title>
+</head>
+
+<body onload="setTitle()">
+</body>
+</html>
'filename': 'Makefile.templ',
'buildtype': ['dev', 'official'],
},
-# XPK package generator
- {
- 'filename': 'tools/make_xpk.py',
- 'buildtype': ['dev', 'official'],
- },
]
'buildtype': ['dev', 'official'],
'archive': 'xwalk-win32-syms.zip',
},
-# XPK package generator
- {
- 'filename': 'tools/make_xpk.py',
- 'buildtype': ['dev', 'official'],
- },
]
}, {
'use_custom_freetype%': 0,
}],
+ ['OS=="win" or OS=="mac"', {
+ 'disable_nacl': 1,
+ }],
], # conditions
},
'includes' : [
'runtime/browser/image_util.h',
'runtime/browser/media/media_capture_devices_dispatcher.cc',
'runtime/browser/media/media_capture_devices_dispatcher.h',
+ 'runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.cc',
+ 'runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h',
'runtime/browser/runtime.cc',
'runtime/browser/runtime.h',
'runtime/browser/runtime_context.cc',
'runtime/renderer/android/xwalk_permission_client.h',
'runtime/renderer/android/xwalk_render_view_ext.cc',
'runtime/renderer/android/xwalk_render_view_ext.h',
+ 'runtime/renderer/pepper/pepper_helper.cc',
+ 'runtime/renderer/pepper/pepper_helper.h',
+ 'runtime/renderer/pepper/pepper_uma_host.cc',
+ 'runtime/renderer/pepper/pepper_uma_host.h',
+ 'runtime/renderer/pepper/xwalk_renderer_pepper_host_factory.cc',
+ 'runtime/renderer/pepper/xwalk_renderer_pepper_host_factory.h',
'runtime/renderer/tizen/xwalk_content_renderer_client_tizen.cc',
'runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h',
'runtime/renderer/tizen/xwalk_render_view_ext_tizen.cc',
},
},
'conditions': [
- [ 'tizen == 1 or tizen_mobile == 1', {
+ ['tizen==1', {
'dependencies': [
'build/system.gyp:tizen_geolocation',
'sysapps/sysapps_resources.gyp:xwalk_sysapps_resources',
['exclude', '_aura\\.cc$'],
],
}],
+ ['disable_nacl==0', {
+ 'conditions': [
+ ['OS=="linux"', {
+ 'sources': [
+ 'runtime/browser/nacl_host/nacl_browser_delegate_impl.cc',
+ 'runtime/browser/nacl_host/nacl_browser_delegate_impl.h',
+ ],
+ 'dependencies': [
+ '../components/nacl.gyp:nacl',
+ '../components/nacl.gyp:nacl_browser',
+ '../components/nacl.gyp:nacl_common',
+ '../components/nacl.gyp:nacl_renderer',
+ '../components/nacl.gyp:nacl_helper',
+ '../native_client/src/trusted/service_runtime/linux/nacl_bootstrap.gyp:nacl_helper_bootstrap',
+ ],
+ }],
+ ],
+ }],
+ ['enable_plugins==1', {
+ 'dependencies': [
+ '../ppapi/ppapi_internal.gyp:ppapi_host',
+ '../ppapi/ppapi_internal.gyp:ppapi_proxy',
+ '../ppapi/ppapi_internal.gyp:ppapi_ipc',
+ '../ppapi/ppapi_internal.gyp:ppapi_shared',
+ ],
+ }, { # enable_plugins==0
+ 'sources/': [
+ ['exclude', '^runtime/browser/renderer_host/pepper/'],
+ ['exclude', '^runtime/renderer/pepper/'],
+ ],
+ }],
],
},
{
'dependencies': [
'xwalk',
'xwalk_all_tests',
- 'xwalk_xpk_generator',
],
},
{
'xwalk_runtime_lib_apk',
'xwalk_app_hello_world_apk',
'xwalk_app_template',
+ 'xwalk_core_sample_apk'
],
}],
],
},
- {
- 'target_name': 'xwalk_xpk_generator',
- 'type': 'none',
- 'copies': [
- {
- 'destination': '<(PRODUCT_DIR)/tools',
- 'files': [
- 'tools/make_xpk.py',
- ],
- },
- ],
- },
], # targets
'conditions': [
['OS=="linux"', {
'java_in_dir': 'test/android/core/javatests',
'is_test_apk': 1,
'additional_input_paths': [
+ '<(PRODUCT_DIR)/xwalk_xwview_test/assets/add_js_interface.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/broadcast.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/echo.html',
'<(PRODUCT_DIR)/xwalk_xwview_test/assets/echoSync.html',
{
'destination': '<(PRODUCT_DIR)/xwalk_xwview_test/assets',
'files': [
+ 'test/android/data/add_js_interface.html',
'test/android/data/broadcast.html',
'test/android/data/echo.html',
'test/android/data/echoSync.html',
'apk_name': 'XWalkRuntimeClientShell',
'java_in_dir': 'app/android/runtime_client_shell',
'resource_dir': 'app/android/runtime_client_shell/res',
+ 'is_test_apk': 1,
'additional_input_paths': [
'<(PRODUCT_DIR)/runtime_client_shell/assets/extensions-config.json',
'<(PRODUCT_DIR)/runtime_client_shell/assets/index.html',
'../skia/skia.gyp:skia',
],
}],
- ['tizen == 1 or tizen_mobile == 1', {
+ ['tizen==1', {
'sources': [
'application/common/manifest_handlers/navigation_handler_unittest.cc',
],