diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 924a943d..c96f62da 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2932,6 +2932,8 @@ "android/preferences/autofill/autofill_profile_bridge.h", "android/preferences/browser_prefs_android.cc", "android/preferences/browser_prefs_android.h", + "android/preferences/clipboard_android.cc", + "android/preferences/clipboard_android.h", "android/preferences/pref_service_bridge.cc", "android/preferences/pref_service_bridge.h", "android/preferences/preferences_launcher.cc",
diff --git a/chrome/browser/android/preferences/browser_prefs_android.cc b/chrome/browser/android/preferences/browser_prefs_android.cc index 6e9a9c7..1db741d 100644 --- a/chrome/browser/android/preferences/browser_prefs_android.cc +++ b/chrome/browser/android/preferences/browser_prefs_android.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/android/preferences/browser_prefs_android.h" +#include "chrome/browser/android/preferences/clipboard_android.h" #include "chrome/browser/android/search_geolocation/search_geolocation_disclosure_tab_helper.h" #include "chrome/browser/android/search_geolocation/search_geolocation_service.h" #include "chrome/browser/notifications/notification_platform_bridge_android.h" @@ -12,6 +13,10 @@ namespace android { +void RegisterPrefs(PrefRegistrySimple* registry) { + RegisterClipboardAndroidPrefs(registry); +} + void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { NotificationPlatformBridgeAndroid::RegisterProfilePrefs(registry); SearchGeolocationDisclosureTabHelper::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/android/preferences/browser_prefs_android.h b/chrome/browser/android/preferences/browser_prefs_android.h index 8693362..0764c5a 100644 --- a/chrome/browser/android/preferences/browser_prefs_android.h +++ b/chrome/browser/android/preferences/browser_prefs_android.h
@@ -5,12 +5,17 @@ #ifndef CHROME_BROWSER_ANDROID_PREFERENCES_BROWSER_PREFS_ANDROID_H_ #define CHROME_BROWSER_ANDROID_PREFERENCES_BROWSER_PREFS_ANDROID_H_ +class PrefRegistrySimple; + namespace user_prefs { class PrefRegistrySyncable; } // namespace user_prefs namespace android { +// Register all prefs that will be used via the local state PrefService. +void RegisterPrefs(PrefRegistrySimple* registry); + // Register all prefs that will be used via a PrefService attached to a user // Profile on Android. void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
diff --git a/chrome/browser/android/preferences/clipboard_android.cc b/chrome/browser/android/preferences/clipboard_android.cc new file mode 100644 index 0000000..9e5882f8 --- /dev/null +++ b/chrome/browser/android/preferences/clipboard_android.cc
@@ -0,0 +1,43 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/preferences/clipboard_android.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/time/time.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/clipboard_android.h" + +namespace { + +void HandleClipboardModified(PrefService* local_state, base::Time time) { + local_state->SetInt64(prefs::kClipboardLastModifiedTime, + time.ToInternalValue()); +} + +} // namespace + +namespace android { + +void RegisterClipboardAndroidPrefs(PrefRegistrySimple* registry) { + registry->RegisterInt64Pref(prefs::kClipboardLastModifiedTime, 0u); +} + +void InitClipboardAndroidFromLocalState(PrefService* local_state) { + DCHECK(local_state); + // Given the context, the cast is guaranteed to succeed. + ui::ClipboardAndroid* clipboard = + static_cast<ui::ClipboardAndroid*>(ui::Clipboard::GetForCurrentThread()); + clipboard->SetLastModifiedTimeWithoutRunningCallback( + base::Time::FromInternalValue( + local_state->GetInt64(prefs::kClipboardLastModifiedTime))); + clipboard->SetModifiedCallback( + base::Bind(&HandleClipboardModified, local_state)); +} + +} // namespace android
diff --git a/chrome/browser/android/preferences/clipboard_android.h b/chrome/browser/android/preferences/clipboard_android.h new file mode 100644 index 0000000..eed04f47 --- /dev/null +++ b/chrome/browser/android/preferences/clipboard_android.h
@@ -0,0 +1,19 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_PREFERENCES_CLIPBOARD_ANDROID_H_ +#define CHROME_BROWSER_ANDROID_PREFERENCES_CLIPBOARD_ANDROID_H_ + +class PrefService; +class PrefRegistrySimple; + +namespace android { + +void RegisterClipboardAndroidPrefs(PrefRegistrySimple* registry); + +void InitClipboardAndroidFromLocalState(PrefService* local_state); + +} // namespace android + +#endif // CHROME_BROWSER_ANDROID_PREFERENCES_CLIPBOARD_ANDROID_H_
diff --git a/chrome/browser/chrome_browser_main_android.cc b/chrome/browser/chrome_browser_main_android.cc index 6617e4f..a788005 100644 --- a/chrome/browser/chrome_browser_main_android.cc +++ b/chrome/browser/chrome_browser_main_android.cc
@@ -12,7 +12,9 @@ #include "base/task_scheduler/post_task.h" #include "base/trace_event/trace_event.h" #include "chrome/browser/android/mojo/chrome_interface_registrar_android.h" +#include "chrome/browser/android/preferences/clipboard_android.h" #include "chrome/browser/android/seccomp_support_detector.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/descriptors_android.h" @@ -97,6 +99,13 @@ content::BrowserThread::FILE, FROM_HERE, base::Bind(&DeleteFileTask, bookmark_image_file_path), base::TimeDelta::FromMinutes(1)); + + // Idempotent. Needs to be called once on startup. If + // InitializeClipboardAndroidFromLocalState() is called multiple times (e.g., + // once per profile load), that's okay; the additional calls don't change + // anything. + android::InitClipboardAndroidFromLocalState(g_browser_process->local_state()); + // Start watching the preferences that need to be backed up backup using // Android backup, so that we create a new backup if they change. backup_watcher_.reset(new chrome::android::ChromeBackupWatcher(profile()));
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 9c5edf8f..e1b39c36 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -377,6 +377,10 @@ PluginsResourceService::RegisterPrefs(registry); #endif +#if defined(OS_ANDROID) + ::android::RegisterPrefs(registry); +#endif + #if !defined(OS_ANDROID) task_manager::TaskManagerInterface::RegisterPrefs(registry); #endif // !defined(OS_ANDROID)
diff --git a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc index c8c7fad..a8c8bff 100644 --- a/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc +++ b/chrome/browser/safe_browsing/safe_browsing_blocking_page_test.cc
@@ -562,26 +562,13 @@ if (!rfh) return VISIBILITY_ERROR; - // clang-format off - std::string jsFindVisibility = R"( - (function isNodeVisible(node) { - if (!node) return 'node not found'; - if (node.offsetWidth === 0 || node.offsetHeight === 0) return false; - // Don't check opacity, since the css transition may actually leave - // opacity at 0 after it's been unhidden - if (node.classList.contains('hidden')) return false; - // Otherwise, we must check all parent nodes - var parentVisibility = isNodeVisible(node.parentElement); - if (parentVisibility === 'node not found') { - return true; // none of the parents are set invisible - } - return parentVisibility; - }(document.getElementById(')" + node_id + R"(')));)"; - // clang-format on - - std::unique_ptr<base::Value> value = - content::ExecuteScriptAndGetValue(rfh, jsFindVisibility); - + std::unique_ptr<base::Value> value = content::ExecuteScriptAndGetValue( + rfh, "var node = document.getElementById('" + node_id + + "');\n" + "if (node)\n" + " node.offsetWidth > 0 && node.offsetHeight > 0;" + "else\n" + " 'node not found';\n"); if (!value.get()) return VISIBILITY_ERROR;
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index a8a5cec..6786c82 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2534,4 +2534,11 @@ const char kSettingsResetPromptLastTriggeredForHomepage[] = "settings_reset_prompt.last_triggered_for_homepage"; +#if defined(OS_ANDROID) +// Timestamp of the clipboard's last modified time, stored in base::Time's +// internal format (int64) in local store. (I.e., this is not a per-profile +// pref.) +const char kClipboardLastModifiedTime[] = "ui.clipboard.last_modified_time"; +#endif + } // namespace prefs
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 44f3d46..04c8bf16 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -912,6 +912,11 @@ extern const char kSettingsResetPromptLastTriggeredForDefaultSearch[]; extern const char kSettingsResetPromptLastTriggeredForStartupUrls[]; extern const char kSettingsResetPromptLastTriggeredForHomepage[]; + +#if defined(OS_ANDROID) +extern const char kClipboardLastModifiedTime[]; +#endif + } // namespace prefs #endif // CHROME_COMMON_PREF_NAMES_H_
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2.css b/components/security_interstitials/core/browser/resources/interstitial_v2.css index d82e6bd..ac09eece 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_v2.css +++ b/components/security_interstitials/core/browser/resources/interstitial_v2.css
@@ -328,10 +328,10 @@ * Details message replaces the top content in its own scrollable area. */ -@media (max-width: 420px) { +@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait) { #details-button { border: 0; - margin: 28px 0 0; + margin: 8px 0 0; } .secondary-button { @@ -342,17 +342,18 @@ /* Fixed nav. */ @media (min-width: 240px) and (max-width: 420px) and - (min-height: 401px), - (min-width: 421px) and (min-height: 240px) and - (max-height: 736px) { + (min-height: 401px) and (max-height: 736px) and (orientation:portrait), + (min-width: 421px) and (max-width: 736px) and (min-height: 240px) and + (max-height: 420px) and (orientation:landscape) { body .nav-wrapper { background: #f7f7f7; bottom: 0; box-shadow: 0 -22px 40px rgb(247, 247, 247); + left: 0; margin: 0; max-width: 736px; - padding-left: 0px; - padding-right: 48px; + padding-left: 24px; + padding-right: 24px; position: fixed; z-index: 2; } @@ -370,14 +371,10 @@ #main-content { padding-bottom: 40px; } - - #details { - padding-top: 5.5vh; - } } -@media (max-width: 420px) and (orientation: portrait), - (max-height: 736px) { +@media (max-width: 420px) and (max-height: 736px) and (orientation: portrait), + (max-width: 736px) and (max-height: 420px) and (orientation: landscape) { body { margin: 0 auto; } @@ -417,7 +414,6 @@ height: 0; opacity: 0; overflow: hidden; - padding-bottom: 0; transition: none; } @@ -432,12 +428,12 @@ } .icon { - margin-bottom: 5.69vh; + margin-bottom: 12px; } .interstitial-wrapper { box-sizing: border-box; - margin: 7vh auto 12px; + margin: 24px auto 12px; padding: 0 24px; position: relative; } @@ -464,34 +460,151 @@ } } -@media (min-width: 421px) and (min-height: 500px) and (max-height: 736px) { - .interstitial-wrapper { - margin-top: 10vh; - } -} - @media (min-height: 400px) and (orientation:portrait) { .interstitial-wrapper { margin-bottom: 145px; } } -@media (min-height: 299px) { +@media (min-height: 299px) and (orientation:portrait) { .nav-wrapper { padding-bottom: 16px; } } -@media (min-height: 500px) and (max-height: 650px) and (max-width: 414px) and - (orientation: portrait) { +@media (min-height: 405px) and (max-height: 736px) and + (max-width: 420px) and (orientation:portrait) { + .icon { + margin-bottom: 24px; + } + .interstitial-wrapper { - margin-top: 7vh; + margin-top: 64px; } } -@media (min-height: 650px) and (max-width: 414px) and (orientation: portrait) { +@media (min-height: 480px) and (max-width: 420px) and + (max-height: 736px) and (orientation: portrait), + (min-height: 338px) and (max-height: 420px) and (max-width: 736px) and + (orientation: landscape) { + .icon { + margin-bottom: 24px; + } + + .nav-wrapper { + padding-bottom: 24px; + } +} + +@media (min-height: 500px) and (max-width: 414px) and (orientation: portrait) { .interstitial-wrapper { - margin-top: 10vh; + margin-top: 96px; + } +} + +/* Phablet sizing */ +@media (min-width: 375px) and (min-height: 641px) and (max-height: 736px) and + (max-width: 414px) and (orientation: portrait) { + button, + [dir='rtl'] button, + .small-link { + font-size: 1em; + padding-bottom: 12px; + padding-top: 12px; + } + + body:not(.offline) .icon { + height: 80px; + width: 80px; + } + + #details-button { + margin-top: 28px; + } + + h1 { + font-size: 1.7em; + } + + .icon { + margin-bottom: 28px; + } + + .interstitial-wrapper { + padding: 28px; + } + + .interstitial-wrapper p { + font-size: 1.05em; + } + + .nav-wrapper { + padding: 28px; + } +} + +@media (min-width: 420px) and (max-width: 736px) and + (min-height: 240px) and (max-height: 298px) and + (orientation:landscape) { + body:not(.offline) .icon { + height: 50px; + width: 50px; + } + + .icon { + padding-top: 0; + } + + .interstitial-wrapper { + margin-top: 16px; + } + + .nav-wrapper { + padding: 0 24px 8px; + } +} + +@media (min-width: 420px) and (max-width: 736px) and + (min-height: 240px) and (max-height: 420px) and + (orientation:landscape) { + #details-button { + margin: 0; + } + + .interstitial-wrapper { + margin-bottom: 70px; + } + + .nav-wrapper { + margin-top: 0; + } + + #extended-reporting-opt-in { + margin-top: 0; + } +} + +/* Phablet landscape */ +@media (min-width: 680px) and (max-height: 414px) { + .interstitial-wrapper { + margin: 24px auto; + } + + .nav-wrapper { + margin: 16px auto 0; + } +} + +@media (max-height: 240px) and (orientation: landscape), + (max-height: 480px) and (orientation: portrait), + (max-width: 419px) and (max-height: 323px) { + body:not(.offline) .icon { + height: 56px; + width: 56px; + } + + .icon { + margin-bottom: 16px; } }
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js b/components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js index 8980099..f2962323 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js +++ b/components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js
@@ -12,9 +12,10 @@ var helpOuterBox = document.querySelector('#details'); var mainContent = document.querySelector('#main-content'); var mediaQuery = '(min-width: 240px) and (max-width: 420px) and ' + - '(min-height: 401px), ' + - '(max-height: 736px) and (min-height: 240px) and ' + - '(min-width: 421px)'; + '(max-height: 736px) and (min-height: 401px) and ' + + '(orientation: portrait), (max-width: 736px) and ' + + '(max-height: 420px) and (min-height: 240px) and ' + + '(min-width: 421px) and (orientation: landscape)'; var detailsHidden = helpOuterBox.classList.contains('hidden'); var runnerContainer = document.querySelector('.runner-container');
diff --git a/infra/config/cq.cfg b/infra/config/cq.cfg index 72fcb3b..b9cb514 100644 --- a/infra/config/cq.cfg +++ b/infra/config/cq.cfg
@@ -3,14 +3,12 @@ version: 1 cq_name: "chromium" +in_production: false cq_status_url: "https://chromium-cq-status.appspot.com" git_repo_url: "https://chromium.googlesource.com/chromium/src" commit_burst_delay: 60 max_commit_burst: 2 -# Drain the CQ (crbug.com/570421) -draining_start_time: "2017-04-27T21:20:30Z" - gerrit {} rietveld { url: "https://codereview.chromium.org"
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc index b33b78f..1852f24 100644 --- a/ui/base/clipboard/clipboard_android.cc +++ b/ui/base/clipboard/clipboard_android.cc
@@ -5,10 +5,12 @@ #include "ui/base/clipboard/clipboard_android.h" #include <algorithm> +#include <utility> #include "base/android/context_utils.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" +#include "base/callback.h" #include "base/lazy_instance.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" @@ -52,6 +54,7 @@ class ClipboardMap { public: ClipboardMap(); + void SetModifiedCallback(ClipboardAndroid::ModifiedCallback cb); std::string Get(const std::string& format); uint64_t GetSequenceNumber() const; base::Time GetLastModifiedTime() const; @@ -62,6 +65,9 @@ void CommitToAndroidClipboard(); void Clear(); + // Unlike the functions above, does not call |modified_cb_|. + void SetLastModifiedTimeWithoutRunningCallback(base::Time time); + private: enum class MapState { kOutOfDate, @@ -69,7 +75,12 @@ kPreparingCommit, }; + // Updates |last_modified_time_| to |time| and writes it to |local_state_|. + void UpdateLastModifiedTime(base::Time time); + + // Updates |map_| and |map_state_| if necessary by fetching data from Java. void UpdateFromAndroidClipboard(); + std::map<std::string, std::string> map_; MapState map_state_; base::Lock lock_; @@ -77,6 +88,8 @@ uint64_t sequence_number_; base::Time last_modified_time_; + ClipboardAndroid::ModifiedCallback modified_cb_; + // Java class and methods for the Android ClipboardManager. ScopedJavaGlobalRef<jobject> clipboard_manager_; }; @@ -87,6 +100,10 @@ DCHECK(clipboard_manager_.obj()); } +void ClipboardMap::SetModifiedCallback(ClipboardAndroid::ModifiedCallback cb) { + modified_cb_ = std::move(cb); +} + std::string ClipboardMap::Get(const std::string& format) { base::AutoLock lock(lock_); UpdateFromAndroidClipboard(); @@ -103,7 +120,7 @@ } void ClipboardMap::ClearLastModifiedTime() { - last_modified_time_ = base::Time(); + UpdateLastModifiedTime(base::Time()); } bool ClipboardMap::HasFormat(const std::string& format) { @@ -114,7 +131,7 @@ void ClipboardMap::OnPrimaryClipboardChanged() { sequence_number_++; - last_modified_time_ = base::Time::Now(); + UpdateLastModifiedTime(base::Time::Now()); map_state_ = MapState::kOutOfDate; } @@ -151,7 +168,7 @@ } map_state_ = MapState::kUpToDate; sequence_number_++; - last_modified_time_ = base::Time::Now(); + UpdateLastModifiedTime(base::Time::Now()); } void ClipboardMap::Clear() { @@ -161,7 +178,11 @@ Java_Clipboard_clear(env, clipboard_manager_); map_state_ = MapState::kUpToDate; sequence_number_++; - last_modified_time_ = base::Time::Now(); + UpdateLastModifiedTime(base::Time::Now()); +} + +void ClipboardMap::SetLastModifiedTimeWithoutRunningCallback(base::Time time) { + last_modified_time_ = time; } // Add a key:jstr pair to map, but only if jstr is not null, and also @@ -177,6 +198,13 @@ } } +void ClipboardMap::UpdateLastModifiedTime(base::Time time) { + last_modified_time_ = time; + // |modified_callback_| may be null in tests. + if (modified_cb_) + modified_cb_.Run(time); +} + void ClipboardMap::UpdateFromAndroidClipboard() { DCHECK_NE(MapState::kPreparingCommit, map_state_); if (map_state_ == MapState::kUpToDate) @@ -303,6 +331,15 @@ g_map.Get().OnPrimaryClipboardChanged(); } +void ClipboardAndroid::SetModifiedCallback(ModifiedCallback cb) { + g_map.Get().SetModifiedCallback(std::move(cb)); +} + +void ClipboardAndroid::SetLastModifiedTimeWithoutRunningCallback( + base::Time time) { + g_map.Get().SetLastModifiedTimeWithoutRunningCallback(time); +} + ClipboardAndroid::ClipboardAndroid() { DCHECK(CalledOnValidThread()); }
diff --git a/ui/base/clipboard/clipboard_android.h b/ui/base/clipboard/clipboard_android.h index 8589e9c..716cc387 100644 --- a/ui/base/clipboard/clipboard_android.h +++ b/ui/base/clipboard/clipboard_android.h
@@ -12,6 +12,7 @@ #include <stdint.h> #include "base/android/scoped_java_ref.h" +#include "base/callback_forward.h" #include "base/macros.h" #include "base/time/time.h" @@ -19,11 +20,22 @@ class ClipboardAndroid : public Clipboard { public: + // Callback called whenever the clipboard is modified. The parameter + // represents the time of the modification. + using ModifiedCallback = base::Callback<void(base::Time)>; + // Called by Java when the Java Clipboard is notified that the clipboard has // changed. void OnPrimaryClipChanged(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + // Sets the callback called whenever the clipboard is modified. + UI_BASE_EXPORT void SetModifiedCallback(ModifiedCallback cb); + + // Sets the last modified time without calling the above callback. + UI_BASE_EXPORT void SetLastModifiedTimeWithoutRunningCallback( + base::Time time); + private: friend class Clipboard;