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.app.runtime.extension;
7 import android.app.Activity;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.content.res.AssetManager;
11 import android.content.res.Resources;
12 import android.content.res.Resources.NotFoundException;
13 import android.util.Log;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import java.lang.reflect.Constructor;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.Class;
21 import java.util.HashMap;
23 import org.json.JSONArray;
24 import org.json.JSONException;
25 import org.json.JSONObject;
28 * This internal class acts a manager to manage extensions.
30 public class XWalkRuntimeExtensionManager implements XWalkExtensionContextClient {
31 private final static String TAG = "XWalkExtensionManager";
32 private final static String EXTENSION_CONFIG_FILE = "extensions-config.json";
34 private final Context mContext;
35 private final Activity mActivity;
37 private final HashMap<String, XWalkRuntimeExtensionBridge> mExtensions = new HashMap<String, XWalkRuntimeExtensionBridge>();
38 // This variable is to set whether to load external extensions. The default is true.
39 private boolean mLoadExternalExtensions;
41 public XWalkRuntimeExtensionManager(Context context, Activity activity) {
44 mLoadExternalExtensions = true;
48 public void registerExtension(XWalkExtensionClient extension) {
49 if (mExtensions.get(extension.getExtensionName()) != null) {
50 Log.e(TAG, extension.getExtensionName() + "is already registered!");
54 XWalkRuntimeExtensionBridge bridge = XWalkRuntimeExtensionBridgeFactory.createInstance(extension);
55 mExtensions.put(extension.getExtensionName(), bridge);
59 public void unregisterExtension(String name) {
60 XWalkRuntimeExtensionBridge bridge = mExtensions.get(name);
62 mExtensions.remove(name);
68 public Context getContext() {
73 public Activity getActivity() {
78 public void postMessage(XWalkExtensionClient extension, int instanceID, String message) {
79 XWalkRuntimeExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
80 if (bridge != null) bridge.postMessage(instanceID, message);
83 public void broadcastMessage(XWalkExtensionClient extension, String message) {
84 XWalkRuntimeExtensionBridge bridge = mExtensions.get(extension.getExtensionName());
85 if (bridge != null) bridge.broadcastMessage(message);
88 public void onStart() {
89 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
94 public void onResume() {
95 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
100 public void onPause() {
101 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
106 public void onStop() {
107 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
112 public void onDestroy() {
113 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
114 extension.onDestroy();
119 public void onActivityResult(int requestCode, int resultCode, Intent data) {
120 for(XWalkRuntimeExtensionBridge extension: mExtensions.values()) {
121 extension.onActivityResult(requestCode, resultCode, data);
125 public void loadExtensions() {
126 loadExternalExtensions();
129 public void setAllowExternalExtensions(boolean load) {
130 mLoadExternalExtensions = load;
133 private void loadExternalExtensions() {
134 if (!mLoadExternalExtensions) return;
136 // Read extensions-config.json and create external extensions.
137 String configFileContent;
139 configFileContent = getExtensionJSFileContent(mActivity, EXTENSION_CONFIG_FILE, false);
140 } catch (IOException e) {
141 Log.w(TAG, "Failed to read extensions-config.json");
146 JSONArray jsonFeatures = new JSONArray(configFileContent);
147 int extensionCount = jsonFeatures.length();
148 for (int i = 0; i < extensionCount; i++) {
149 JSONObject jsonObject = jsonFeatures.getJSONObject(i);
150 String name = jsonObject.getString("name");
151 String className = jsonObject.getString("class");
152 String jsApiFile = jsonObject.getString("jsapi");
154 // Load the content of the JavaScript file.
157 jsApi = getExtensionJSFileContent(mActivity, jsApiFile, false);
158 } catch (IOException e) {
159 Log.w(TAG, "Failed to read the file " + jsApiFile);
163 if (name != null && className != null && jsApi != null) {
164 createExternalExtension(name, className, jsApi, this);
167 } catch (JSONException e) {
168 Log.w(TAG, "Failed to parse extensions-config.json");
172 private String getExtensionJSFileContent(Context context, String fileName, boolean fromRaw)
175 InputStream inputStream = null;
178 // If fromRaw is true, Try to find js file in res/raw first.
179 // And then try to get it from assets if failed.
180 Resources resource = context.getResources();
181 String resName = (new File(fileName).getName().split("\\."))[0];
182 int resId = resource.getIdentifier(resName, "raw", context.getPackageName());
185 inputStream = resource.openRawResource(resId);
186 } catch (NotFoundException e) {
187 Log.w(TAG, "Inputstream failed to open for R.raw." + resName +
188 ", try to find it in assets");
192 if (inputStream == null) {
193 AssetManager assetManager = context.getAssets();
194 inputStream = assetManager.open(fileName);
196 int size = inputStream.available();
197 byte[] buffer = new byte[size];
198 inputStream.read(buffer);
199 result = new String(buffer);
201 if (inputStream != null) {
208 private void createExternalExtension(String name, String className, String jsApi,
209 XWalkExtensionContextClient extensionContext) {
210 Activity activity = extensionContext.getActivity();
212 Class<?> clazz = activity.getClassLoader().loadClass(className);
213 Constructor<?> constructor = clazz.getConstructor(String.class,
214 String.class, XWalkExtensionContextClient.class);
215 constructor.newInstance(name, jsApi, this);
216 } catch (ClassNotFoundException e) {
218 } catch (IllegalAccessException e) {
220 } catch (InstantiationException e) {
222 } catch (InvocationTargetException e) {
224 } catch (NoSuchMethodException e) {
229 private static void handleException(Exception e) {
230 // TODO(yongsheng): Handle exceptions here.
231 Log.e(TAG, "Error in calling methods of external extensions. " + e.toString());