1// Copyright 2012 The Chromium Authors. 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. 4 5package org.chromium.ui.base; 6 7import android.content.ContentResolver; 8import android.content.Context; 9import android.content.Intent; 10import android.os.Bundle; 11import android.util.Log; 12import android.util.SparseArray; 13import android.widget.Toast; 14 15import org.chromium.base.CalledByNative; 16import org.chromium.base.JNINamespace; 17 18import java.util.HashMap; 19 20/** 21 * The window base class that has the minimum functionality. 22 */ 23@JNINamespace("ui") 24public class WindowAndroid { 25 private static final String TAG = "WindowAndroid"; 26 27 // Native pointer to the c++ WindowAndroid object. 28 private long mNativeWindowAndroid = 0; 29 30 // A string used as a key to store intent errors in a bundle 31 static final String WINDOW_CALLBACK_ERRORS = "window_callback_errors"; 32 33 protected Context mApplicationContext; 34 protected SparseArray<IntentCallback> mOutstandingIntents; 35 protected HashMap<Integer, String> mIntentErrors; 36 37 /** 38 * @param context The application context. 39 */ 40 public WindowAndroid(Context context) { 41 assert context == context.getApplicationContext(); 42 mApplicationContext = context; 43 mOutstandingIntents = new SparseArray<IntentCallback>(); 44 mIntentErrors = new HashMap<Integer, String>(); 45 } 46 47 /** 48 * Shows an intent and returns the results to the callback object. 49 * @param intent The intent that needs to be showed. 50 * @param callback The object that will receive the results for the intent. 51 * @param errorId The ID of error string to be show if activity is paused before intent 52 * results. 53 * @return Whether the intent was shown. 54 */ 55 public boolean showIntent(Intent intent, IntentCallback callback, int errorId) { 56 return showCancelableIntent(intent, callback, errorId) >= 0; 57 } 58 59 /** 60 * Shows an intent that could be canceled and returns the results to the callback object. 61 * @param intent The intent that needs to be showed. 62 * @param callback The object that will receive the results for the intent. 63 * @param errorId The ID of error string to be show if activity is paused before intent 64 * results. 65 * @return A non-negative request code that could be used for finishActivity, or -1 if failed. 66 */ 67 public int showCancelableIntent(Intent intent, IntentCallback callback, int errorId) { 68 Log.d(TAG, "Can't show intent as context is not an Activity: " + intent); 69 return -1; 70 } 71 72 /** 73 * Force finish another activity that you had previously started with showCancelableIntent. 74 * @param requestCode The request code returned from showCancelableIntent. 75 */ 76 public void cancelIntent(int requestCode) { 77 Log.d(TAG, "Can't cancel intent as context is not an Activity: " + requestCode); 78 } 79 80 /** 81 * Removes a callback from the list of pending intents, so that nothing happens if/when the 82 * result for that intent is received. 83 * @param callback The object that should have received the results 84 * @return True if the callback was removed, false if it was not found. 85 */ 86 public boolean removeIntentCallback(IntentCallback callback) { 87 int requestCode = mOutstandingIntents.indexOfValue(callback); 88 if (requestCode < 0) return false; 89 mOutstandingIntents.remove(requestCode); 90 mIntentErrors.remove(requestCode); 91 return true; 92 } 93 94 /** 95 * Displays an error message with a provided error message string. 96 * @param error The error message string to be displayed. 97 */ 98 public void showError(String error) { 99 if (error != null) { 100 Toast.makeText(mApplicationContext, error, Toast.LENGTH_SHORT).show(); 101 } 102 } 103 104 /** 105 * Displays an error message from the given resource id. 106 * @param resId The error message string's resource id. 107 */ 108 public void showError(int resId) { 109 showError(mApplicationContext.getString(resId)); 110 } 111 112 /** 113 * Displays an error message for a nonexistent callback. 114 * @param error The error message string to be displayed. 115 */ 116 protected void showCallbackNonExistentError(String error) { 117 showError(error); 118 } 119 120 /** 121 * Broadcasts the given intent to all interested BroadcastReceivers. 122 */ 123 public void sendBroadcast(Intent intent) { 124 mApplicationContext.sendBroadcast(intent); 125 } 126 127 /** 128 * TODO(nileshagrawal): Stop returning Activity Context crbug.com/233440. 129 * @return Activity context, it could be null. Note, in most cases, you probably 130 * just need Application Context returned by getApplicationContext(). 131 * @see #getApplicationContext() 132 */ 133 @Deprecated 134 public Context getContext() { 135 return null; 136 } 137 138 /** 139 * @return The application context for this activity. 140 */ 141 public Context getApplicationContext() { 142 return mApplicationContext; 143 } 144 145 /** 146 * Saves the error messages that should be shown if any pending intents would return 147 * after the application has been put onPause. 148 * @param bundle The bundle to save the information in onPause 149 */ 150 public void saveInstanceState(Bundle bundle) { 151 bundle.putSerializable(WINDOW_CALLBACK_ERRORS, mIntentErrors); 152 } 153 154 /** 155 * Restores the error messages that should be shown if any pending intents would return 156 * after the application has been put onPause. 157 * @param bundle The bundle to restore the information from onResume 158 */ 159 public void restoreInstanceState(Bundle bundle) { 160 if (bundle == null) return; 161 162 Object errors = bundle.getSerializable(WINDOW_CALLBACK_ERRORS); 163 if (errors instanceof HashMap) { 164 @SuppressWarnings("unchecked") 165 HashMap<Integer, String> intentErrors = (HashMap<Integer, String>) errors; 166 mIntentErrors = intentErrors; 167 } 168 } 169 170 /** 171 * Responds to the intent result if the intent was created by the native window. 172 * @param requestCode Request code of the requested intent. 173 * @param resultCode Result code of the requested intent. 174 * @param data The data returned by the intent. 175 * @return Boolean value of whether the intent was started by the native window. 176 */ 177 public boolean onActivityResult(int requestCode, int resultCode, Intent data) { 178 return false; 179 } 180 181 /** 182 * An interface that intent callback objects have to implement. 183 */ 184 public interface IntentCallback { 185 /** 186 * Handles the data returned by the requested intent. 187 * @param window A window reference. 188 * @param resultCode Result code of the requested intent. 189 * @param contentResolver An instance of ContentResolver class for accessing returned data. 190 * @param data The data returned by the intent. 191 */ 192 public void onIntentCompleted(WindowAndroid window, int resultCode, 193 ContentResolver contentResolver, Intent data); 194 } 195 196 /** 197 * Tests that an activity is available to handle the passed in intent. 198 * @param intent The intent to check. 199 * @return True if an activity is available to process this intent when started, meaning that 200 * Context.startActivity will not throw ActivityNotFoundException. 201 */ 202 public boolean canResolveActivity(Intent intent) { 203 return mApplicationContext.getPackageManager().resolveActivity(intent, 0) != null; 204 } 205 206 /** 207 * Destroys the c++ WindowAndroid object if one has been created. 208 */ 209 public void destroy() { 210 if (mNativeWindowAndroid != 0) { 211 nativeDestroy(mNativeWindowAndroid); 212 mNativeWindowAndroid = 0; 213 } 214 } 215 216 /** 217 * Returns a pointer to the c++ AndroidWindow object and calls the initializer if 218 * the object has not been previously initialized. 219 * @return A pointer to the c++ AndroidWindow. 220 */ 221 public long getNativePointer() { 222 if (mNativeWindowAndroid == 0) { 223 mNativeWindowAndroid = nativeInit(); 224 } 225 return mNativeWindowAndroid; 226 } 227 228 /** 229 * Returns a PNG-encoded screenshot of the the window region at (|windowX|, 230 * |windowY|) with the size |width| by |height| pixels. 231 */ 232 @CalledByNative 233 public byte[] grabSnapshot(int windowX, int windowY, int width, int height) { 234 return null; 235 } 236 237 private native long nativeInit(); 238 private native void nativeDestroy(long nativeWindowAndroid); 239 240} 241