mobile/android/base/FindInPageBar.java

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko;
     7 import org.mozilla.gecko.util.GeckoEventListener;
     8 import org.mozilla.gecko.util.ThreadUtils;
    10 import org.json.JSONObject;
    12 import android.content.Context;
    13 import android.text.Editable;
    14 import android.text.TextUtils;
    15 import android.text.TextWatcher;
    16 import android.util.AttributeSet;
    17 import android.view.KeyEvent;
    18 import android.view.LayoutInflater;
    19 import android.view.View;
    20 import android.view.inputmethod.InputMethodManager;
    21 import android.widget.LinearLayout;
    23 public class FindInPageBar extends LinearLayout implements TextWatcher, View.OnClickListener, GeckoEventListener  {
    24     private static final String REQUEST_ID = "FindInPageBar";
    26     private final Context mContext;
    27     private CustomEditText mFindText;
    28     private boolean mInflated = false;
    30     public FindInPageBar(Context context, AttributeSet attrs) {
    31         super(context, attrs);
    32         mContext = context;
    33         setFocusable(true);
    34     }
    36     public void inflateContent() {
    37         LayoutInflater inflater = LayoutInflater.from(mContext);
    38         View content = inflater.inflate(R.layout.find_in_page_content, this);
    40         content.findViewById(R.id.find_prev).setOnClickListener(this);
    41         content.findViewById(R.id.find_next).setOnClickListener(this);
    42         content.findViewById(R.id.find_close).setOnClickListener(this);
    44         // Capture clicks on the rest of the view to prevent them from
    45         // leaking into other views positioned below.
    46         content.setOnClickListener(this);
    48         mFindText = (CustomEditText) content.findViewById(R.id.find_text);
    49         mFindText.addTextChangedListener(this);
    50         mFindText.setOnKeyPreImeListener(new CustomEditText.OnKeyPreImeListener() {
    51             @Override
    52             public boolean onKeyPreIme(View v, int keyCode, KeyEvent event) {
    53                 if (keyCode == KeyEvent.KEYCODE_BACK) {
    54                     hide();
    55                     return true;
    56                 }
    57                 return false;
    58             }
    59         });
    61         mInflated = true;
    62         GeckoAppShell.getEventDispatcher().registerEventListener("TextSelection:Data", this);
    63     }
    65     public void show() {
    66         if (!mInflated)
    67             inflateContent();
    69         setVisibility(VISIBLE);
    70         mFindText.requestFocus();
    72         // handleMessage() receives response message and determines initial state of softInput
    73         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("TextSelection:Get", REQUEST_ID));
    74     }
    76     public void hide() {
    77         setVisibility(GONE);
    78         getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
    79         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Closed", null));
    80     }
    82     private InputMethodManager getInputMethodManager(View view) {
    83         Context context = view.getContext();
    84         return (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
    85      }
    87     public void onDestroy() {
    88         if (!mInflated) {
    89             return;
    90         }
    91         GeckoAppShell.getEventDispatcher().unregisterEventListener("TextSelection:Data", this);
    92     }
    94     // TextWatcher implementation
    96     @Override
    97     public void afterTextChanged(Editable s) {
    98         GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Find", s.toString()));
    99     }
   101     @Override
   102     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
   103         // ignore
   104     }
   106     @Override
   107     public void onTextChanged(CharSequence s, int start, int before, int count) {
   108         // ignore
   109     }
   111     // View.OnClickListener implementation
   113     @Override
   114     public void onClick(View v) {
   115         final int viewId = v.getId();
   117         if (viewId == R.id.find_prev) {
   118             GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Prev", mFindText.getText().toString()));
   119             getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
   120             return;
   121         }
   123         if (viewId == R.id.find_next) {
   124             GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent("FindInPage:Next", mFindText.getText().toString()));
   125             getInputMethodManager(mFindText).hideSoftInputFromWindow(mFindText.getWindowToken(), 0);
   126             return;
   127         }
   129         if (viewId == R.id.find_close) {
   130             hide();
   131         }
   132     }
   134     // GeckoEventListener implementation
   136     @Override
   137     public void handleMessage(String event, JSONObject message) {
   138         if (!event.equals("TextSelection:Data") || !REQUEST_ID.equals(message.optString("requestId"))) {
   139             return;
   140         }
   142         final String text = message.optString("text");
   144         // Populate an initial find string, virtual keyboard not required.
   145         if (!TextUtils.isEmpty(text)) {
   146             // Populate initial selection
   147             ThreadUtils.postToUiThread(new Runnable() {
   148                 @Override
   149                 public void run() {
   150                     mFindText.setText(text);
   151                 }
   152             });
   153             return;
   154         }
   156         // Show the virtual keyboard.
   157         if (mFindText.hasWindowFocus()) {
   158             getInputMethodManager(mFindText).showSoftInput(mFindText, 0);
   159         } else {
   160             // showSoftInput won't work until after the window is focused.
   161             mFindText.setOnWindowFocusChangeListener(new CustomEditText.OnWindowFocusChangeListener() {
   162                 @Override
   163                 public void onWindowFocusChanged(boolean hasFocus) {
   164                     if (!hasFocus)
   165                         return;
   167                     mFindText.setOnWindowFocusChangeListener(null);
   168                     getInputMethodManager(mFindText).showSoftInput(mFindText, 0);
   169                }
   170             });
   171         }
   172     }
   173 }

mercurial