• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Context;
22 import android.content.res.Resources;
23 import android.graphics.Bitmap;
24 import android.graphics.BitmapFactory;
25 import android.os.Handler;
26 import android.text.Spannable;
27 import android.text.SpannableString;
28 import android.text.style.UnderlineSpan;
29 import android.util.Log;
30 import android.view.InflateException;
31 import android.view.LayoutInflater;
32 import android.view.View;
33 import android.view.ViewGroup;
34 import android.widget.Button;
35 import android.widget.ImageView;
36 import android.widget.TextView;
37 
38 import java.io.InputStream;
39 import java.io.IOException;
40 import java.lang.ClassCastException;
41 import java.net.HttpURLConnection;
42 import java.net.MalformedURLException;
43 import java.net.URL;
44 
45 import org.json.JSONException;
46 import org.json.JSONObject;
47 
48 /**
49  * Base dialog class for gears
50  */
51 class GearsBaseDialog {
52 
53   private static final String TAG = "GearsNativeDialog";
54   protected Handler mHandler;
55   protected Activity mActivity;
56   protected String mDialogArguments;
57 
58   private Bitmap mIcon;
59   private final int MAX_ICON_SIZE = 64;
60   protected int mChoosenIconSize;
61 
62   // Dialog closing types
63   public static final int CANCEL = 0;
64   public static final int ALWAYS_DENY = 1;
65   public static final int ALLOW = 2;
66   public static final int DENY = 3;
67   public static final int NEW_ICON = 4;
68   public static final int UPDATE_ICON = 5;
69   public static final int REQUEST_ICON = 6;
70   public static final int PAUSE_REQUEST_ICON = 7;
71   public static final int CLEAR_REQUEST_ICON = 8;
72 
73   protected final String LOCAL_DATA_STRING = "localData";
74   protected final String LOCAL_STORAGE_STRING = "localStorage";
75   protected final String LOCATION_DATA_STRING = "locationData";
76 
77   protected String mGearsVersion = "UNDEFINED";
78   protected boolean mDebug = false;
79 
GearsBaseDialog(Activity activity, Handler handler, String arguments)80   public GearsBaseDialog(Activity activity, Handler handler, String arguments) {
81     mActivity = activity;
82     mHandler = handler;
83     mDialogArguments = arguments;
84   }
85 
getResources()86   Resources getResources() {
87     return mActivity.getResources();
88   }
89 
getSystemService(String name)90   Object getSystemService(String name) {
91     return mActivity.getSystemService(name);
92   }
93 
findViewById(int id)94   View findViewById(int id) {
95     return mActivity.findViewById(id);
96   }
97 
getString(int id)98   private String getString(int id) {
99     return mActivity.getString(id);
100   }
101 
setDebug(boolean debug)102   public void setDebug(boolean debug) {
103     mDebug = debug;
104   }
105 
setGearsVersion(String version)106   public void setGearsVersion(String version) {
107     mGearsVersion = version;
108   }
109 
closeDialog(int closingType)110   public String closeDialog(int closingType) {
111     return null;
112   }
113 
114   /*
115    * Utility methods for setting up the dialogs elements
116    */
117 
118   /**
119    * Inflate a given layout in a view (which has to be
120    * a ViewGroup, e.g. LinearLayout).
121    * This is used to share the basic dialog outline among
122    * the different dialog types.
123    */
inflate(int layout, int viewID)124   void inflate(int layout, int viewID) {
125     LayoutInflater inflater = (LayoutInflater) getSystemService(
126         Context.LAYOUT_INFLATER_SERVICE);
127     View view = findViewById(viewID);
128     if (view != null) {
129       try {
130         ViewGroup viewGroup = (ViewGroup) view;
131         inflater.inflate(layout, viewGroup);
132       } catch (ClassCastException e) {
133         String msg = "exception, the view (" + view + ")";
134         msg += " is not a ViewGroup";
135         Log.e(TAG, msg, e);
136       } catch (InflateException e) {
137         Log.e(TAG, "exception while inflating the layout", e);
138       }
139     } else {
140       String msg = "problem, trying to inflate a non-existent view";
141       msg += " (" + viewID + ")";
142       Log.e(TAG, msg);
143     }
144   }
145 
146   /**
147    * Button setup.
148    * Set the button's text and its listener. If the text resource's id
149    * is 0, makes the button invisible.
150    */
setupButton(int buttonRscID, int rscString, View.OnClickListener listener, boolean isLink, boolean requestFocus)151   void setupButton(int buttonRscID,
152                    int rscString,
153                    View.OnClickListener listener,
154                    boolean isLink,
155                    boolean requestFocus) {
156     View view = findViewById(buttonRscID);
157     if (view == null) {
158       return;
159     }
160 
161     Button button = (Button) view;
162 
163     if (rscString == 0) {
164       button.setVisibility(View.GONE);
165     } else {
166       CharSequence text = getString(rscString);
167       button.setText(text);
168       button.setOnClickListener(listener);
169       if (isLink) {
170         displayAsLink(button);
171       }
172       if (requestFocus) {
173         button.requestFocus();
174       }
175     }
176   }
177 
178   /**
179    * Button setup: as the above method, except that 'isLink' and
180    * 'requestFocus' default to false.
181    */
setupButton(int buttonRsc, int rsc, View.OnClickListener listener)182   void setupButton(int buttonRsc, int rsc,
183                    View.OnClickListener listener) {
184     setupButton(buttonRsc, rsc, listener, false, false);
185   }
186 
187   /**
188    * Utility method to setup the three dialog buttons.
189    */
setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc)190   void setupButtons(int alwaysDenyRsc, int allowRsc, int denyRsc) {
191     setupButton(R.id.button_alwaysdeny, alwaysDenyRsc,
192                 new Button.OnClickListener() {
193                   public void onClick(View v) {
194                     mHandler.sendEmptyMessage(ALWAYS_DENY);
195                   }
196                 });
197 
198     setupButton(R.id.button_allow, allowRsc,
199                 new Button.OnClickListener() {
200                   public void onClick(View v) {
201                     mHandler.sendEmptyMessage(ALLOW);
202                   }
203                 });
204 
205     setupButton(R.id.button_deny, denyRsc,
206                 new Button.OnClickListener() {
207                   public void onClick(View v) {
208                     mHandler.sendEmptyMessage(DENY);
209                   }
210                 });
211   }
212 
213   /**
214    * Display a button as an HTML link. Remove the background, set the
215    * text color to R.color.dialog_link and draw an underline
216    */
displayAsLink(Button button)217   void displayAsLink(Button button) {
218     if (button == null) {
219       return;
220     }
221 
222     CharSequence text = button.getText();
223     button.setBackgroundDrawable(null);
224     int color = getResources().getColor(R.color.dialog_link);
225     button.setTextColor(color);
226     SpannableString str = new SpannableString(text);
227     str.setSpan(new UnderlineSpan(), 0, str.length(),
228                 Spannable.SPAN_INCLUSIVE_INCLUSIVE);
229     button.setText(str);
230     button.setFocusable(false);
231   }
232 
233   /**
234    * Utility method to set elements' text indicated in
235    * the dialogs' arguments.
236    */
setLabel(JSONObject json, String name, int rsc)237   void setLabel(JSONObject json, String name, int rsc) {
238     try {
239       if (json.has(name)) {
240         String text = json.getString(name);
241         View view = findViewById(rsc);
242         if (view != null && text != null) {
243           TextView textView = (TextView) view;
244           textView.setText(text);
245           textView.setVisibility(View.VISIBLE);
246         }
247       }
248     } catch (JSONException e) {
249       Log.e(TAG, "json exception", e);
250     }
251   }
252 
253   /**
254    * Utility method to hide a view.
255    */
hideView(View v, int rsc)256   void hideView(View v, int rsc) {
257     if (rsc == 0) {
258       return;
259     }
260     View view;
261     if (v == null) {
262       view = findViewById(rsc);
263     } else {
264       view = v.findViewById(rsc);
265     }
266     if (view != null) {
267       view.setVisibility(View.GONE);
268     }
269   }
270 
271   /**
272    * Utility method to show a view.
273    */
showView(View v, int rsc)274   void showView(View v, int rsc) {
275     if (rsc == 0) {
276       return;
277     }
278     View view;
279     if (v == null) {
280       view = findViewById(rsc);
281     } else {
282       view = v.findViewById(rsc);
283     }
284     if (view != null) {
285       view.setVisibility(View.VISIBLE);
286     }
287   }
288 
289   /**
290    * Utility method to set a text.
291    */
setText(View v, int rsc, CharSequence text)292   void setText(View v, int rsc, CharSequence text) {
293     if (rsc == 0) {
294       return;
295     }
296     View view = v.findViewById(rsc);
297     if (view != null) {
298       TextView textView = (TextView) view;
299       textView.setText(text);
300       textView.setVisibility(View.VISIBLE);
301     }
302   }
303 
304   /**
305    * Utility method to set a text.
306    */
setText(View v, int rsc, int txtRsc)307   void setText(View v, int rsc, int txtRsc) {
308     if (rsc == 0) {
309       return;
310     }
311     View view = v.findViewById(rsc);
312     if (view != null) {
313       TextView textView = (TextView) view;
314       if (txtRsc == 0) {
315         textView.setVisibility(View.GONE);
316       } else {
317         CharSequence text = getString(txtRsc);
318         textView.setText(text);
319         textView.setVisibility(View.VISIBLE);
320       }
321     }
322   }
323 
324   /**
325    * Utility class to download an icon in the background.
326    * Once done ask the UI thread to update the icon.
327    */
328   class IconDownload implements Runnable {
329     private String mUrlString;
330 
IconDownload(String url)331     IconDownload(String url) {
332       mUrlString = url;
333     }
334 
run()335     public void run() {
336       if (mUrlString == null) {
337         return;
338       }
339       try {
340         URL url = new URL(mUrlString);
341         HttpURLConnection connection = (HttpURLConnection) url.openConnection();
342         connection.setDoInput(true);
343         connection.connect();
344         int length = connection.getContentLength();
345         InputStream is = connection.getInputStream();
346         Bitmap customIcon = BitmapFactory.decodeStream(is);
347         if (customIcon != null) {
348           mIcon = customIcon;
349           mHandler.sendEmptyMessage(UPDATE_ICON);
350         }
351       } catch (ClassCastException e) {
352         Log.e(TAG, "Class cast exception (" + mUrlString + ")", e);
353       } catch (MalformedURLException e) {
354         Log.e(TAG, "Malformed url (" + mUrlString + ") ", e);
355       } catch (IOException e) {
356         Log.e(TAG, "Exception downloading icon (" + mUrlString + ") ", e);
357       }
358     }
359   }
360 
361   /**
362    * Utility method to update the icon.
363    * Called on the UI thread.
364    */
updateIcon()365   public void updateIcon() {
366     if (mIcon == null) {
367       return;
368     }
369     View view = findViewById(R.id.origin_icon);
370     if (view != null) {
371       ImageView imageView = (ImageView) view;
372       imageView.setMaxHeight(MAX_ICON_SIZE);
373       imageView.setMaxWidth(MAX_ICON_SIZE);
374       imageView.setScaleType(ImageView.ScaleType.FIT_XY);
375       imageView.setImageBitmap(mIcon);
376       imageView.setVisibility(View.VISIBLE);
377     }
378   }
379 
380   /**
381    * Utility method to download an icon from a url and set
382    * it to the GUI element R.id.origin_icon.
383    * It is used both in the shortcut dialog and the
384    * permission dialog.
385    * The actual download is done in the background via
386    * IconDownload; once the icon is downlowded the UI is updated
387    * via updateIcon().
388    * The icon size is included in the layout with the choosen
389    * size, although not displayed, to limit text reflow once
390    * the icon is received.
391    */
downloadIcon(String url)392   void downloadIcon(String url) {
393     if (url == null) {
394       return;
395     }
396     View view = findViewById(R.id.origin_icon);
397     if (view != null) {
398       view.setMinimumWidth(mChoosenIconSize);
399       view.setMinimumHeight(mChoosenIconSize);
400       view.setVisibility(View.INVISIBLE);
401     }
402     Thread thread = new Thread(new IconDownload(url));
403     thread.start();
404   }
405 
406   /**
407    * Utility method that get the dialogMessage
408    * and icon and ask the setupDialog(message,icon)
409    * method to set the values.
410    */
setupDialog()411   public void setupDialog() {
412     TextView dialogMessage = null;
413     ImageView icon = null;
414 
415     View view = findViewById(R.id.dialog_message);
416     if (view != null) {
417       dialogMessage = (TextView) view;
418     }
419 
420     View iconView = findViewById(R.id.icon);
421     if (iconView != null) {
422       icon = (ImageView) iconView;
423     }
424 
425     if ((dialogMessage != null) && (icon != null)) {
426       setupDialog(dialogMessage, icon);
427       dialogMessage.setVisibility(View.VISIBLE);
428     }
429   }
430 
431   /*
432    * Set the message and icon of the dialog
433    */
setupDialog(TextView message, ImageView icon)434   public void setupDialog(TextView message, ImageView icon) {
435     message.setText(R.string.unrecognized_dialog_message);
436     icon.setImageResource(R.drawable.ic_dialog_menu_generic);
437     message.setVisibility(View.VISIBLE);
438   }
439 
440   /**
441    * Setup the dialog
442    * By default, just display a simple message.
443    */
setup()444   public void setup() {
445     setupButtons(0, 0, R.string.default_button);
446     setupDialog();
447   }
448 
449   /**
450    * Method called when the back button is pressed,
451    * allowing the dialog to intercept the default behaviour.
452    */
handleBackButton()453   public boolean handleBackButton() {
454     return false;
455   }
456 
457   /**
458    * Returns the resource string of the notification displayed
459    * after the dialog. By default, does not return one.
460    */
notification()461   public int notification() {
462     return 0;
463   }
464 
465   /**
466    * If a secondary dialog (e.g. a confirmation dialog) is created,
467    * GearsNativeDialog will call this method.
468    */
onCreateDialog(int id)469   public Dialog onCreateDialog(int id) {
470     // This should be redefined by subclasses as needed.
471     return null;
472   }
473 
474 }
475