1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.xwalk.core;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.io.IOException;
10 import java.lang.StringBuilder;
11 import java.util.HashSet;
14 import android.content.Context;
15 import android.content.res.AssetManager;
16 import android.content.res.Resources.NotFoundException;
17 import android.os.Build;
18 import android.util.Log;
20 import org.chromium.base.ApplicationStatusManager;
21 import org.chromium.base.CommandLine;
22 import org.chromium.base.JNINamespace;
23 import org.chromium.base.PathUtils;
24 import org.chromium.base.ThreadUtils;
25 import org.chromium.base.library_loader.LibraryLoader;
26 import org.chromium.base.library_loader.ProcessInitException;
27 import org.chromium.content.browser.BrowserStartupController;
28 import org.chromium.content.browser.DeviceUtils;
29 import org.chromium.content.browser.ResourceExtractor;
30 import org.chromium.content.browser.ResourceExtractor.ResourceIntercepter;
31 import org.chromium.net.NetworkChangeNotifier;
33 @JNINamespace("xwalk")
34 class XWalkViewDelegate {
35 private static boolean sInitialized = false;
36 private static boolean sRunningOnIA = true;
37 private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "xwalkcore";
38 private static final String[] MANDATORY_PAKS = {
43 private static final String[] MANDATORY_LIBRARIES = {
46 private static final String TAG = "XWalkViewDelegate";
47 private static final String XWALK_RESOURCES_LIST_RES_NAME = "xwalk_resources_list";
49 private static final String COMMAND_LINE_FILE = "xwalk-command-line";
51 private static String[] readCommandLine(Context context) {
52 InputStreamReader reader = null;
56 context.getAssets().open(COMMAND_LINE_FILE, AssetManager.ACCESS_BUFFER);
59 char[] buffer = new char[size];
60 StringBuilder builder = new StringBuilder();
62 reader = new InputStreamReader(input, "UTF-8");
63 while ((length = reader.read(buffer, 0, size)) != -1) {
64 builder.append(buffer, 0, length);
67 return CommandLine.tokenizeQuotedAruments(
68 builder.toString().toCharArray());
69 } catch (IOException e) {
73 if (reader != null) reader.close();
74 } catch (IOException e) {
75 Log.e(TAG, "Unable to close file reader.", e);
80 public static void init(XWalkView xwalkView) throws UnsatisfiedLinkError {
85 // Initialize the ActivityStatus. This is needed and used by many internal
86 // features such as location provider to listen to activity status.
87 ApplicationStatusManager.init(xwalkView.getActivity().getApplication());
89 // Auto detect network connectivity state.
90 // setAutoDetectConnectivityState() need to be called before activity started.
91 NetworkChangeNotifier.init(xwalkView.getActivity());
92 NetworkChangeNotifier.setAutoDetectConnectivityState(true);
94 // We will miss activity onCreate() status in ApplicationStatusManager,
95 // informActivityStarted() will simulate these callbacks.
96 ApplicationStatusManager.informActivityStarted(xwalkView.getActivity());
98 final Context context = xwalkView.getViewContext();
100 // Last place to initialize CommandLine object. If you haven't initialize
101 // the CommandLine object before XWalkViewContent is created, here will create
102 // the object to guarantee the CommandLine object is not null and the
103 // consequent prodedure does not crash.
104 if (!CommandLine.isInitialized()) {
105 CommandLine.init(readCommandLine(context.getApplicationContext()));
108 // If context's applicationContext is not the same package with itself,
109 // It's a cross package invoking, load core library from library apk.
110 // Only load the native library from /data/data if the Android version is
111 // lower than 4.2. Android enables a system path /data/app-lib to store native
112 // libraries starting from 4.2 and load them automatically.
113 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 &&
114 !context.getApplicationContext().getPackageName().equals(context.getPackageName())) {
115 for (String library : MANDATORY_LIBRARIES) {
116 System.load("/data/data/" + context.getPackageName() + "/lib/" + library);
119 loadLibrary(context);
120 DeviceUtils.addDeviceSpecificUserAgentSwitch(context);
122 if (sRunningOnIA && !nativeIsLibraryBuiltForIA()) {
123 throw new UnsatisfiedLinkError();
126 ResourceExtractor.setMandatoryPaksToExtract(MANDATORY_PAKS);
127 final int resourcesListResId = context.getResources().getIdentifier(
128 XWALK_RESOURCES_LIST_RES_NAME, "array", context.getPackageName());
129 if (resourcesListResId != 0) {
130 ResourceExtractor.setResourceIntercepter(new ResourceIntercepter() {
133 public Set<String> getInterceptableResourceList() {
135 Set<String> resourcesList = new HashSet<String>();
136 String[] resources = context.getResources().getStringArray(resourcesListResId);
137 for (String resource : resources) {
138 resourcesList.add(resource);
140 return resourcesList;
141 } catch (NotFoundException e) {
142 Log.w(TAG, "R.array." + XWALK_RESOURCES_LIST_RES_NAME + " can't be found.");
148 public InputStream interceptLoadingForResource(String resource) {
149 String resourceName = resource.split("\\.")[0];
150 int resId = context.getResources().getIdentifier(
151 resourceName, "raw", context.getPackageName());
153 if (resId != 0) return context.getResources().openRawResource(resId);
154 } catch (NotFoundException e) {
155 Log.w(TAG, "R.raw." + resourceName + " can't be found.");
161 ResourceExtractor.setExtractImplicitLocaleForTesting(false);
162 // Use MixedContext to initialize the ResourceExtractor, as the pak file
163 // is in the library apk if in shared apk mode.
164 ResourceExtractor.get(context);
166 startBrowserProcess(context);
170 private static void loadLibrary(Context context) {
171 PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
173 LibraryLoader.loadNow(context, true);
174 } catch (ProcessInitException e) {
175 throw new RuntimeException("Cannot load Crosswalk Core", e);
179 private static void startBrowserProcess(final Context context) {
180 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
184 LibraryLoader.ensureInitialized();
185 } catch (ProcessInitException e) {
186 throw new RuntimeException("Cannot initialize Crosswalk Core", e);
189 BrowserStartupController.get(context).startBrowserProcessesSync(
190 BrowserStartupController.MAX_RENDERERS_SINGLE_PROCESS);
191 } catch (ProcessInitException e) {
192 throw new RuntimeException("Cannot initialize Crosswalk Core", e);
198 public static boolean isRunningOnIA() {
202 private static native boolean nativeIsLibraryBuiltForIA();
205 sRunningOnIA = Build.CPU_ABI.equalsIgnoreCase("x86");