OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 |
| 5 package org.chromium.chrome.browser.contextualsearch; |
| 6 |
| 7 import org.chromium.base.CalledByNative; |
| 8 import org.chromium.chrome.browser.CompositorChromeActivity; |
| 9 import org.chromium.chrome.browser.EmptyTabObserver; |
| 10 import org.chromium.chrome.browser.Tab; |
| 11 import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
| 12 import org.chromium.chrome.browser.profiles.Profile; |
| 13 import org.chromium.chrome.browser.search_engines.TemplateUrlService; |
| 14 import org.chromium.chrome.browser.search_engines.TemplateUrlService.TemplateUrl
ServiceObserver; |
| 15 import org.chromium.content.browser.ContentViewCore; |
| 16 import org.chromium.content_public.browser.GestureStateListener; |
| 17 |
| 18 /** |
| 19 * Manages the activation and gesture listeners for ContextualSearch on a given
tab. |
| 20 */ |
| 21 public class ContextualSearchTabHelper extends EmptyTabObserver { |
| 22 /** |
| 23 * Notification handler for Contextual Search events. |
| 24 */ |
| 25 private final TemplateUrlServiceObserver mTemplateUrlObserver = |
| 26 new TemplateUrlServiceObserver() { |
| 27 @Override |
| 28 public void onTemplateURLServiceChanged() { |
| 29 onContextualSearchPrefChanged(); |
| 30 } |
| 31 }; |
| 32 |
| 33 /** |
| 34 * The current ContentViewCore for the Tab which this helper is monitoring. |
| 35 */ |
| 36 private ContentViewCore mBaseContentViewCore; |
| 37 |
| 38 /** |
| 39 * The GestureListener used for handling events from the current ContentView
Core. |
| 40 */ |
| 41 private GestureStateListener mGestureStateListener; |
| 42 |
| 43 private long mNativeHelper = 0; |
| 44 |
| 45 /** |
| 46 * Creates a contextual search tab helper for the given tab. |
| 47 * @param tab The tab whose contextual search actions will be handled by thi
s helper. |
| 48 */ |
| 49 public static void createForTab(Tab tab) { |
| 50 new ContextualSearchTabHelper(tab); |
| 51 } |
| 52 |
| 53 private ContextualSearchTabHelper(Tab tab) { |
| 54 tab.addObserver(this); |
| 55 } |
| 56 |
| 57 @Override |
| 58 public void onPageLoadStarted(Tab tab) { |
| 59 if (tab.getContentViewCore() == null) { |
| 60 // Nothing to do yet. |
| 61 return; |
| 62 } |
| 63 |
| 64 mBaseContentViewCore = tab.getContentViewCore(); |
| 65 // Add Contextual Search here in case it couldn't get added in onContent
Changed() due to |
| 66 // being too early in initialization of Chrome (ContextualSearchManager
being null). |
| 67 setContextualSearchHooks(mBaseContentViewCore); |
| 68 } |
| 69 |
| 70 @Override |
| 71 public void onPageLoadFinished(Tab tab) { |
| 72 // Native initialization happens after a page loads to ensure profile is
initialized. |
| 73 if (mNativeHelper == 0) { |
| 74 mNativeHelper = nativeInit(tab.getProfile()); |
| 75 } |
| 76 } |
| 77 |
| 78 @Override |
| 79 public void onContentChanged(Tab tab) { |
| 80 updateHooksForNewContentViewCore(tab); |
| 81 } |
| 82 |
| 83 @Override |
| 84 public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didF
inishLoad) { |
| 85 updateHooksForNewContentViewCore(tab); |
| 86 } |
| 87 |
| 88 @Override |
| 89 public void onDestroyed(Tab tab) { |
| 90 if (mNativeHelper != 0) { |
| 91 nativeDestroy(mNativeHelper); |
| 92 mNativeHelper = 0; |
| 93 } |
| 94 removeContextualSearchHooks(mBaseContentViewCore); |
| 95 mBaseContentViewCore = null; |
| 96 } |
| 97 |
| 98 /** |
| 99 * Should be called whenever the Tab's ContentViewCore changes. Removes hook
s from the |
| 100 * existing ContentViewCore, if necessary and then adds hooks for the new Co
ntentViewCore. |
| 101 * @param tab |
| 102 */ |
| 103 private void updateHooksForNewContentViewCore(Tab tab) { |
| 104 removeContextualSearchHooks(mBaseContentViewCore); |
| 105 mBaseContentViewCore = tab.getContentViewCore(); |
| 106 setContextualSearchHooks(mBaseContentViewCore); |
| 107 } |
| 108 |
| 109 /** |
| 110 * Sets up the Contextual Search hooks, adding or removing them depending on
whether it is |
| 111 * currently active. |
| 112 * @param cvc The content view core to attach the gesture state listener to. |
| 113 */ |
| 114 private void setContextualSearchHooks(ContentViewCore cvc) { |
| 115 if (cvc == null) return; |
| 116 |
| 117 if (isContextualSearchActive(cvc)) { |
| 118 addContextualSearchHooks(cvc); |
| 119 } else { |
| 120 removeContextualSearchHooks(cvc); |
| 121 } |
| 122 } |
| 123 |
| 124 /** |
| 125 * Adds Contextual Search hooks for its client and listener to the given con
tent view core. |
| 126 * @param cvc The content view core to attach the gesture state listener to. |
| 127 */ |
| 128 private void addContextualSearchHooks(ContentViewCore cvc) { |
| 129 if (ContextualSearchFieldTrial.isEnabled(cvc.getContext().getApplication
Context())) { |
| 130 ContextualSearchUma.logPreferenceState( |
| 131 ContextualSearchPolicy.getInstance(cvc.getContext()).getProm
oTapsRemaining()); |
| 132 } |
| 133 if (mGestureStateListener == null) { |
| 134 mGestureStateListener = getContextualSearchManager(cvc).getGestureSt
ateListener(); |
| 135 cvc.addGestureStateListener(mGestureStateListener); |
| 136 cvc.setContextualSearchClient(getContextualSearchManager(cvc)); |
| 137 TemplateUrlService.getInstance().addObserver(mTemplateUrlObserver); |
| 138 } |
| 139 } |
| 140 |
| 141 /** |
| 142 * Removes Contextual Search hooks for its client and listener from the give
n content view core. |
| 143 * @param cvc The content view core to detach the gesture state listener fro
m. |
| 144 */ |
| 145 private void removeContextualSearchHooks(ContentViewCore cvc) { |
| 146 if (cvc == null) return; |
| 147 |
| 148 if (ContextualSearchFieldTrial.isEnabled(cvc.getContext().getApplication
Context())) { |
| 149 ContextualSearchUma.logPreferenceState( |
| 150 ContextualSearchPolicy.getInstance(cvc.getContext()).getProm
oTapsRemaining()); |
| 151 } |
| 152 if (mGestureStateListener != null) { |
| 153 cvc.removeGestureStateListener(mGestureStateListener); |
| 154 mGestureStateListener = null; |
| 155 cvc.setContextualSearchClient(null); |
| 156 TemplateUrlService.getInstance().removeObserver(mTemplateUrlObserver
); |
| 157 } |
| 158 } |
| 159 |
| 160 /** |
| 161 * @return whether Contextual Search is enabled and active in this tab. |
| 162 */ |
| 163 private static boolean isContextualSearchActive(ContentViewCore cvc) { |
| 164 return !cvc.getWebContents().isIncognito() && getContextualSearchManager
(cvc) != null |
| 165 && !PrefServiceBridge.getInstance().isContextualSearchDisabled() |
| 166 && TemplateUrlService.getInstance().isDefaultSearchEngineGoogle() |
| 167 // Svelte and Accessibility devices are incompatible with the first-
run flow and |
| 168 // Talkback has poor interaction with tap to search (see http://crbu
g.com/399708 and |
| 169 // http://crbug.com/396934). |
| 170 // TODO(jeremycho): Handle these cases. |
| 171 && !getContextualSearchManager(cvc).isRunningInCompatibilityMode(); |
| 172 } |
| 173 |
| 174 /** |
| 175 * @return the Contextual Search manager. |
| 176 */ |
| 177 private static ContextualSearchManager getContextualSearchManager(ContentVie
wCore cvc) { |
| 178 // TODO(yfriedman): Decouple this from the activity. |
| 179 if (cvc.getContext() instanceof CompositorChromeActivity) { |
| 180 return ((CompositorChromeActivity) cvc.getContext()).getContextualSe
archManager(); |
| 181 } |
| 182 return null; |
| 183 } |
| 184 |
| 185 @CalledByNative |
| 186 private void onContextualSearchPrefChanged() { |
| 187 setContextualSearchHooks(mBaseContentViewCore); |
| 188 } |
| 189 |
| 190 private native long nativeInit(Profile profile); |
| 191 private native void nativeDestroy(long nativeContextualSearchTabHelper); |
| 192 } |
OLD | NEW |