1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.browser; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.content.Intent; 22 import android.net.Uri; 23 import android.os.Bundle; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.util.Log; 27 import android.view.Gravity; 28 import android.view.KeyEvent; 29 import android.view.Window; 30 import android.widget.BaseAdapter; 31 import android.widget.Toast; 32 33 import android.webkit.gears.NativeDialog; 34 35 import com.android.browser.GearsBaseDialog; 36 import com.android.browser.GearsPermissionsDialog; 37 import com.android.browser.GearsSettingsDialog; 38 39 /** 40 * Native dialog Activity used by gears 41 * TODO: rename in GearsNativeDialogActivity 42 * @hide 43 */ 44 public class GearsNativeDialog extends Activity { 45 46 private static final String TAG = "GearsNativeDialog"; 47 48 private String mDialogArguments; 49 50 private String mGearsVersion = null; 51 52 private boolean mDebug = false; 53 54 private int mDialogType; 55 private final int SETTINGS_DIALOG = 1; 56 private final int PERMISSION_DIALOG = 2; 57 private final int LOCATION_DIALOG = 3; 58 59 private final String VERSION_STRING = "version"; 60 private final String SETTINGS_DIALOG_STRING = "settings_dialog"; 61 private final String PERMISSION_DIALOG_STRING = "permissions_dialog"; 62 private final String LOCATION_DIALOG_STRING = "locations_dialog"; 63 64 private boolean mDialogDismissed = false; 65 66 GearsBaseDialog dialog; 67 68 // Handler for callbacks to the UI thread 69 final Handler mHandler = new Handler() { 70 public void handleMessage(Message msg) { 71 if (msg.what == GearsBaseDialog.NEW_ICON) { 72 BaseAdapter adapter = (BaseAdapter) msg.obj; 73 adapter.notifyDataSetChanged(); 74 } else if (msg.what == GearsBaseDialog.UPDATE_ICON) { 75 dialog.updateIcon(); 76 } else if (msg.what == GearsBaseDialog.ALWAYS_DENY) { 77 closeDialog(GearsBaseDialog.ALWAYS_DENY); 78 } else if (msg.what == GearsBaseDialog.ALLOW) { 79 closeDialog(GearsBaseDialog.ALLOW); 80 } else if (msg.what == GearsBaseDialog.DENY) { 81 closeDialog(GearsBaseDialog.DENY); 82 } 83 super.handleMessage(msg); 84 } 85 }; 86 87 @Override onCreate(Bundle icicle)88 public void onCreate(Bundle icicle) { 89 getArguments(); 90 if (mDialogType == SETTINGS_DIALOG) { 91 setTheme(android.R.style.Theme); 92 } 93 super.onCreate(icicle); 94 if (mDialogType != SETTINGS_DIALOG) { 95 requestWindowFeature(Window.FEATURE_NO_TITLE); 96 setContentView(R.layout.gears_dialog); 97 } 98 99 switch (mDialogType) { 100 case SETTINGS_DIALOG: 101 dialog = new GearsSettingsDialog(this, mHandler, mDialogArguments); 102 dialog.setGearsVersion(mGearsVersion); 103 break; 104 case PERMISSION_DIALOG: 105 dialog = new GearsPermissionsDialog(this, mHandler, mDialogArguments); 106 break; 107 case LOCATION_DIALOG: 108 dialog = new GearsPermissionsDialog(this, mHandler, mDialogArguments); 109 break; 110 default: 111 dialog = new GearsBaseDialog(this, mHandler, mDialogArguments); 112 } 113 dialog.setDebug(mDebug); 114 dialog.setup(); 115 } 116 117 /** 118 * Get the arguments for the dialog 119 * 120 * The dialog needs a json string as an argument, as 121 * well as a dialogType. In debug mode the arguments 122 * are mocked. 123 */ getArguments()124 private void getArguments() { 125 if (mDebug) { 126 mDialogType = LOCATION_DIALOG +1; 127 mockArguments(); 128 129 return; 130 } 131 132 Intent intent = getIntent(); 133 mDialogArguments = intent.getStringExtra("dialogArguments"); 134 String dialogTypeString = intent.getStringExtra("dialogType"); 135 if (dialogTypeString == null) { 136 return; 137 } 138 139 if (Browser.LOGV_ENABLED) { 140 Log.v(TAG, "dialogtype: " + dialogTypeString); 141 } 142 143 if (dialogTypeString.equalsIgnoreCase(SETTINGS_DIALOG_STRING)) { 144 mDialogType = SETTINGS_DIALOG; 145 mGearsVersion = intent.getStringExtra(VERSION_STRING); 146 } else if (dialogTypeString.equalsIgnoreCase(PERMISSION_DIALOG_STRING)) { 147 mDialogType = PERMISSION_DIALOG; 148 } else if (dialogTypeString.equalsIgnoreCase(LOCATION_DIALOG_STRING)) { 149 mDialogType = LOCATION_DIALOG; 150 } 151 } 152 153 /** 154 * Utility method for debugging the dialog. 155 * 156 * Set mock arguments. 157 */ mockArguments()158 private void mockArguments() { 159 160 String argumentsPermissions = "{ locale: \"en-US\", " 161 + "origin: \"http://www.google.com\", dialogType: \"localData\"," 162 + "customIcon: \"http://google-gears.googlecode.com/" 163 + "svn/trunk/gears/test/manual/shortcuts/32.png\"," 164 + "customName: \"My Application\"," 165 + "customMessage: \"Press the button to enable my " 166 + "application to run offline!\" };"; 167 168 String argumentsPermissions2 = "{ locale: \"en-US\", " 169 + "origin: \"http://www.google.com\", dialogType: \"localData\" };"; 170 171 String argumentsLocation = "{ locale: \"en-US\", " 172 + "origin: \"http://www.google.com\", dialogType: \"locationData\"," 173 + "customIcon: \"http://google-gears.googlecode.com/" 174 + "svn/trunk/gears/test/manual/shortcuts/32.png\"," 175 + "customName: \"My Application\"," 176 + "customMessage: \"Press the button to enable my " 177 + "application to run offline!\" };"; 178 179 String argumentsSettings = "{ locale: \"en-US\", permissions: [ { " 180 + "name: \"http://www.google.com\", " 181 + "localStorage: { permissionState: 0 }, " 182 + "locationData: { permissionState: 1 } }, " 183 + "{ name: \"http://www.aaronboodman.com\", " 184 + "localStorage: { permissionState: 1 }, " 185 + "locationData: { permissionState: 2 } }, " 186 + "{ name: \"http://www.evil.org\", " 187 + "localStorage: { permissionState: 2 }, " 188 + "locationData: { permissionState: 2 } } ] }"; 189 190 switch (mDialogType) { 191 case PERMISSION_DIALOG: 192 mDialogArguments = argumentsPermissions; 193 break; 194 case LOCATION_DIALOG: 195 mDialogArguments = argumentsLocation; 196 break; 197 case SETTINGS_DIALOG: 198 mDialogArguments = argumentsSettings; 199 break; 200 } 201 } 202 203 /** 204 * Close the dialog and set the return string value. 205 */ closeDialog(int closingType)206 private void closeDialog(int closingType) { 207 String ret = dialog.closeDialog(closingType); 208 209 if (mDebug) { 210 Log.v(TAG, "closeDialog ret value: " + ret); 211 } 212 213 NativeDialog.closeDialog(ret); 214 notifyEndOfDialog(); 215 finish(); 216 217 // If the dialog sets a notification, we display it. 218 int notification = dialog.notification(); 219 if (notification != 0) { 220 Toast toast = Toast.makeText(this, notification, Toast.LENGTH_LONG); 221 toast.setGravity(Gravity.BOTTOM, 0, 0); 222 toast.show(); 223 } 224 } 225 226 @Override onDestroy()227 public void onDestroy() { 228 super.onDestroy(); 229 // In case we reach this point without 230 // notifying NativeDialog, we do it now. 231 if (!mDialogDismissed) { 232 notifyEndOfDialog(); 233 } 234 } 235 236 @Override onPause()237 public void onPause(){ 238 super.onPause(); 239 if (!mDialogDismissed) { 240 closeDialog(GearsBaseDialog.CANCEL); 241 } 242 } 243 244 /** 245 * Signal to NativeDialog that we are done. 246 */ notifyEndOfDialog()247 private void notifyEndOfDialog() { 248 NativeDialog.signalFinishedDialog(); 249 mDialogDismissed = true; 250 } 251 252 /** 253 * Intercepts the back key to immediately notify 254 * NativeDialog that we are done. 255 */ dispatchKeyEvent(KeyEvent event)256 public boolean dispatchKeyEvent(KeyEvent event) { 257 if ((event.getKeyCode() == KeyEvent.KEYCODE_BACK) 258 && (event.getAction() == KeyEvent.ACTION_DOWN)) { 259 if (!dialog.handleBackButton()) { 260 // if the dialog doesn't do anything with the back button 261 closeDialog(GearsBaseDialog.CANCEL); 262 } 263 return true; // event consumed 264 } 265 return super.dispatchKeyEvent(event); 266 } 267 268 /** 269 * If the dialog call showDialog() on ourself, we let 270 * it handle the creation of this secondary dialog. 271 * It is used in GearsSettingsDialog, to create the confirmation 272 * dialog when the user click on "Remove this site from Gears" 273 */ 274 @Override onCreateDialog(int id)275 protected Dialog onCreateDialog(int id) { 276 return dialog.onCreateDialog(id); 277 } 278 279 } 280