diff --git a/DEPS b/DEPS index 3fb6298..da2a9e0 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'a86c017d368ab375f49ed8e16bc8d0897cf034a1', + 'v8_revision': '7e6e8430ad10f7ec20095b857dd14eb9525c5872', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '597f96ee44a5845b23057d1576b3694480cc6fa8', + 'catapult_revision': 'c9212cbf522072a1011063b212da5ee7baeb56df', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other.
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index cbb91a3..6781d1ac 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -700,6 +700,9 @@ "//components/printing/common", "//components/printing/renderer", "//components/safe_browsing", + "//components/safe_browsing/browser", + "//components/safe_browsing/common", + "//components/safe_browsing/triggers", "//components/safe_browsing_db:safe_browsing_db_mobile", "//components/spellcheck:build_features", "//components/supervised_user_error_page",
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc index 0835b14..22d70ed 100644 --- a/android_webview/browser/aw_browser_context.cc +++ b/android_webview/browser/aw_browser_context.cc
@@ -29,6 +29,7 @@ #include "components/prefs/in_memory_pref_store.h" #include "components/prefs/pref_service.h" #include "components/prefs/pref_service_factory.h" +#include "components/safe_browsing/triggers/trigger_manager.h" #include "components/url_formatter/url_fixer.h" #include "components/user_prefs/user_prefs.h" #include "components/visitedlink/browser/visitedlink_master.h" @@ -206,9 +207,13 @@ web_restriction_provider_->SetAuthority( user_pref_service_->GetString(prefs::kWebRestrictionsAuthority)); - safe_browsing_ui_manager_ = new AwSafeBrowsingUIManager(); + safe_browsing_ui_manager_ = + new AwSafeBrowsingUIManager(GetAwURLRequestContext()); safe_browsing_db_manager_ = new safe_browsing::RemoteSafeBrowsingDatabaseManager(); + safe_browsing_trigger_manager_ = + base::MakeUnique<safe_browsing::TriggerManager>( + safe_browsing_ui_manager_.get()); } void AwBrowserContext::OnWebRestrictionsAuthorityChanged() { @@ -395,6 +400,12 @@ return safe_browsing_db_manager_.get(); } +safe_browsing::TriggerManager* AwBrowserContext::GetSafeBrowsingTriggerManager() + const { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return safe_browsing_trigger_manager_.get(); +} + void AwBrowserContext::RebuildTable( const scoped_refptr<URLEnumerator>& enumerator) { // Android WebView rebuilds from WebChromeClient.getVisitedHistory. The client
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h index 7e907d0..b2c89e47 100644 --- a/android_webview/browser/aw_browser_context.h +++ b/android_webview/browser/aw_browser_context.h
@@ -42,6 +42,10 @@ class VisitedLinkMaster; } +namespace safe_browsing { +class TriggerManager; +} // namespace safe_browsing + namespace android_webview { class AwFormDatabaseService; @@ -117,6 +121,7 @@ AwSafeBrowsingUIManager* GetSafeBrowsingUIManager(); safe_browsing::RemoteSafeBrowsingDatabaseManager* GetSafeBrowsingDBManager(); + safe_browsing::TriggerManager* GetSafeBrowsingTriggerManager() const; private: void InitUserPrefService(); @@ -150,6 +155,7 @@ PrefChangeRegistrar pref_change_registrar_; scoped_refptr<AwSafeBrowsingUIManager> safe_browsing_ui_manager_; + std::unique_ptr<safe_browsing::TriggerManager> safe_browsing_trigger_manager_; scoped_refptr<safe_browsing::RemoteSafeBrowsingDatabaseManager> safe_browsing_db_manager_; bool safe_browsing_db_manager_started_ = false;
diff --git a/android_webview/browser/aw_browser_main_parts.cc b/android_webview/browser/aw_browser_main_parts.cc index 58e7802..78314275 100644 --- a/android_webview/browser/aw_browser_main_parts.cc +++ b/android_webview/browser/aw_browser_main_parts.cc
@@ -8,6 +8,7 @@ #include "android_webview/browser/aw_browser_terminator.h" #include "android_webview/browser/aw_content_browser_client.h" #include "android_webview/browser/aw_result_codes.h" +#include "android_webview/browser/aw_safe_browsing_config_helper.h" #include "android_webview/browser/deferred_gpu_command_service.h" #include "android_webview/browser/net/aw_network_change_notifier_factory.h" #include "android_webview/common/aw_descriptors.h" @@ -133,6 +134,15 @@ } } + if (AwSafeBrowsingConfigHelper::GetSafeBrowsingEnabled()) { + base::FilePath safe_browsing_dir; + if (PathService::Get(android_webview::DIR_SAFE_BROWSING, + &safe_browsing_dir)) { + if (!base::PathExists(safe_browsing_dir)) + base::CreateDirectory(safe_browsing_dir); + } + } + if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kWebViewSandboxedRenderer)) { // Create the renderers crash manager on the UI thread.
diff --git a/android_webview/browser/aw_safe_browsing_blocking_page.cc b/android_webview/browser/aw_safe_browsing_blocking_page.cc index 7f505a3a..ea80eb1 100644 --- a/android_webview/browser/aw_safe_browsing_blocking_page.cc +++ b/android_webview/browser/aw_safe_browsing_blocking_page.cc
@@ -4,7 +4,9 @@ #include "android_webview/browser/aw_safe_browsing_blocking_page.h" +#include "android_webview/browser/aw_browser_context.h" #include "android_webview/browser/aw_safe_browsing_ui_manager.h" +#include "android_webview/browser/net/aw_url_request_context_getter.h" #include "components/security_interstitials/content/security_interstitial_controller_client.h" #include "components/security_interstitials/content/unsafe_resource.h" #include "components/security_interstitials/core/base_safe_browsing_error_ui.h" @@ -43,6 +45,10 @@ ui_manager->app_locale(), base::Time::NowFromSystemTime(), controller(), errorUiType == ErrorUiType::QUIET_GIANT)); } + + // TODO(timvolodine): invoke TriggerManager::StartCollectingThreatDetails(), + // (via AwBrowserContext, e.g. + // AwBrowserContext::FromWebContents(web_contents)), crbug.com/731747. } // static
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.cc b/android_webview/browser/aw_safe_browsing_ui_manager.cc index cf33463..0dc54b9 100644 --- a/android_webview/browser/aw_safe_browsing_ui_manager.cc +++ b/android_webview/browser/aw_safe_browsing_ui_manager.cc
@@ -5,15 +5,44 @@ #include "android_webview/browser/aw_safe_browsing_ui_manager.h" #include "android_webview/browser/aw_safe_browsing_blocking_page.h" +#include "android_webview/browser/net/aw_url_request_context_getter.h" +#include "android_webview/common/aw_paths.h" +#include "base/command_line.h" +#include "base/path_service.h" +#include "components/safe_browsing/base_ping_manager.h" +#include "components/safe_browsing/base_ui_manager.h" +#include "components/safe_browsing/browser/safe_browsing_url_request_context_getter.h" +#include "components/safe_browsing/common/safebrowsing_constants.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; using content::WebContents; +namespace { + +std::string GetProtocolConfigClientName() { + // Return a webview specific client name, see crbug.com/732373 for details. + return "android_webview"; +} + +} // namespace + namespace android_webview { -AwSafeBrowsingUIManager::AwSafeBrowsingUIManager() { +AwSafeBrowsingUIManager::AwSafeBrowsingUIManager( + AwURLRequestContextGetter* browser_url_request_context_getter) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + + // TODO(timvolodine): verify this is what we want regarding the directory. + base::FilePath user_data_dir; + bool result = + PathService::Get(android_webview::DIR_SAFE_BROWSING, &user_data_dir); + DCHECK(result); + + url_request_context_getter_ = + new safe_browsing::SafeBrowsingURLRequestContextGetter( + browser_url_request_context_getter, user_data_dir); } AwSafeBrowsingUIManager::~AwSafeBrowsingUIManager() {} @@ -47,4 +76,32 @@ return client->GetErrorUiType(); } +void AwSafeBrowsingUIManager::SendSerializedThreatDetails( + const std::string& serialized) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (!ping_manager_) { + // Lazy creation of ping manager, needs to happen on IO thread. + safe_browsing::SafeBrowsingProtocolConfig config; + config.client_name = GetProtocolConfigClientName(); + base::CommandLine* cmdline = ::base::CommandLine::ForCurrentProcess(); + config.disable_auto_update = + cmdline->HasSwitch(::safe_browsing::switches::kSbDisableAutoUpdate); + config.url_prefix = ::safe_browsing::kSbDefaultURLPrefix; + config.backup_connect_error_url_prefix = + ::safe_browsing::kSbBackupConnectErrorURLPrefix; + config.backup_http_error_url_prefix = + ::safe_browsing::kSbBackupHttpErrorURLPrefix; + config.backup_network_error_url_prefix = + ::safe_browsing::kSbBackupNetworkErrorURLPrefix; + ping_manager_ = ::safe_browsing::BasePingManager::Create( + url_request_context_getter_.get(), config); + } + + if (!serialized.empty()) { + DVLOG(1) << "Sending serialized threat details"; + ping_manager_->ReportThreatDetails(serialized); + } +} + } // namespace android_webview
diff --git a/android_webview/browser/aw_safe_browsing_ui_manager.h b/android_webview/browser/aw_safe_browsing_ui_manager.h index 79873c6..263f89a5 100644 --- a/android_webview/browser/aw_safe_browsing_ui_manager.h +++ b/android_webview/browser/aw_safe_browsing_ui_manager.h
@@ -12,7 +12,13 @@ #include "components/safe_browsing/base_ui_manager.h" #include "content/public/browser/web_contents.h" +namespace safe_browsing { +class BasePingManager; +class SafeBrowsingURLRequestContextGetter; +} // namespace + namespace android_webview { +class AwURLRequestContextGetter; class AwSafeBrowsingUIManager : public safe_browsing::BaseUIManager { public: @@ -28,19 +34,33 @@ }; // Construction needs to happen on the UI thread. - AwSafeBrowsingUIManager(); - - void DisplayBlockingPage(const UnsafeResource& resource) override; + explicit AwSafeBrowsingUIManager( + AwURLRequestContextGetter* browser_url_request_context_getter); // Gets the correct ErrorUiType for the web contents int GetErrorUiType(const UnsafeResource& resource) const; + // BaseUIManager methods: + void DisplayBlockingPage(const UnsafeResource& resource) override; + + // Called on the IO thread by the ThreatDetails with the serialized + // protocol buffer, so the service can send it over. + void SendSerializedThreatDetails(const std::string& serialized) override; + protected: ~AwSafeBrowsingUIManager() override; void ShowBlockingPageForResource(const UnsafeResource& resource) override; private: + // Provides phishing and malware statistics. Accessed on IO thread. + std::unique_ptr<safe_browsing::BasePingManager> ping_manager_; + + // The SafeBrowsingURLRequestContextGetter used to access + // |url_request_context_|. Accessed on UI thread. + scoped_refptr<safe_browsing::SafeBrowsingURLRequestContextGetter> + url_request_context_getter_; + DISALLOW_COPY_AND_ASSIGN(AwSafeBrowsingUIManager); };
diff --git a/android_webview/common/aw_paths.cc b/android_webview/common/aw_paths.cc index 2e57b00..390a7be 100644 --- a/android_webview/common/aw_paths.cc +++ b/android_webview/common/aw_paths.cc
@@ -21,6 +21,12 @@ cur = cur.Append(FILE_PATH_LITERAL("WebView")) .Append(FILE_PATH_LITERAL("Crash Reports")); break; + case DIR_SAFE_BROWSING: + if (!base::android::GetCacheDirectory(&cur)) + return false; + cur = cur.Append(FILE_PATH_LITERAL("WebView")) + .Append(FILE_PATH_LITERAL("SafeBrowsing")); + break; default: return false; }
diff --git a/android_webview/common/aw_paths.h b/android_webview/common/aw_paths.h index 7449e6b..52cea85 100644 --- a/android_webview/common/aw_paths.h +++ b/android_webview/common/aw_paths.h
@@ -15,6 +15,9 @@ DIR_CRASH_DUMPS = PATH_START, // Directory where crash dumps are written. + DIR_SAFE_BROWSING, // Directory where safe browsing related cookies are + // stored. + PATH_END };
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt index dcee1c8..f29be24 100644 --- a/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt +++ b/android_webview/tools/system_webview_shell/test/data/webexposed/global-interface-listing-expected.txt
@@ -5166,7 +5166,8 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix +interface WebKitCSSMatrix : DOMMatrixReadOnly + attribute @@toStringTag getter a getter b getter c @@ -5190,16 +5191,18 @@ getter m43 getter m44 method constructor - method inverse - method multiply - method rotate - method rotateAxisAngle - method scale + method invertSelf + method multiplySelf + method preMultiplySelf + method rotateAxisAngleSelf + method rotateFromVectorSelf + method rotateSelf + method scale3dSelf + method scaleSelf method setMatrixValue - method skewX - method skewY - method toString - method translate + method skewXSelf + method skewYSelf + method translateSelf setter a setter b setter c
diff --git a/base/BUILD.gn b/base/BUILD.gn index f1f42b8..f99f960 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2576,7 +2576,6 @@ "android/java/src/org/chromium/base/PackageUtils.java", "android/java/src/org/chromium/base/PathService.java", "android/java/src/org/chromium/base/PathUtils.java", - "android/java/src/org/chromium/base/PerfTraceEvent.java", "android/java/src/org/chromium/base/PowerMonitor.java", "android/java/src/org/chromium/base/Promise.java", "android/java/src/org/chromium/base/ResourceExtractor.java", @@ -2698,7 +2697,6 @@ "test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java", "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java", "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java", - "test/android/javatests/src/org/chromium/base/test/util/PerfTest.java", "test/android/javatests/src/org/chromium/base/test/util/Restriction.java", "test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java", "test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java",
diff --git a/base/android/java/src/org/chromium/base/PerfTraceEvent.java b/base/android/java/src/org/chromium/base/PerfTraceEvent.java deleted file mode 100644 index 8a87773..0000000 --- a/base/android/java/src/org/chromium/base/PerfTraceEvent.java +++ /dev/null
@@ -1,379 +0,0 @@ -// Copyright 2014 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. - -package org.chromium.base; - -import android.os.Debug; -import android.os.Debug.MemoryInfo; -import android.util.Log; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import org.chromium.base.annotations.SuppressFBWarnings; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.util.LinkedList; -import java.util.List; - -/** - * PerfTraceEvent can be used like TraceEvent, but is intended for - * performance measurement. By limiting the types of tracing we hope - * to minimize impact on measurement. - * - * All PerfTraceEvent events funnel into TraceEvent. When not doing - * performance measurements, they act the same. However, - * PerfTraceEvents can be enabled even when TraceEvent is not. - * - * Unlike TraceEvent, PerfTraceEvent data is sent to the system log, - * not to a trace file. - * - * Performance events need to have very specific names so we find - * the right ones. For example, we specify the name exactly in - * the @TracePerf annotation. Thus, unlike TraceEvent, we do not - * support an implicit trace name based on the callstack. - */ -@SuppressFBWarnings("CHROMIUM_SYNCHRONIZED_METHOD") -public class PerfTraceEvent { - private static final int MAX_NAME_LENGTH = 40; - private static final String MEMORY_TRACE_NAME_SUFFIX = "_BZR_PSS"; - private static File sOutputFile; - - /** The event types understood by the perf trace scripts. */ - private enum EventType { - START("S"), - FINISH("F"), - INSTANT("I"); - - // The string understood by the trace scripts. - private final String mTypeStr; - - EventType(String typeStr) { - mTypeStr = typeStr; - } - - @Override - public String toString() { - return mTypeStr; - } - } - - private static boolean sEnabled; - private static boolean sTrackTiming = true; - private static boolean sTrackMemory; - - // A list of performance trace event strings. - // Events are stored as a JSON dict much like TraceEvent. - // E.g. timestamp is in microseconds. - private static JSONArray sPerfTraceStrings; - - // A filter for performance tracing. Only events that match a - // string in the list are saved. Presence of a filter does not - // necessarily mean perf tracing is enabled. - private static List<String> sFilter; - - // Nanosecond start time of performance tracing. - private static long sBeginNanoTime; - - /** - * Specifies what event names will be tracked. - * - * @param strings Event names we will record. - */ - @VisibleForTesting - public static synchronized void setFilter(List<String> strings) { - sFilter = new LinkedList<String>(strings); - } - - /** - * Enable or disable perf tracing. - * Disabling of perf tracing will dump trace data to the system log. - */ - @VisibleForTesting - public static synchronized void setEnabled(boolean enabled) { - if (sEnabled == enabled) { - return; - } - if (enabled) { - sBeginNanoTime = System.nanoTime(); - sPerfTraceStrings = new JSONArray(); - } else { - dumpPerf(); - sPerfTraceStrings = null; - sFilter = null; - } - sEnabled = enabled; - } - - /** - * Enables memory tracking for all timing perf events tracked. - * - * <p> - * Only works when called in combination with {@link #setEnabled(boolean)}. - * - * <p> - * By enabling this feature, an additional perf event containing the memory usage will be - * logged whenever {@link #instant(String)}, {@link #begin(String)}, or {@link #end(String)} - * is called. - * - * @param enabled Whether to enable memory tracking for all perf events. - */ - @VisibleForTesting - public static synchronized void setMemoryTrackingEnabled(boolean enabled) { - sTrackMemory = enabled; - } - - /** - * Enables timing tracking for all perf events tracked. - * - * <p> - * Only works when called in combination with {@link #setEnabled(boolean)}. - * - * <p> - * If this feature is enabled, whenever {@link #instant(String)}, {@link #begin(String)}, - * or {@link #end(String)} is called the time since start of tracking will be logged. - * - * @param enabled Whether to enable timing tracking for all perf events. - */ - @VisibleForTesting - public static synchronized void setTimingTrackingEnabled(boolean enabled) { - sTrackTiming = enabled; - } - - /** - * @return True if tracing is enabled, false otherwise. - * It is safe to call trace methods without checking if PerfTraceEvent - * is enabled. - */ - @VisibleForTesting - public static synchronized boolean enabled() { - return sEnabled; - } - - /** - * Record an "instant" perf trace event. E.g. "screen update happened". - */ - public static synchronized void instant(String name) { - // Instant doesn't really need/take an event id, but this should be okay. - final long eventId = name.hashCode(); - TraceEvent.instant(name); - if (sEnabled && matchesFilter(name)) { - savePerfString(name, eventId, EventType.INSTANT, false); - } - } - - - /** - * Record an "begin" perf trace event. - * Begin trace events should have a matching end event. - */ - @VisibleForTesting - public static synchronized void begin(String name) { - final long eventId = name.hashCode(); - TraceEvent.startAsync(name, eventId); - if (sEnabled && matchesFilter(name)) { - // Done before calculating the starting perf data to ensure calculating the memory usage - // does not influence the timing data. - if (sTrackMemory) { - savePerfString(makeMemoryTraceNameFromTimingName(name), eventId, EventType.START, - true); - } - if (sTrackTiming) { - savePerfString(name, eventId, EventType.START, false); - } - } - } - - /** - * Record an "end" perf trace event, to match a begin event. The - * time delta between begin and end is usually interesting to - * graph code. - */ - @VisibleForTesting - public static synchronized void end(String name) { - final long eventId = name.hashCode(); - TraceEvent.finishAsync(name, eventId); - if (sEnabled && matchesFilter(name)) { - if (sTrackTiming) { - savePerfString(name, eventId, EventType.FINISH, false); - } - // Done after calculating the ending perf data to ensure calculating the memory usage - // does not influence the timing data. - if (sTrackMemory) { - savePerfString(makeMemoryTraceNameFromTimingName(name), eventId, EventType.FINISH, - true); - } - } - } - - /** - * Record an "begin" memory trace event. - * Begin trace events should have a matching end event. - */ - @VisibleForTesting - public static synchronized void begin(String name, MemoryInfo memoryInfo) { - final long eventId = name.hashCode(); - TraceEvent.startAsync(name, eventId); - if (sEnabled && matchesFilter(name)) { - // Done before calculating the starting perf data to ensure calculating the memory usage - // does not influence the timing data. - long timestampUs = (System.nanoTime() - sBeginNanoTime) / 1000; - savePerfString(makeMemoryTraceNameFromTimingName(name), eventId, EventType.START, - timestampUs, memoryInfo); - if (sTrackTiming) { - savePerfString(name, eventId, EventType.START, false); - } - } - } - - /** - * Record an "end" memory trace event, to match a begin event. The - * memory usage delta between begin and end is usually interesting to - * graph code. - */ - @VisibleForTesting - public static synchronized void end(String name, MemoryInfo memoryInfo) { - final long eventId = name.hashCode(); - TraceEvent.finishAsync(name, eventId); - if (sEnabled && matchesFilter(name)) { - if (sTrackTiming) { - savePerfString(name, eventId, EventType.FINISH, false); - } - // Done after calculating the instant perf data to ensure calculating the memory usage - // does not influence the timing data. - long timestampUs = (System.nanoTime() - sBeginNanoTime) / 1000; - savePerfString(makeMemoryTraceNameFromTimingName(name), eventId, EventType.FINISH, - timestampUs, memoryInfo); - } - } - - /** - * Determine if we are interested in this trace event. - * @return True if the name matches the allowed filter; else false. - */ - private static boolean matchesFilter(String name) { - return sFilter != null ? sFilter.contains(name) : false; - } - - /** - * Save a perf trace event as a JSON dict. The format mirrors a TraceEvent dict. - * - * @param name The trace data - * @param id The id of the event - * @param type the type of trace event (I, S, F) - * @param includeMemory Whether to include current browser process memory usage in the trace. - */ - private static void savePerfString(String name, long id, EventType type, - boolean includeMemory) { - long timestampUs = (System.nanoTime() - sBeginNanoTime) / 1000; - MemoryInfo memInfo = null; - if (includeMemory) { - memInfo = new MemoryInfo(); - Debug.getMemoryInfo(memInfo); - } - savePerfString(name, id, type, timestampUs, memInfo); - } - - /** - * Save a perf trace event as a JSON dict. The format mirrors a TraceEvent dict. - * - * @param name The trace data - * @param id The id of the event - * @param type the type of trace event (I, S, F) - * @param timestampUs The time stamp at which this event was recorded - * @param memoryInfo Memory details to be included in this perf string, null if - * no memory details are to be included. - */ - private static void savePerfString(String name, long id, EventType type, long timestampUs, - MemoryInfo memoryInfo) { - try { - JSONObject traceObj = new JSONObject(); - traceObj.put("cat", "Java"); - traceObj.put("ts", timestampUs); - traceObj.put("ph", type); - traceObj.put("name", name); - traceObj.put("id", id); - if (memoryInfo != null) { - int pss = memoryInfo.nativePss + memoryInfo.dalvikPss + memoryInfo.otherPss; - traceObj.put("mem", pss); - } - sPerfTraceStrings.put(traceObj); - } catch (JSONException e) { - throw new RuntimeException(e); - } - } - - /** - * Generating a trace name for tracking memory based on the timing name passed in. - * - * @param name The timing name to use as a base for the memory perf name. - * @return The memory perf name to use. - */ - public static String makeMemoryTraceNameFromTimingName(String name) { - return makeSafeTraceName(name, MEMORY_TRACE_NAME_SUFFIX); - } - - /** - * Builds a name to be used in the perf trace framework. The framework has length requirements - * for names, so this ensures the generated name does not exceed the maximum (trimming the - * base name if necessary). - * - * @param baseName The base name to use when generating the name. - * @param suffix The required suffix to be appended to the name. - * @return A name that is safe for the perf trace framework. - */ - public static String makeSafeTraceName(String baseName, String suffix) { - int suffixLength = suffix.length(); - - if (baseName.length() + suffixLength > MAX_NAME_LENGTH) { - baseName = baseName.substring(0, MAX_NAME_LENGTH - suffixLength); - } - return baseName + suffix; - } - - /** - * Sets a file to dump the results to. If {@code file} is {@code null}, it will be dumped - * to STDOUT, otherwise the JSON performance data will be appended to {@code file}. This should - * be called before the performance run starts. When {@link #setEnabled(boolean)} is called - * with {@code false}, the perf data will be dumped. - * - * @param file Which file to append the performance data to. If {@code null}, the performance - * data will be sent to STDOUT. - */ - @VisibleForTesting - public static synchronized void setOutputFile(File file) { - sOutputFile = file; - } - - /** - * Dump all performance data we have saved up to the log. - * Output as JSON for parsing convenience. - */ - private static void dumpPerf() { - String json = sPerfTraceStrings.toString(); - - if (sOutputFile == null) { - System.out.println(json); - } else { - try { - PrintStream stream = new PrintStream(new FileOutputStream(sOutputFile, true)); - try { - stream.print(json); - } finally { - try { - stream.close(); - } catch (Exception ex) { - Log.e("PerfTraceEvent", "Unable to close perf trace output file."); - } - } - } catch (FileNotFoundException ex) { - Log.e("PerfTraceEvent", "Unable to dump perf trace data to output file."); - } - } - } -}
diff --git a/base/debug/activity_tracker.cc b/base/debug/activity_tracker.cc index 04a293cd..3ff8928 100644 --- a/base/debug/activity_tracker.cc +++ b/base/debug/activity_tracker.cc
@@ -1601,6 +1601,12 @@ process_data_.SetString(key, group_name); } +void GlobalActivityTracker::RecordException(const void* pc, + const void* origin, + uint32_t code) { + RecordExceptionImpl(pc, origin, code); +} + void GlobalActivityTracker::MarkDeleted() { allocator_->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED); }
diff --git a/base/debug/activity_tracker.h b/base/debug/activity_tracker.h index 0a37935..b8eeffd6 100644 --- a/base/debug/activity_tracker.h +++ b/base/debug/activity_tracker.h
@@ -1021,6 +1021,7 @@ return RecordExceptionImpl(::tracked_objects::GetProgramCounter(), origin, code); } + void RecordException(const void* pc, const void* origin, uint32_t code); // Marks the tracked data as deleted. void MarkDeleted();
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java b/base/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java deleted file mode 100644 index 9b3495c..0000000 --- a/base/test/android/javatests/src/org/chromium/base/test/util/PerfTest.java +++ /dev/null
@@ -1,88 +0,0 @@ -// Copyright 2014 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. - -package org.chromium.base.test.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This annotation tells the test harness that this method will be used in a performance test. - * This means that the test harness will use the parameters here to figure out which trace calls - * to track specifically for this test. - * <p> - * Each of the lists ({@link #traceNames()}, {@link #graphNames()}, - * and {@link #seriesNames()}) should have the same number of - * elements. - * <p> - * To write a performance test, you need to do the following: - * <p><ol> - * <li>Add TraceEvent calls to the code that you want to track. - * <ul> - * <li> For FPS, add a TraceEvent.instant call where you want to time and detect calls. - * <li> For code segment timing, add {@link org.chromium.base.TraceEvent#begin()}/ - * {@link org.chromium.base.TraceEvent#end()} calls around the code - * segment (does not have to be in the same method). - * </ul> - * <li> Write a Java Automated UI Test that instruments this code. - * <li> Add this PerfTest annotation to the test method. - * <ul> - * <li> traceNames must be a list of the names of all of the TraceEvent calls you want to track. - * <li> graphNames must be a list, one for each traceName, of which graph the trace data should be - * placed in (does not have to be unique). - * <li> seriesNames must be a list, one for each traceName, of what the series should be called - * for this trace data (has to be unique per graphName). - * <li> When checked in, the buildbots will automatically run this test and the results will show up - * under the Java Automation UI Performance graph, where there will be tabs for each graphName - * specified. - * <li> To test your performance test, run the following command and you should see the performance - * numbers printed to the console. - * </ol> - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface PerfTest { - /** - * @return A list of the trace calls to track. - */ - public String[] traceNames(); - - /** - * @return A list, one for each traceName, that represents which graph this trace call should - * be output on. This does not have to be unique if there are multiple series per - * graph. - */ - public String[] graphNames(); - - /** - * @return A list, one for each traceName, that represents the series this trace call should be - * on the corresponding graph. This should be unique. - */ - public String[] seriesNames(); - - /** - * @return Whether or not we should automatically start and stop tracing for the test. This - * makes it easier to run some tests where tracing is started and stopped at the - * beginning and end of that particular test. - */ - public boolean autoTrace() default false; - - /** - * @return Whether this performance test should track memory usage in addition to time. If - * true, this will track memory usage when tracking time deltas or instants. With each - * graph defined in the annotation for tracking time, this will add an additional graph - * suffixed with a memory identifier containing the same series as those tracking the - * timing performance but instead will be tracking memory consumption. - */ - public boolean traceMemory() default true; - - /** - * @return Whether this performance test should track time or (optionally) only memory. If - * false, this will not automatically track time deltas or instants when logging - * memory info. - */ - public boolean traceTiming() default true; -}
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py index 6f31a33..c1253d9 100644 --- a/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -34,7 +34,7 @@ 'SmallTest', 'MediumTest', 'LargeTest', 'EnormousTest', 'IntegrationTest'] _EXCLUDE_UNLESS_REQUESTED_ANNOTATIONS = [ 'DisabledTest', 'FlakyTest'] -_VALID_ANNOTATIONS = set(['Manual', 'PerfTest'] + _DEFAULT_ANNOTATIONS + +_VALID_ANNOTATIONS = set(['Manual'] + _DEFAULT_ANNOTATIONS + _EXCLUDE_UNLESS_REQUESTED_ANNOTATIONS) _EXTRA_DRIVER_TEST_LIST = ( 'org.chromium.test.driver.OnDeviceInstrumentationDriver.TestList')
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 2b631c60..91fbb27 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1207,6 +1207,8 @@ subtree_property_changed_ = false; inputs_.update_rect = gfx::Rect(); + if (mask_layer()) + DCHECK_EQ(bounds().ToString(), mask_layer()->bounds().ToString()); layer_tree_host_->RemoveLayerShouldPushProperties(this); }
diff --git a/cc/layers/layer_unittest.cc b/cc/layers/layer_unittest.cc index e55c86f4..bd4c508 100644 --- a/cc/layers/layer_unittest.cc +++ b/cc/layers/layer_unittest.cc
@@ -324,8 +324,9 @@ // Should be a different size than previous call, to ensure it marks tree // changed. gfx::Size arbitrary_size = gfx::Size(111, 222); - EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(1); + EXPECT_CALL(*layer_tree_host_, SetNeedsCommit()).Times(2); EXECUTE_AND_VERIFY_SUBTREE_CHANGED(root->SetBounds(arbitrary_size)); + EXECUTE_AND_VERIFY_SUBTREE_CHANGED(dummy_layer1->SetBounds(arbitrary_size)); EXECUTE_AND_VERIFY_SUBTREE_CHANGES_RESET( root->PushPropertiesTo(root_impl.get()); child->PushPropertiesTo(child_impl.get());
diff --git a/cc/test/data/mask_of_larger_layer.png b/cc/test/data/mask_of_larger_layer.png deleted file mode 100644 index d133ebd..0000000 --- a/cc/test/data/mask_of_larger_layer.png +++ /dev/null Binary files differ
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc index 6e013786..1e7cf22 100644 --- a/cc/trees/layer_tree_host_pixeltest_masks.cc +++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -149,41 +149,6 @@ base::FilePath(FILE_PATH_LITERAL("mask_of_clipped_layer.png"))); } -TEST_P(LayerTreeHostMasksPixelTest, MaskOfLargerLayer) { - scoped_refptr<SolidColorLayer> background = - CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE); - - scoped_refptr<SolidColorLayer> green = CreateSolidColorLayerWithBorder( - gfx::Rect(0, 0, 100, 100), kCSSGreen, 1, SK_ColorBLACK); - background->AddChild(green); - - gfx::Size mask_bounds(50, 50); - MaskContentLayerClient client(mask_bounds); - scoped_refptr<PictureLayer> mask = PictureLayer::Create(&client); - mask->SetBounds(mask_bounds); - mask->SetIsDrawable(true); - mask->SetLayerMaskType(mask_type_); - green->SetMaskLayer(mask.get()); - - if (raster_buffer_provider_type_ == RASTER_BUFFER_PROVIDER_TYPE_BITMAP) { - // Bitmap produces a sharper (but equivalent sized) mask. - float percentage_pixels_large_error = 40.0f; - float percentage_pixels_small_error = 0.0f; - float average_error_allowed_in_bad_pixels = 65.0f; - int large_error_allowed = 120; - int small_error_allowed = 0; - pixel_comparator_.reset(new FuzzyPixelComparator( - true, // discard_alpha - percentage_pixels_large_error, percentage_pixels_small_error, - average_error_allowed_in_bad_pixels, large_error_allowed, - small_error_allowed)); - } - - RunPixelResourceTest( - background, - base::FilePath(FILE_PATH_LITERAL("mask_of_larger_layer.png"))); -} - TEST_P(LayerTreeHostMasksPixelTest, MaskOfLayerNonExactTextureSize) { scoped_refptr<SolidColorLayer> background = CreateSolidColorLayer(gfx::Rect(100, 100), SK_ColorWHITE);
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc index 423f812..1bb3e30 100644 --- a/cc/trees/layer_tree_host_unittest.cc +++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1685,6 +1685,7 @@ scoped_refptr<Layer> root = Layer::Create(); root->SetBounds(gfx::Size(10, 10)); child_layer_ = make_scoped_refptr(new UpdateCountingLayer); + child_layer_->SetBounds(gfx::Size(10, 10)); mask_layer_ = make_scoped_refptr(new UpdateCountingLayer); mask_layer_->SetBounds(gfx::Size(10, 10)); child_layer_->SetMaskLayer(mask_layer_.get()); @@ -6991,12 +6992,12 @@ content_layer->AddChild(content_child_layer); std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); + FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(50, 50)); PaintFlags paint1, paint2; static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); + ->add_draw_rect_with_flags(gfx::Rect(0, 0, 50, 40), paint1); static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); + ->add_draw_rect_with_flags(gfx::Rect(0, 40, 50, 10), paint2); client_.set_fill_with_nonsolid_color(true); static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); @@ -7023,7 +7024,7 @@ content_child_layer->SetBounds(child_size); content_child_layer->SetPosition(gfx::PointF(20.f, 0.f)); - gfx::Size mask_size(100, 100); + gfx::Size mask_size(50, 50); mask_layer->SetBounds(mask_size); mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); mask_layer_id_ = mask_layer->id(); @@ -7241,131 +7242,6 @@ SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeTestMultiTextureMaskLayerWithScaling); -class LayerTreeTestMaskLayerWithDifferentBounds : public LayerTreeTest { - protected: - void SetupTree() override { - // The mask layer has bounds 100x100 but is attached to a layer with bounds - // 50x50. - - scoped_refptr<Layer> root = Layer::Create(); - - scoped_refptr<FakePictureLayer> content_layer = - FakePictureLayer::Create(&client_); - root->AddChild(content_layer); - - std::unique_ptr<RecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(gfx::Size(100, 100)); - PaintFlags paint1, paint2; - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 0, 100, 90), paint1); - static_cast<FakeRecordingSource*>(recording_source.get()) - ->add_draw_rect_with_flags(gfx::Rect(0, 90, 100, 10), paint2); - client_.set_fill_with_nonsolid_color(true); - static_cast<FakeRecordingSource*>(recording_source.get())->Rerecord(); - - scoped_refptr<FakePictureLayer> mask_layer = - FakePictureLayer::CreateWithRecordingSource( - &client_, std::move(recording_source)); - content_layer->SetMaskLayer(mask_layer.get()); - - gfx::Size root_size(100, 100); - root->SetBounds(root_size); - - gfx::Size layer_size(50, 50); - content_layer->SetBounds(layer_size); - - gfx::Size mask_size(100, 100); - mask_layer->SetBounds(mask_size); - mask_layer->SetLayerMaskType(Layer::LayerMaskType::MULTI_TEXTURE_MASK); - - layer_tree_host()->SetRootLayer(root); - LayerTreeTest::SetupTree(); - client_.set_bounds(root->bounds()); - } - - void BeginTest() override { PostSetNeedsCommitToMainThread(); } - - DrawResult PrepareToDrawOnThread(LayerTreeHostImpl* host_impl, - LayerTreeHostImpl::FrameData* frame_data, - DrawResult draw_result) override { - EXPECT_EQ(2u, frame_data->render_passes.size()); - RenderPass* root_pass = frame_data->render_passes.back().get(); - EXPECT_EQ(2u, root_pass->quad_list.size()); - - // There's a solid color quad under everything. - EXPECT_EQ(DrawQuad::SOLID_COLOR, root_pass->quad_list.back()->material); - - EXPECT_EQ(DrawQuad::RENDER_PASS, root_pass->quad_list.front()->material); - const RenderPassDrawQuad* render_pass_quad = - RenderPassDrawQuad::MaterialCast(root_pass->quad_list.front()); - switch (host_impl->active_tree()->source_frame_number()) { - case 0: - // Check that the mask fills the surface. - EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - break; - case 1: - // Applying a DSF should change the render surface size, but won't - // affect which part of the mask is used. - EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), - render_pass_quad->rect.ToString()); - if (host_impl->settings().enable_mask_tiling) { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 50.f / 128.f, 50.f / 128.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } else { - EXPECT_EQ(gfx::RectF(0.f, 0.f, 1.f, 1.f).ToString(), - render_pass_quad->mask_uv_rect.ToString()); - } - EndTest(); - break; - } - return draw_result; - } - - void DidCommit() override { - switch (layer_tree_host()->SourceFrameNumber()) { - case 1: - gfx::Size double_root_size(200, 200); - layer_tree_host()->SetViewportSize(double_root_size); - layer_tree_host()->SetDeviceScaleFactor(2.f); - break; - } - } - - void AfterTest() override {} - - FakeContentLayerClient client_; -}; - -class LayerTreeTestSingleTextureMaskLayerWithDifferentBounds - : public LayerTreeTestMaskLayerWithDifferentBounds { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = false; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestSingleTextureMaskLayerWithDifferentBounds); - -class LayerTreeTestMultiTextureMaskLayerWithDifferentBounds - : public LayerTreeTestMaskLayerWithDifferentBounds { - public: - void InitializeSettings(LayerTreeSettings* settings) override { - settings->enable_mask_tiling = true; - } -}; - -SINGLE_AND_MULTI_THREAD_TEST_F( - LayerTreeTestMultiTextureMaskLayerWithDifferentBounds); - class LayerTreeTestMaskWithNonExactTextureSize : public LayerTreeTest { protected: void SetupTree() override {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index 4823a10..20f8297f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -22,7 +22,6 @@ import android.widget.ArrayAdapter; import android.widget.ListPopupWindow; -import org.chromium.base.PerfTraceEvent; import org.chromium.base.VisibleForTesting; import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.chrome.R; @@ -443,7 +442,6 @@ * @return Whether or not animations are done. */ public boolean updateLayout(long time, long dt) { - PerfTraceEvent.instant("StripLayoutHelper:updateLayout"); final boolean doneAnimating = onUpdateAnimation(time, false); updateStrip();
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f25e2a9..21098432 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -856,8 +856,6 @@ "page_load_metrics/observers/previews_page_load_metrics_observer.h", "page_load_metrics/observers/protocol_page_load_metrics_observer.cc", "page_load_metrics/observers/protocol_page_load_metrics_observer.h", - "page_load_metrics/observers/resource_tracking_page_load_metrics_observer.cc", - "page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h", "page_load_metrics/observers/service_worker_page_load_metrics_observer.cc", "page_load_metrics/observers/service_worker_page_load_metrics_observer.h", "page_load_metrics/observers/subresource_filter_metrics_observer.cc",
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc index caf4d3a0..64dd5a3 100644 --- a/chrome/browser/chrome_browser_field_trials_desktop.cc +++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -34,6 +34,7 @@ #include "chrome/install_static/install_util.h" #include "components/browser_watcher/features.h" #include "components/browser_watcher/stability_data_names.h" +#include "components/browser_watcher/stability_debugging.h" #include "components/browser_watcher/stability_metrics.h" #include "components/browser_watcher/stability_paths.h" #endif @@ -188,6 +189,8 @@ // of this, there is no need to flush it here. metrics::GlobalPersistentSystemProfile::GetInstance() ->RegisterPersistentAllocator(global_tracker->allocator()); + + browser_watcher::RegisterStabilityVEH(); } } #endif // defined(OS_WIN)
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index c6dfc3db..efc1b8e 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -1428,17 +1428,6 @@ IncognitoModePrefs::InitializePlatformParentalControls(); #endif -#if BUILDFLAG(ENABLE_EXTENSIONS) - if (!variations::GetVariationParamValue( - "LightSpeed", "EarlyInitStartup").empty()) { - // Try to compute this early on another thread so that we don't spend time - // during profile load initializing the extensions APIs. - BrowserThread::PostTask(BrowserThread::FILE_USER_BLOCKING, FROM_HERE, - base::BindOnce(base::IgnoreResult( - &extensions::FeatureProvider::GetAPIFeatures))); - } -#endif - // Android updates the metrics service dynamically depending on whether the // application is in the foreground or not. Do not start here. #if !defined(OS_ANDROID)
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 3449d44..ee5890e 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3432,6 +3432,10 @@ task_scheduler_util::MaybePerformBrowserTaskSchedulerRedirection(); } +base::FilePath ChromeContentBrowserClient::GetLoggingFileName() { + return logging::GetLogFileName(); +} + // static void ChromeContentBrowserClient::SetDefaultQuotaSettingsForTesting( const storage::QuotaSettings* settings) {
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index c11d7b30..734f7e0 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -317,6 +317,7 @@ std::unique_ptr<base::TaskScheduler::InitParams> GetTaskSchedulerInitParams() override; void PerformExperimentalTaskSchedulerRedirections() override; + base::FilePath GetLoggingFileName() override; private: friend class DisableWebRtcEncryptionFlagTest;
diff --git a/chrome/browser/chrome_content_browser_client_unittest.cc b/chrome/browser/chrome_content_browser_client_unittest.cc index 853335e..53548f6 100644 --- a/chrome/browser/chrome_content_browser_client_unittest.cc +++ b/chrome/browser/chrome_content_browser_client_unittest.cc
@@ -342,3 +342,11 @@ } // namespace content #endif // !defined(OS_ANDROID) + +class ChromeContentBrowserClientGetLoggingFileTest : public testing::Test {}; + +TEST_F(ChromeContentBrowserClientGetLoggingFileTest, GetLoggingFile) { + ChromeContentBrowserClient client; + base::FilePath log_file_name; + EXPECT_FALSE(client.GetLoggingFileName().empty()); +}
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 5d01795..01148fcd 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -278,12 +278,6 @@ DBusThreadManager::Get()->GetPowerManagerClient()); CrosDBusService::ServiceProviderList service_providers; - // TODO(derat): Remove this provider once all callers are using - // |proxy_resolution_service_| instead: http://crbug.com/703217 - service_providers.push_back( - base::MakeUnique<ProxyResolutionServiceProvider>( - kLibCrosServiceInterface, kResolveNetworkProxy, - base::MakeUnique<ChromeProxyResolutionServiceProviderDelegate>())); if (GetAshConfig() == ash::Config::CLASSIC) { // TODO(crbug.com/629707): revisit this with mustash dbus work. service_providers.push_back(base::MakeUnique<DisplayPowerServiceProvider>( @@ -313,8 +307,6 @@ kNetworkProxyServiceName, dbus::ObjectPath(kNetworkProxyServicePath), CrosDBusService::CreateServiceProviderList( base::MakeUnique<ProxyResolutionServiceProvider>( - kNetworkProxyServiceInterface, - kNetworkProxyServiceResolveProxyMethod, base::MakeUnique< ChromeProxyResolutionServiceProviderDelegate>())));
diff --git a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc index 675f657..f4bbeb0 100644 --- a/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc +++ b/chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.cc
@@ -1380,6 +1380,11 @@ std::unique_ptr<user_manager::UserImage>* result_out, MovableOnDestroyCallbackHolder on_finish, std::unique_ptr<user_manager::UserImage> user_image) { + if (user_image->image().isNull()) { + LOG(ERROR) << "Failed to decode default wallpaper. "; + return; + } + *result_out = std::move(user_image); SetWallpaper((*result_out)->image(), layout); }
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 8f1aa9c4..b7e1508 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -360,7 +360,14 @@ ASSERT_TRUE(catcher.GetNextResult()) << catcher.message(); } -IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestDeclarative1) { +// This test times out regularly on MSAN trybots. See http://crbug.com/733395. +#if defined(MEMORY_SANITIZER) +#define MAYBE_WebRequestDeclarative1 DISABLED_WebRequestDeclarative1 +#else +#define MAYBE_WebRequestDeclarative1 WebRequestDeclarative1 +#endif +IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, + MAYBE_WebRequestDeclarative1) { ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative1.html")) << message_;
diff --git a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc index 42a5568..a3ea43e 100644 --- a/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc +++ b/chrome/browser/loader/chrome_resource_dispatcher_host_delegate.cc
@@ -349,28 +349,6 @@ } } -void NotifyUIThreadOfRequestStarted( - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - const content::GlobalRequestID& request_id, - ResourceType resource_type, - bool is_download, - base::TimeTicks request_creation_time) { - content::WebContents* web_contents = web_contents_getter.Run(); - if (!web_contents) - return; - - if (!is_download) { - page_load_metrics::MetricsWebContentsObserver* metrics_observer = - page_load_metrics::MetricsWebContentsObserver::FromWebContents( - web_contents); - - if (metrics_observer) { - metrics_observer->OnRequestStarted(request_id, resource_type, - request_creation_time); - } - } -} - void NotifyUIThreadOfRequestComplete( const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, const content::ResourceRequestInfo::FrameTreeNodeIdGetter& @@ -480,16 +458,6 @@ const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request); - // TODO(petewil): Unify the safe browsing request and the metrics observer - // request if possible so we only have to cross to the main thread once. - // http://crbug.com/712312. - BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::Bind(&NotifyUIThreadOfRequestStarted, - info->GetWebContentsGetterForRequest(), - info->GetGlobalRequestID(), info->GetResourceType(), - info->IsDownload(), request->creation_time())); - ProfileIOData* io_data = ProfileIOData::FromResourceContext( resource_context);
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc index b5a5ce6..f7835a84f0 100644 --- a/chrome/browser/metrics/chrome_metrics_services_manager_client.cc +++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.cc
@@ -246,12 +246,6 @@ return enabled_state_provider_->IsReportingEnabled(); } -bool ChromeMetricsServicesManagerClient::OnlyDoMetricsRecording() { - const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - return cmdline->HasSwitch(switches::kMetricsRecordingOnly) || - cmdline->HasSwitch(switches::kEnableBenchmarking); -} - #if defined(OS_WIN) void ChromeMetricsServicesManagerClient::UpdateRunningServices( bool may_record,
diff --git a/chrome/browser/metrics/chrome_metrics_services_manager_client.h b/chrome/browser/metrics/chrome_metrics_services_manager_client.h index ae5947d..24014ac 100644 --- a/chrome/browser/metrics/chrome_metrics_services_manager_client.h +++ b/chrome/browser/metrics/chrome_metrics_services_manager_client.h
@@ -72,7 +72,6 @@ CreateEntropyProvider() override; net::URLRequestContextGetter* GetURLRequestContext() override; bool IsMetricsReportingEnabled() override; - bool OnlyDoMetricsRecording() override; #if defined(OS_WIN) // On Windows, the client controls whether Crashpad can upload crash reports.
diff --git a/chrome/browser/metrics/metrics_service_browsertest.cc b/chrome/browser/metrics/metrics_service_browsertest.cc index c2367bd..1e971e7 100644 --- a/chrome/browser/metrics/metrics_service_browsertest.cc +++ b/chrome/browser/metrics/metrics_service_browsertest.cc
@@ -19,11 +19,11 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/metrics/metrics_pref_names.h" +#include "components/metrics/metrics_switches.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test_utils.h" #include "net/base/filename_util.h" @@ -72,7 +72,7 @@ public: void SetUpCommandLine(base::CommandLine* command_line) override { // Enable the metrics service for testing (in recording-only mode). - command_line->AppendSwitch(switches::kMetricsRecordingOnly); + command_line->AppendSwitch(metrics::switches::kMetricsRecordingOnly); } // Open three tabs then navigate to |crashy_url| and wait for the renderer to
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc index feb2898..ef05b3f 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -283,24 +283,6 @@ return nullptr; } -void MetricsWebContentsObserver::OnRequestStarted( - const content::GlobalRequestID& request_id, - content::ResourceType resource_type, - base::TimeTicks creation_time) { - // Note for the main HTML page, the tracker may not exist yet, so - // OnStartedResource will not be called for the main page. While the main - // page is not being tracked today, if we do decide to track it, we will need - // to first make sure that GlobalRequestID is set in an earlier callback. - // TODO(bmcquade): Evaluate whether moving tracker creation to - // DidStartNavigation would address this. - PageLoadTracker* tracker = - GetTrackerOrNullForRequest(request_id, resource_type, creation_time); - if (tracker) { - ExtraRequestStartInfo extra_request_start_info(resource_type); - tracker->OnStartedResource(extra_request_start_info); - } -} - void MetricsWebContentsObserver::OnRequestComplete( const GURL& url, const net::HostPortPair& host_port_pair,
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h index ad72ba5..a57a65e 100644 --- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h +++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -104,12 +104,6 @@ void WillProcessNavigationResponse( content::NavigationHandle* navigation_handle); - // A resource request started on the IO thread. This method is invoked on - // the UI thread. - void OnRequestStarted(const content::GlobalRequestID& request_id, - content::ResourceType resource_type, - base::TimeTicks creation_time); - // A resource request completed on the IO thread. This method is invoked on // the UI thread. void OnRequestComplete(
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc index 00933a7..e01e847 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.cc
@@ -90,12 +90,6 @@ mock_timer->Fire(); } -void PageLoadMetricsObserverTestHarness::SimulateStartedResource( - const ExtraRequestStartInfo& info) { - observer_->OnRequestStarted(content::GlobalRequestID(), info.resource_type, - base::TimeTicks::Now()); -} - void PageLoadMetricsObserverTestHarness::SimulateLoadedResource( const ExtraRequestCompleteInfo& info) { observer_->OnRequestComplete(
diff --git a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h index 79c2ce5..a5f3a03 100644 --- a/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h +++ b/chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h
@@ -56,9 +56,6 @@ const mojom::PageLoadMetadata& metadata); // Simulates a loaded resource. - void SimulateStartedResource(const ExtraRequestStartInfo& info); - - // Simulates a loaded resource. void SimulateLoadedResource(const ExtraRequestCompleteInfo& info); // Simulates a user input.
diff --git a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.cc deleted file mode 100644 index 1f74a34..0000000 --- a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// 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/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h" - -namespace page_load_metrics { - -ResourceTrackingPageLoadMetricsObserver:: - ResourceTrackingPageLoadMetricsObserver() - : started_count_(0), completed_count_(0) {} -ResourceTrackingPageLoadMetricsObserver:: - ~ResourceTrackingPageLoadMetricsObserver() {} - -void ResourceTrackingPageLoadMetricsObserver::OnStartedResource( - const ExtraRequestStartInfo& extra_request_start_info) { - // TODO(petewiL): Store this by type. - ++started_count_; -} - -void ResourceTrackingPageLoadMetricsObserver::OnLoadedResource( - const ExtraRequestCompleteInfo& extra_request_complete_info) { - // TODO(petewil): Check to see if the type of the request changed. If it did, - // update the old and new types for the started type. Then update by type for - // the completed type. - ++completed_count_; -} - -void ResourceTrackingPageLoadMetricsObserver::GetCountsForTypeForTesting( - const content::ResourceType type, - int64_t* started_count, - int64_t* completed_count) { - if (started_count != nullptr) - *started_count = started_count_; - if (completed_count != nullptr) - *completed_count = completed_count_; -} - -} // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h deleted file mode 100644 index 58e8d87..0000000 --- a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h +++ /dev/null
@@ -1,49 +0,0 @@ -// 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_PAGE_LOAD_METRICS_OBSERVERS_RESOURCE_TRACKING_PAGE_LOAD_METRICS_OBSERVER_H_ -#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_RESOURCE_TRACKING_PAGE_LOAD_METRICS_OBSERVER_H_ - -#include <stdint.h> - -#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" - -namespace page_load_metrics { - -class ResourceTrackingPageLoadMetricsObserver - : public page_load_metrics::PageLoadMetricsObserver { - public: - ResourceTrackingPageLoadMetricsObserver(); - ~ResourceTrackingPageLoadMetricsObserver() override; - - // Called by the PageLoadMetrics framework when we start a new request, so we - // can update our data structures to be able to calculate a resource done - // percentage. - void OnStartedResource( - const ExtraRequestStartInfo& extra_request_start_info) override; - - // Called by the PageLoadMetrics framework when we start a new request, so we - // can update our data structures to be able to calculate a resource done - // percentage. - void OnLoadedResource( - const ExtraRequestCompleteInfo& extra_request_complete_info) override; - - // For the specified type, get the count of requests started and completed. - // TODO(petewil) Note that type is not used yet, code to use it is coming - // soon. - void GetCountsForTypeForTesting(const content::ResourceType type, - int64_t* started_count, - int64_t* completed_count); - - private: - // TODO(petewil): Some way to keep track of what we've seen - // TODO(petewil): Some way to inform our keeper of aggregate results when they - // change. - int64_t started_count_; - int64_t completed_count_; -}; - -} // namespace page_load_metrics - -#endif // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_RESOURCE_TRACKING_PAGE_LOAD_METRICS_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer_unittest.cc deleted file mode 100644 index 7f8d5a2a..0000000 --- a/chrome/browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer_unittest.cc +++ /dev/null
@@ -1,77 +0,0 @@ -// 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/page_load_metrics/observers/resource_tracking_page_load_metrics_observer.h" - -#include "chrome/browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h" - -namespace { -const char kFakeUrl[] = "http://www.google.com/nothingotseehere.html"; -} // namespace - -namespace page_load_metrics { - -class ResourceTrackingPageLoadMetricsObserverTest - : public page_load_metrics::PageLoadMetricsObserverTestHarness { - public: - ResourceTrackingPageLoadMetricsObserverTest() : observer_(nullptr) {} - - protected: - void RegisterObservers(page_load_metrics::PageLoadTracker* tracker) override { - std::unique_ptr<page_load_metrics::ResourceTrackingPageLoadMetricsObserver> - observer( - new page_load_metrics::ResourceTrackingPageLoadMetricsObserver()); - // Keep track of the observer pointer so we can check it in the unit test. - observer_ = observer.get(); - tracker->AddObserver(std::move(observer)); - } - - page_load_metrics::ResourceTrackingPageLoadMetricsObserver* observer() { - return observer_; - } - - private: - // observer_ is owned by the last created PageLoadTracker, and its lifetime is - // dictated by that tracker's lifetime. - page_load_metrics::ResourceTrackingPageLoadMetricsObserver* observer_; -}; - -TEST_F(ResourceTrackingPageLoadMetricsObserverTest, StartAndFinish) { - page_load_metrics::ExtraRequestStartInfo start_info_1{ - content::ResourceType::RESOURCE_TYPE_IMAGE}; - - page_load_metrics::ExtraRequestStartInfo start_info_2{ - content::ResourceType::RESOURCE_TYPE_IMAGE}; - - page_load_metrics::ExtraRequestCompleteInfo done_info{ - GURL(), - net::HostPortPair(), - -1 /*frame_tree_node_id*/, - false /*was_cached*/, - 1024 * 40 /* raw_body_bytes */, - 1024 * 40 /* original_network_content_length */, - nullptr /* data reduction_proxy */, - content::ResourceType::RESOURCE_TYPE_IMAGE, - 0, - }; - - // Start the navigation. This will create the page load tracker and register - // the observers. - NavigateAndCommit(GURL(kFakeUrl)); - - // Simulate starting two images, and completing one. - SimulateStartedResource(start_info_1); - SimulateStartedResource(start_info_2); - SimulateLoadedResource(done_info); - - int64_t started = -1; - int64_t completed = -1; - EXPECT_NE(nullptr, observer()); - observer()->GetCountsForTypeForTesting( - content::ResourceType::RESOURCE_TYPE_IMAGE, &started, &completed); - EXPECT_EQ(2, started); - EXPECT_EQ(1, completed); -} - -} // namespace page_load_metrics
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc index 54e0435..fc708c4 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.cc
@@ -81,14 +81,6 @@ ExtraRequestCompleteInfo::~ExtraRequestCompleteInfo() {} -ExtraRequestStartInfo::ExtraRequestStartInfo(content::ResourceType found_type) - : resource_type(found_type) {} - -ExtraRequestStartInfo::ExtraRequestStartInfo( - const ExtraRequestStartInfo& other) = default; - -ExtraRequestStartInfo::~ExtraRequestStartInfo() {} - FailedProvisionalLoadInfo::FailedProvisionalLoadInfo(base::TimeDelta interval, net::Error error) : time_to_failed_provisional_load(interval), error(error) {}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h index 4117133..9ee8b5d 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -256,21 +256,6 @@ int net_error; }; -// Container for various information about a started request within a page load. -struct ExtraRequestStartInfo { - explicit ExtraRequestStartInfo(content::ResourceType type); - - ExtraRequestStartInfo(const ExtraRequestStartInfo& other); - - ~ExtraRequestStartInfo(); - - // The type of the request as gleaned from the DOM or the file extension. This - // may be less accurate than the type at request completion time, which has - // access to mime-type headers. During XHRs, we sometimes see resources come - // back as a different type than we expected. - const content::ResourceType resource_type; -}; - // Interface for PageLoadMetrics observers. All instances of this class are // owned by the PageLoadTracker tracking a page load. class PageLoadMetricsObserver { @@ -459,10 +444,6 @@ const FailedProvisionalLoadInfo& failed_provisional_load_info, const PageLoadExtraInfo& extra_info) {} - // Called whenever a request load begins. - virtual void OnStartedResource( - const ExtraRequestStartInfo& extra_request_start_info) {} - // Called whenever a request is loaded for this page load. This comes // unfiltered from the ResourceDispatcherHost and may include blob requests // and data uris.
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc index 9f83e20f..6847eeb 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.cc +++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -418,13 +418,6 @@ } } -void PageLoadTracker::OnStartedResource( - const ExtraRequestStartInfo& extra_request_start_info) { - for (const auto& observer : observers_) { - observer->OnStartedResource(extra_request_start_info); - } -} - void PageLoadTracker::OnLoadedResource( const ExtraRequestCompleteInfo& extra_request_complete_info) { for (const auto& observer : observers_) {
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h index 4a849c77..f8185b0 100644 --- a/chrome/browser/page_load_metrics/page_load_tracker.h +++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -191,9 +191,6 @@ void NotifyClientRedirectTo(const PageLoadTracker& destination); - void OnStartedResource( - const ExtraRequestStartInfo& extra_request_started_info); - void OnLoadedResource( const ExtraRequestCompleteInfo& extra_request_complete_info);
diff --git a/chrome/browser/resources/offline_pages/offline_internals.css b/chrome/browser/resources/offline_pages/offline_internals.css index b37a1dc9b..534ae985 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.css +++ b/chrome/browser/resources/offline_pages/offline_internals.css
@@ -50,3 +50,8 @@ #current-status { font-size: 15px; } + +.dump { + font-family: monospace; + white-space: pre-wrap; +}
diff --git a/chrome/browser/resources/offline_pages/offline_internals.html b/chrome/browser/resources/offline_pages/offline_internals.html index e2d5355..a90859c 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.html +++ b/chrome/browser/resources/offline_pages/offline_internals.html
@@ -60,7 +60,7 @@ </thead> <tbody id="stored-pages"> </tbody> </table> - <div id="page-actions-info"></div> + <div id="page-actions-info" class="dump"></div> <h2>Request Queue</h2> <div> @@ -78,7 +78,7 @@ </thead> <tbody id="request-queue"> </tbody> </table> - <div id="request-queue-actions-info"></div> + <div id="request-queue-actions-info" class="dump"></div> <input id="url" type="url" placeholder="http://www.url1.com, http://www.url2.com, ..."> <button id="add-to-queue">Load in background</button> @@ -90,6 +90,17 @@ <button id="schedule-nwake">Schedule NWake</button> <button id="cancel-nwake">Cancel NWake</button> </div> + <div> + <input id="generate-urls" type="text" + placeholder="http://www.url1.com, http://www.url2.com, ..."> + <button id="generate-page-bundle">Generate Page Bundle</button> + </div> + <div> + <input id="operation-name" type="text" + placeholder="operations/1234-5678"> + <button id="get-operation">Get Operation</button> + </div> </div> + <div id="prefetch-actions-info" class="dump"></div> </body> </html>
diff --git a/chrome/browser/resources/offline_pages/offline_internals.js b/chrome/browser/resources/offline_pages/offline_internals.js index b01b0a322..0f03bcf 100644 --- a/chrome/browser/resources/offline_pages/offline_internals.js +++ b/chrome/browser/resources/offline_pages/offline_internals.js
@@ -178,6 +178,14 @@ browserProxy.getRequestQueue().then(fillRequestQueue); } + /** + * Callback for prefetch actions. + * @param {string} info The result of performing the prefetch actions. + */ + function setPrefetchResult(info) { + $('prefetch-actions-info').textContent = info; + } + /** * Downloads all the stored page and request queue information into a file. * TODO(chili): Create a CSV writer that can abstract out the line joining. @@ -317,10 +325,18 @@ } }; $('schedule-nwake').onclick = function() { - browserProxy.scheduleNwake(); + browserProxy.scheduleNwake().then(setPrefetchResult); }; $('cancel-nwake').onclick = function() { - browserProxy.cancelNwake(); + browserProxy.cancelNwake().then(setPrefetchResult); + }; + $('generate-page-bundle').onclick = function() { + browserProxy.generatePageBundle($('generate-urls').value). + then(setPrefetchResult); + }; + $('get-operation').onclick = function() { + browserProxy.getOperation($('operation-name').value). + then(setPrefetchResult); }; if (!incognito) refreshAll();
diff --git a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js index 6e1ad1f..4066134 100644 --- a/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js +++ b/chrome/browser/resources/offline_pages/offline_internals_browser_proxy.js
@@ -131,6 +131,20 @@ * @return {!Promise} A promise firing when the task has been cancelled. */ cancelNwake: function() {}, + + /** + * Sends and processes a request to generate page bundle. + * @param {string} urls A list of comma-separated URLs. + * @return {!Promise<string>} A string describing the result. + */ + generatePageBundle: function(urls) {}, + + /** + * Sends and processes a request to get operation. + * @param {string} name Name of operation. + * @return {!Promise<string>} A string describing the result. + */ + getOperation: function(name) {}, }; /** @@ -205,6 +219,16 @@ cancelNwake: function() { return cr.sendWithPromise('cancelNwake'); }, + + /** @override */ + generatePageBundle: function(urls) { + return cr.sendWithPromise('generatePageBundle', urls); + }, + + /** @override */ + getOperation: function(name) { + return cr.sendWithPromise('getOperation', name); + }, }; return {
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index 7aa5974e..63d8b7a1 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -673,7 +673,11 @@ if (origin == print_preview.DestinationOrigin.LOCAL || origin == print_preview.DestinationOrigin.CROS) { - this.nativeLayer_.startGetLocalDestinationCapabilities(id); + this.nativeLayer_.getPrinterCapabilities(id).then( + this.onLocalDestinationCapabilitiesSet_.bind(this), + this.onGetCapabilitiesFail_.bind(this, + /** @type {print_preview.DestinationOrigin} */ (origin), + id)); return true; } @@ -959,17 +963,26 @@ // Notify about selected destination change. cr.dispatchSimpleEvent( this, DestinationStore.EventType.DESTINATION_SELECT); - // Request destination capabilities, of not known yet. + // Request destination capabilities from backend, since they are not + // known yet. if (destination.capabilities == null) { if (destination.isPrivet) { - this.nativeLayer_.startGetPrivetDestinationCapabilities( - destination.id); + this.nativeLayer_.getPrivetPrinterCapabilities(destination.id).then( + this.onPrivetCapabilitiesSet_.bind(this), + this.onGetCapabilitiesFail_.bind(this, destination.origin, + destination.id)); } else if (destination.isExtension) { - this.nativeLayer_.startGetExtensionDestinationCapabilities( - destination.id); + this.nativeLayer_.getExtensionPrinterCapabilities(destination.id) + .then( + this.onExtensionCapabilitiesSet_.bind(this, destination.id), + this.onGetCapabilitiesFail_.bind(this, destination.origin, + destination.id) + ); } else if (destination.isLocal) { - this.nativeLayer_.startGetLocalDestinationCapabilities( - destination.id); + this.nativeLayer_.getPrinterCapabilities(destination.id).then( + this.onLocalDestinationCapabilitiesSet_.bind(this), + this.onGetCapabilitiesFail_.bind(this, destination.origin, + destination.id)); } else { assert(this.cloudPrintInterface_ != null, 'Cloud destination selected, but GCP is not enabled'); @@ -1337,26 +1350,10 @@ var nativeLayerEventTarget = this.nativeLayer_.getEventTarget(); this.tracker_.add( nativeLayerEventTarget, - print_preview.NativeLayer.EventType.CAPABILITIES_SET, - this.onLocalDestinationCapabilitiesSet_.bind(this)); - this.tracker_.add( - nativeLayerEventTarget, - print_preview.NativeLayer.EventType.GET_CAPABILITIES_FAIL, - this.onGetCapabilitiesFail_.bind(this)); - this.tracker_.add( - nativeLayerEventTarget, print_preview.NativeLayer.EventType.DESTINATIONS_RELOAD, this.onDestinationsReload_.bind(this)); this.tracker_.add( nativeLayerEventTarget, - print_preview.NativeLayer.EventType.PRIVET_CAPABILITIES_SET, - this.onPrivetCapabilitiesSet_.bind(this)); - this.tracker_.add( - nativeLayerEventTarget, - print_preview.NativeLayer.EventType.EXTENSION_CAPABILITIES_SET, - this.onExtensionCapabilitiesSet_.bind(this)); - this.tracker_.add( - nativeLayerEventTarget, print_preview.NativeLayer.EventType.PROVISIONAL_DESTINATION_RESOLVED, this.handleProvisionalDestinationResolved_.bind(this)); }, @@ -1419,14 +1416,14 @@ * local destination. Updates the destination with new capabilities if the * destination already exists, otherwise it creates a new destination and * then updates its capabilities. - * @param {Event} event Contains the capabilities of the local print - * destination. + * @param {print_preview.PrinterCapabilitiesResponse} settingsInfo Contains + * information about and capabilities of the local print destination. * @private */ - onLocalDestinationCapabilitiesSet_: function(event) { - var destinationId = event.settingsInfo['printerId']; - var printerName = event.settingsInfo['printerName']; - var printerDescription = event.settingsInfo['printerDescription']; + onLocalDestinationCapabilitiesSet_: function(settingsInfo) { + var destinationId = settingsInfo['printerId']; + var printerName = settingsInfo['printerName']; + var printerDescription = settingsInfo['printerDescription']; // PDF is special since we don't need to query the device for // capabilities. var origin = destinationId == @@ -1438,7 +1435,7 @@ ''); var destination = this.destinationMap_[key]; var capabilities = DestinationStore.localizeCapabilities_( - event.settingsInfo.capabilities); + settingsInfo.capabilities); // Special case for PDF printer (until local printers capabilities are // reported in CDD format too). if (destinationId == @@ -1455,7 +1452,7 @@ } destination.capabilities = capabilities; } else { - var isEnterprisePrinter = event.settingsInfo['cupsEnterprisePrinter']; + var isEnterprisePrinter = settingsInfo['cupsEnterprisePrinter']; destination = print_preview.LocalDestinationParser.parse( {deviceName: destinationId, printerName: printerName, @@ -1477,15 +1474,17 @@ * Called when a request to get a local destination's print capabilities * fails. If the destination is the initial destination, auto-select another * destination instead. - * @param {Event} event Contains the destination ID that failed. + * @param {print_preview.DestinationOrigin} origin The origin type of the + * failed destination. + * @param {string} destinationId The destination ID that failed. * @private */ - onGetCapabilitiesFail_: function(event) { + onGetCapabilitiesFail_: function(origin, destinationId) { console.warn('Failed to get print capabilities for printer ' + - event.destinationId); + destinationId); if (this.autoSelectMatchingDestination_ && this.autoSelectMatchingDestination_.matchIdAndOrigin( - event.destinationId, event.destinationOrigin)) { + destinationId, origin)) { this.selectDefaultDestination_(); } }, @@ -1575,14 +1574,15 @@ /** * Called when capabilities for a privet printer are set. - * @param {Object} event Contains the capabilities and printer ID. + * @param {!print_preview.PrivetPrinterCapabilitiesResponse} printerInfo + * Contains the privet printer's description and capabilities. * @private */ - onPrivetCapabilitiesSet_: function(event) { + onPrivetCapabilitiesSet_: function(printerInfo) { var destinations = - print_preview.PrivetDestinationParser.parse(event.printer); + print_preview.PrivetDestinationParser.parse(printerInfo.printer); destinations.forEach(function(dest) { - dest.capabilities = event.capabilities; + dest.capabilities = printerInfo.capabilities; this.updateDestination_(dest); }, this); }, @@ -1617,18 +1617,19 @@ /** * Called when capabilities for an extension managed printer are set. - * @param {Object} event Contains the printer's capabilities and ID. + * @param {string} printerId The printer Id. + * @param {!print_preview.Cdd} capabilities The printer's capabilities. * @private */ - onExtensionCapabilitiesSet_: function(event) { + onExtensionCapabilitiesSet_: function(printerId, capabilities) { var destinationKey = this.getDestinationKey_( print_preview.DestinationOrigin.EXTENSION, - event.printerId, + printerId, '' /* account */); var destination = this.destinationMap_[destinationKey]; if (!destination) return; - destination.capabilities = event.capabilities; + destination.capabilities = capabilities; this.updateDestination_(destination); },
diff --git a/chrome/browser/resources/print_preview/data/local_parsers.js b/chrome/browser/resources/print_preview/data/local_parsers.js index 97cceab..cb34a4a 100644 --- a/chrome/browser/resources/print_preview/data/local_parsers.js +++ b/chrome/browser/resources/print_preview/data/local_parsers.js
@@ -38,7 +38,8 @@ /** * Parses a privet destination as one or more local printers. - * @param {!Object} destinationInfo Object that describes a privet printer. + * @param {!print_preview.PrivetPrinterDescription} destinationInfo Object + * that describes a privet printer. * @return {!Array<!print_preview.Destination>} Parsed destination info. */ PrivetDestinationParser.parse = function(destinationInfo) {
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index f259e5e..f4e6984 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -29,6 +29,37 @@ /** * @typedef {{ * printerId: string, + * printerName: string, + * printerDescription: string, + * cupsEnterprisePrinter: (boolean | undefined), + * capabilities: !print_preview.Cdd, + * }} + */ +print_preview.PrinterCapabilitiesResponse; + +/** + * @typedef {{ + * serviceName: string, + * name: string, + * hasLocalPrinting: boolean, + * isUnregistered: boolean, + * cloudID: string, + * }} + * @see PrintPreviewHandler::FillPrinterDescription in print_preview_handler.cc + */ +print_preview.PrivetPrinterDescription; + +/** + * @typedef {{ + * printer: !print_preview.PrivetPrinterDescription, + * capabilities: !print_preview.Cdd, + * }} + */ +print_preview.PrivetPrinterCapabilitiesResponse; + +/** + * @typedef {{ + * printerId: string, * success: boolean, * capabilities: Object, * }} @@ -45,14 +76,6 @@ function NativeLayer() { // Bind global handlers global.setUseCloudPrint = this.onSetUseCloudPrint_.bind(this); - global.updateWithPrinterCapabilities = - this.onUpdateWithPrinterCapabilities_.bind(this); - global.failedToGetPrinterCapabilities = - this.onFailedToGetPrinterCapabilities_.bind(this); - global.failedToGetPrivetPrinterCapabilities = - this.onFailedToGetPrivetPrinterCapabilities_.bind(this); - global.failedToGetExtensionPrinterCapabilities = - this.onFailedToGetExtensionPrinterCapabilities_.bind(this); global.reloadPrintersList = this.onReloadPrintersList_.bind(this); global.printToCloud = this.onPrintToCloud_.bind(this); global.fileSelectionCancelled = @@ -69,11 +92,7 @@ global.onDidPreviewPage = this.onDidPreviewPage_.bind(this); global.updatePrintPreview = this.onUpdatePrintPreview_.bind(this); global.onDidGetAccessToken = this.onDidGetAccessToken_.bind(this); - global.onPrivetCapabilitiesSet = - this.onPrivetCapabilitiesSet_.bind(this); global.onPrivetPrintFailed = this.onPrivetPrintFailed_.bind(this); - global.onExtensionCapabilitiesSet = - this.onExtensionCapabilitiesSet_.bind(this); global.onEnableManipulateSettingsForTest = this.onEnableManipulateSettingsForTest_.bind(this); global.printPresetOptionsFromDocument = @@ -115,14 +134,12 @@ */ NativeLayer.EventType = { ACCESS_TOKEN_READY: 'print_preview.NativeLayer.ACCESS_TOKEN_READY', - CAPABILITIES_SET: 'print_preview.NativeLayer.CAPABILITIES_SET', CLOUD_PRINT_ENABLE: 'print_preview.NativeLayer.CLOUD_PRINT_ENABLE', DESTINATIONS_RELOAD: 'print_preview.NativeLayer.DESTINATIONS_RELOAD', DISABLE_SCALING: 'print_preview.NativeLayer.DISABLE_SCALING', FILE_SELECTION_CANCEL: 'print_preview.NativeLayer.FILE_SELECTION_CANCEL', FILE_SELECTION_COMPLETE: 'print_preview.NativeLayer.FILE_SELECTION_COMPLETE', - GET_CAPABILITIES_FAIL: 'print_preview.NativeLayer.GET_CAPABILITIES_FAIL', MANIPULATE_SETTINGS_FOR_TEST: 'print_preview.NativeLayer.MANIPULATE_SETTINGS_FOR_TEST', PAGE_COUNT_READY: 'print_preview.NativeLayer.PAGE_COUNT_READY', @@ -134,12 +151,7 @@ 'print_preview.NativeLayer.PREVIEW_GENERATION_FAIL', PRINT_TO_CLOUD: 'print_preview.NativeLayer.PRINT_TO_CLOUD', SETTINGS_INVALID: 'print_preview.NativeLayer.SETTINGS_INVALID', - PRIVET_PRINTER_CHANGED: 'print_preview.NativeLayer.PRIVET_PRINTER_CHANGED', - PRIVET_CAPABILITIES_SET: - 'print_preview.NativeLayer.PRIVET_CAPABILITIES_SET', PRIVET_PRINT_FAILED: 'print_preview.NativeLayer.PRIVET_PRINT_FAILED', - EXTENSION_CAPABILITIES_SET: - 'print_preview.NativeLayer.EXTENSION_CAPABILITIES_SET', PRINT_PRESET_OPTIONS: 'print_preview.NativeLayer.PRINT_PRESET_OPTIONS', PROVISIONAL_DESTINATION_RESOLVED: 'print_preview.NativeLayer.PROVISIONAL_DESTINATION_RESOLVED' @@ -241,15 +253,6 @@ }, /** - * Requests the privet destination's printing capabilities. A - * PRIVET_CAPABILITIES_SET event will be dispatched in response. - * @param {string} destinationId ID of the destination. - */ - startGetPrivetDestinationCapabilities: function(destinationId) { - chrome.send('getPrivetPrinterCapabilities', [destinationId]); - }, - - /** * Request a list of extension printers. Printers are reported as they are * found by a series of 'extension-printers-added' events. * @return {!Promise} Will be resolved when all extension managed printers @@ -260,22 +263,37 @@ }, /** - * Requests an extension destination's printing capabilities. A - * EXTENSION_CAPABILITIES_SET event will be dispatched in response. - * @param {string} destinationId The ID of the destination whose - * capabilities are requested. + * Requests the destination's printing capabilities. Returns a promise that + * will be resolved with the capabilities if they are obtained successfully. + * @param {string} destinationId ID of the destination. + * @return {!Promise<!print_preview.PrinterCapabilitiesResponse>} */ - startGetExtensionDestinationCapabilities: function(destinationId) { - chrome.send('getExtensionPrinterCapabilities', [destinationId]); + getPrinterCapabilities: function(destinationId) { + return cr.sendWithPromise('getPrinterCapabilities', destinationId); }, /** - * Requests the destination's printing capabilities. A CAPABILITIES_SET - * event will be dispatched in response. + * Requests the privet destination's printing capabilities. Returns a + * promise that will be resolved with capabilities and printer information + * if capabilities are obtained successfully. * @param {string} destinationId ID of the destination. + * @return {!Promise<!print_preview.PrivetPrinterCapabilitiesResponse>} */ - startGetLocalDestinationCapabilities: function(destinationId) { - chrome.send('getPrinterCapabilities', [destinationId]); + getPrivetPrinterCapabilities: function(destinationId) { + return cr.sendWithPromise('getPrivetPrinterCapabilities', destinationId); + }, + + /** + * Requests the extension destination's printing capabilities. Returns a + * promise that will be resolved with the ID and capabilities if + * capabilities are obtained successfully. + * @param {string} destinationId The ID of the destination whose + * capabilities are requested. + * @return {!Promise<!print_preview.Cdd>} + */ + getExtensionPrinterCapabilities: function(destinationId) { + return cr.sendWithPromise('getExtensionPrinterCapabilities', + destinationId); }, /** @@ -549,65 +567,6 @@ this.eventTarget_.dispatchEvent(cloudPrintEnableEvent); }, - /** - * Called when native layer gets settings information for a requested local - * destination. - * @param {Object} settingsInfo printer setting information. - * @private - */ - onUpdateWithPrinterCapabilities_: function(settingsInfo) { - assert(settingsInfo.capabilities, - 'Capabilities update without capabilites'); - var capsSetEvent = new Event(NativeLayer.EventType.CAPABILITIES_SET); - capsSetEvent.settingsInfo = settingsInfo; - this.eventTarget_.dispatchEvent(capsSetEvent); - }, - - /** - * Called when native layer gets settings information for a requested local - * destination. - * @param {string} destinationId Printer affected by error. - * @private - */ - onFailedToGetPrinterCapabilities_: function(destinationId) { - var getCapsFailEvent = new Event( - NativeLayer.EventType.GET_CAPABILITIES_FAIL); - getCapsFailEvent.destinationId = destinationId; - getCapsFailEvent.destinationOrigin = - print_preview.DestinationOrigin.LOCAL; - this.eventTarget_.dispatchEvent(getCapsFailEvent); - }, - - /** - * Called when native layer gets settings information for a requested privet - * destination. - * @param {string} destinationId Printer affected by error. - * @private - */ - onFailedToGetPrivetPrinterCapabilities_: function(destinationId) { - var getCapsFailEvent = new Event( - NativeLayer.EventType.GET_CAPABILITIES_FAIL); - getCapsFailEvent.destinationId = destinationId; - getCapsFailEvent.destinationOrigin = - print_preview.DestinationOrigin.PRIVET; - this.eventTarget_.dispatchEvent(getCapsFailEvent); - }, - - /** - * Called when native layer fails to get settings information for a - * requested extension destination. - * @param {string} destinationId Printer affected by error. - * @private - */ - onFailedToGetExtensionPrinterCapabilities_: function(destinationId) { - var getCapsFailEvent = new Event( - NativeLayer.EventType.GET_CAPABILITIES_FAIL); - getCapsFailEvent.destinationId = destinationId; - getCapsFailEvent.destinationOrigin = - print_preview.DestinationOrigin.EXTENSION; - this.eventTarget_.dispatchEvent(getCapsFailEvent); - }, - /** Reloads the printer list. */ onReloadPrintersList_: function() { cr.dispatchSimpleEvent(this.eventTarget_, @@ -774,19 +733,6 @@ }, /** - * @param {Object} printer Specifies information about the printer that was - * added. - * @private - */ - onPrivetCapabilitiesSet_: function(printer, capabilities) { - var privetCapabilitiesSetEvent = - new Event(NativeLayer.EventType.PRIVET_CAPABILITIES_SET); - privetCapabilitiesSetEvent.printer = printer; - privetCapabilitiesSetEvent.capabilities = capabilities; - this.eventTarget_.dispatchEvent(privetCapabilitiesSetEvent); - }, - - /** * @param {string} http_error The HTTP response code or -1 if not an HTTP * error. * @private @@ -799,20 +745,6 @@ }, /** - * Called when an extension responds to a request for an extension printer - * capabilities. - * @param {string} printerId The printer's ID. - * @param {!Object} capabilities The reported printer capabilities. - */ - onExtensionCapabilitiesSet_: function(printerId, - capabilities) { - var event = new Event(NativeLayer.EventType.EXTENSION_CAPABILITIES_SET); - event.printerId = printerId; - event.capabilities = capabilities; - this.eventTarget_.dispatchEvent(event); - }, - - /** * Called when Chrome reports that attempt to resolve a provisional * destination failed. * @param {string} destinationId The provisional destination ID.
diff --git a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp index cc2a935..246c892 100644 --- a/chrome/browser/resources/settings/people_page/compiled_resources2.gyp +++ b/chrome/browser/resources/settings/people_page/compiled_resources2.gyp
@@ -205,6 +205,7 @@ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data', '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior', + '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:util', 'sync_browser_proxy', ], 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 262894d..9d6fba8 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -1,6 +1,7 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/html/i18n_behavior.html"> +<link rel="import" href="chrome://resources/html/util.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index 8078686..f404436 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -216,8 +216,8 @@ // Focus the password input box if password is needed to start sync. if (this.syncPrefs.passphraseRequired) { - // Async to allow the dom-if templates to render first. - this.async(function() { + // Wait for the dom-if templates to render and subpage to become visible. + listenOnce(document, 'show-container', function() { var input = /** @type {!PaperInputElement} */ ( this.$$('#existingPassphraseInput')); input.inputElement.focus();
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index bf6795ad..ae8d200b 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -77,29 +77,6 @@ namespace safe_browsing { -namespace { - -// The default URL prefix where browser fetches chunk updates, hashes, -// and reports safe browsing hits and malware details. -const char kSbDefaultURLPrefix[] = - "https://safebrowsing.google.com/safebrowsing"; - -// The backup URL prefix used when there are issues establishing a connection -// with the server at the primary URL. -const char kSbBackupConnectErrorURLPrefix[] = - "https://alt1-safebrowsing.google.com/safebrowsing"; - -// The backup URL prefix used when there are HTTP-specific issues with the -// server at the primary URL. -const char kSbBackupHttpErrorURLPrefix[] = - "https://alt2-safebrowsing.google.com/safebrowsing"; - -// The backup URL prefix used when there are local network specific issues. -const char kSbBackupNetworkErrorURLPrefix[] = - "https://alt3-safebrowsing.google.com/safebrowsing"; - -} // namespace - // static SafeBrowsingServiceFactory* SafeBrowsingService::factory_ = NULL;
diff --git a/chrome/browser/ssl/security_state_tab_helper.cc b/chrome/browser/ssl/security_state_tab_helper.cc index 4313182..c4286f5 100644 --- a/chrome/browser/ssl/security_state_tab_helper.cc +++ b/chrome/browser/ssl/security_state_tab_helper.cc
@@ -15,6 +15,7 @@ #include "components/prefs/pref_service.h" #include "components/security_state/content/content_utils.h" #include "components/ssl_config/ssl_config_prefs.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -39,7 +40,14 @@ SecurityStateTabHelper::SecurityStateTabHelper( content::WebContents* web_contents) : content::WebContentsObserver(web_contents), - logged_http_warning_on_current_navigation_(false) {} + logged_http_warning_on_current_navigation_(false), + is_incognito_(false) { + content::BrowserContext* context = web_contents->GetBrowserContext(); + if (context->IsOffTheRecord() && + !Profile::FromBrowserContext(context)->IsGuestSession()) { + is_incognito_ = true; + } +} SecurityStateTabHelper::~SecurityStateTabHelper() {} @@ -113,12 +121,24 @@ void SecurityStateTabHelper::DidFinishNavigation( content::NavigationHandle* navigation_handle) { - if (navigation_handle->IsInMainFrame() && - !navigation_handle->IsSameDocument()) { - // Only reset the console message flag for main-frame navigations, - // and not for same-document navigations like reference fragments and - // pushState. - logged_http_warning_on_current_navigation_ = false; + // Ignore subframe navigations, same-document navigations, and navigations + // that did not commit (e.g. HTTP/204 or file downloads). + if (!navigation_handle->IsInMainFrame() || + navigation_handle->IsSameDocument() || + !navigation_handle->HasCommitted()) { + return; + } + + logged_http_warning_on_current_navigation_ = false; + + security_state::SecurityInfo security_info; + GetSecurityInfo(&security_info); + if (security_info.incognito_downgraded_security_level) { + web_contents()->GetMainFrame()->AddMessageToConsole( + content::CONSOLE_MESSAGE_LEVEL_WARNING, + "This page was loaded non-securely in an incognito mode browser. A " + "warning has been added to the URL bar. For more information, see " + "https://goo.gl/y8SRRv."); } } @@ -199,5 +219,7 @@ // information is still being initialized, thus no need to check for that. state->malicious_content_status = GetMaliciousContentStatus(); + state->is_incognito = is_incognito_; + return state; }
diff --git a/chrome/browser/ssl/security_state_tab_helper.h b/chrome/browser/ssl/security_state_tab_helper.h index f44e7f8..a15167b 100644 --- a/chrome/browser/ssl/security_state_tab_helper.h +++ b/chrome/browser/ssl/security_state_tab_helper.h
@@ -50,9 +50,9 @@ std::unique_ptr<security_state::VisibleSecurityState> GetVisibleSecurityState() const; - // True if a console message has been logged about an omnibox warning that - // will be shown in future versions of Chrome for insecure HTTP pages. This - // message should only be logged once per main-frame navigation. + // True if a console message has been logged about an omnibox warning shown + // when sensitive input fields are shown on insecure HTTP pages. This message + // should only be logged once per main-frame navigation. bool logged_http_warning_on_current_navigation_; // The time that a console or omnibox warning was shown for insecure @@ -62,6 +62,9 @@ // histogramming. base::Time time_of_http_warning_on_current_navigation_; + // True if this browser tab is in non-guest Incognito mode. + bool is_incognito_; + DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelper); };
diff --git a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc index 07981b7..cf5a8ac 100644 --- a/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc +++ b/chrome/browser/ssl/security_state_tab_helper_browser_tests.cc
@@ -9,11 +9,16 @@ #include "base/macros.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_command_line.h" #include "base/threading/sequenced_worker_pool.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/profiles/profile_window.h" #include "chrome/browser/ssl/cert_verifier_browser_test.h" #include "chrome/browser/ssl/ssl_blocking_page.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" @@ -372,6 +377,21 @@ DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperTest); }; +// Same as SecurityStateTabHelperTest, but with Incognito enabled. +class SecurityStateTabHelperIncognitoTest : public SecurityStateTabHelperTest { + public: + SecurityStateTabHelperIncognitoTest() : SecurityStateTabHelperTest() {} + + void SetUpCommandLine(base::CommandLine* command_line) override { + SecurityStateTabHelperTest::SetUpCommandLine(command_line); + // Test should run Incognito. + command_line->AppendSwitch(switches::kIncognito); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SecurityStateTabHelperIncognitoTest); +}; + class DidChangeVisibleSecurityStateTest : public InProcessBrowserTest { public: DidChangeVisibleSecurityStateTest() @@ -933,6 +953,7 @@ embedded_test_server()->GetURL("/title1.html").host())); } + private: DISALLOW_COPY_AND_ASSIGN(SecurityStateLoadingTest); }; @@ -983,6 +1004,17 @@ ASSERT_TRUE(entry); EXPECT_TRUE(entry->GetSSL().content_status & content::SSLStatus::DISPLAYED_PASSWORD_FIELD_ON_HTTP); + + { + // Ensure the warning is still present when HTTPBad Phase 2 flag is enabled. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + + helper->GetSecurityInfo(&security_info); + EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); + } } // Tests that when a visible password field is detected on a blob URL, the @@ -1243,7 +1275,7 @@ delegate->tab_strip_model()->ActivateTabAt(index, true); ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); - // Navigate to an HTTP page. Use a non-local hostname so that is it + // Navigate to an HTTP page. Use a non-local hostname so that it is // not considered secure. GURL http_url = GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); @@ -1311,7 +1343,7 @@ delegate->tab_strip_model()->ActivateTabAt(index, true); ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); - // Navigate to an HTTP page. Use a non-local hostname so that is it + // Navigate to an HTTP page. Use a non-local hostname so that it is // not considered secure. GURL http_url = GetURLWithNonLocalHostname(embedded_test_server(), "/ssl/page_with_frame.html"); @@ -1352,6 +1384,7 @@ contents, "document.getElementById('navFrame').src = '/title2.html';")); subframe_observer.Wait(); contents->OnCreditCardInputShownOnHttp(); + helper->GetSecurityInfo(&security_info); EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); // Do a main frame navigation and then trigger HTTP_SHOW_WARNING @@ -1392,7 +1425,7 @@ delegate->tab_strip_model()->ActivateTabAt(index, true); ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); - // Navigate to an HTTP page. Use a non-local hostname so that is it + // Navigate to an HTTP page. Use a non-local hostname so that it is // not considered secure. GURL http_url = GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); @@ -1428,6 +1461,7 @@ EXPECT_TRUE(content::ExecuteScript( contents, "history.pushState({ foo: 'bar' }, 'foo', 'bar');")); contents->OnCreditCardInputShownOnHttp(); + helper->GetSecurityInfo(&security_info); EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); // Do a main frame navigation and then trigger HTTP_SHOW_WARNING @@ -1614,6 +1648,262 @@ EXPECT_TRUE(observer.latest_explanations().summary.empty()); } +// Tests that the security level of a HTTP page in Incognito mode is downgraded +// to HTTP_SHOW_WARNING when MarkHttpAsNonSecureWhileIncognito is enabled. +IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperIncognitoTest, + SecurityLevelDowngradedForHTTPInIncognito) { + // Set the mode using the command line flag rather than the field trial to + // ensure that fieldtrial_testing_config.json does not interfere. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + + ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate( + Browser::CreateParams(browser()->profile(), true)); + content::WebContents* original_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* contents = + content::WebContents::Create(content::WebContents::CreateParams( + original_contents->GetBrowserContext())); + ASSERT_TRUE(contents); + ASSERT_TRUE(contents->GetBrowserContext()->IsOffTheRecord()); + contents->SetDelegate(delegate); + delegate->tab_strip_model()->AppendWebContents(contents, true); + int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents); + delegate->tab_strip_model()->ActivateTabAt(index, true); + ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); + + SecurityStyleTestObserver observer(contents); + + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(contents); + ASSERT_TRUE(helper); + + // Navigate to an HTTP page. Use a non-local hostname so that it is + // not considered secure. + GURL http_url = + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); + ui_test_utils::NavigateToURL(delegate, http_url); + content::NavigationEntry* entry = contents->GetController().GetVisibleEntry(); + ASSERT_TRUE(entry); + EXPECT_EQ(http_url, entry->GetURL()); + + security_state::SecurityInfo security_info; + helper->GetSecurityInfo(&security_info); + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); + EXPECT_EQ(1u, observer.latest_explanations().neutral_explanations.size()); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); + + // Check that the expected console message is present. + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); + + // Ensure that same-page pushstate does not add another notice. + EXPECT_TRUE(content::ExecuteScript( + contents, "history.pushState({ foo: 'bar' }, 'foo', 'bar');")); + EXPECT_EQ(1u, observer.latest_explanations().neutral_explanations.size()); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); + // Check that no additional console message is present. + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); +} + +// Tests that additional HTTP_SHOW_WARNING console messages are not +// printed after aborted navigations. +IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperIncognitoTest, + ConsoleMessageNotPrintedForAbortedNavigation) { + // Set the mode using the command line flag rather than the field trial to + // ensure that fieldtrial_testing_config.json does not interfere. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + + ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate( + Browser::CreateParams(browser()->profile(), true)); + content::WebContents* original_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + content::WebContents* contents = + content::WebContents::Create(content::WebContents::CreateParams( + original_contents->GetBrowserContext())); + ASSERT_TRUE(contents); + ASSERT_TRUE(contents->GetBrowserContext()->IsOffTheRecord()); + contents->SetDelegate(delegate); + delegate->tab_strip_model()->AppendWebContents(contents, true); + int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents); + delegate->tab_strip_model()->ActivateTabAt(index, true); + ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); + + SecurityStyleTestObserver observer(contents); + + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(contents); + ASSERT_TRUE(helper); + + // Navigate to an HTTP page. Use a non-local hostname so that it is + // not considered secure. + GURL http_url = + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); + ui_test_utils::NavigateToURL(delegate, http_url); + + security_state::SecurityInfo security_info; + helper->GetSecurityInfo(&security_info); + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); + EXPECT_EQ(1u, observer.latest_explanations().neutral_explanations.size()); + + // Check that the expected console message is present. + ASSERT_NO_FATAL_FAILURE(CheckForOneHttpWarningConsoleMessage(delegate)); + delegate->ClearConsoleMessages(); + + // Perform a navigation that does not commit. + // The embedded test server returns a HTTP/204 only for local URLs, so + // we cannot use GetURLWithNonLocalHostname() here. + GURL http204_url = embedded_test_server()->GetURL("/nocontent"); + ui_test_utils::NavigateToURL(delegate, http204_url); + + // No change is expected in the security state. + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::HTTP_SHOW_WARNING, security_info.security_level); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); + EXPECT_EQ(1u, observer.latest_explanations().neutral_explanations.size()); + + // No additional console logging should occur. + EXPECT_TRUE(delegate->console_messages().empty()); +} + +// Tests that the security level of a HTTP page in Guest mode is not downgraded +// to HTTP_SHOW_WARNING when MarkHttpAsNonSecureWhileIncognito is enabled. +#if defined(OS_CHROMEOS) +// Guest mode cannot be readily browser-tested on ChromeOS. +#define MAYBE_SecurityLevelNotDowngradedForHTTPInGuestMode \ + DISABLED_SecurityLevelNotDowngradedForHTTPInGuestMode +#else +#define MAYBE_SecurityLevelNotDowngradedForHTTPInGuestMode \ + SecurityLevelNotDowngradedForHTTPInGuestMode +#endif +IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperTest, + MAYBE_SecurityLevelNotDowngradedForHTTPInGuestMode) { + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + + // Create a new browser in Guest Mode. + EXPECT_EQ(1U, BrowserList::GetInstance()->size()); + content::WindowedNotificationObserver browser_creation_observer( + chrome::NOTIFICATION_BROWSER_WINDOW_READY, + content::NotificationService::AllSources()); + profiles::SwitchToGuestProfile(ProfileManager::CreateCallback()); + browser_creation_observer.Wait(); + EXPECT_EQ(2U, BrowserList::GetInstance()->size()); + Profile* guest = g_browser_process->profile_manager()->GetProfileByPath( + ProfileManager::GetGuestProfilePath()); + Browser* guest_browser = chrome::FindAnyBrowser(guest, true); + ASSERT_TRUE(guest_browser); + + ConsoleWebContentsDelegate* delegate = new ConsoleWebContentsDelegate( + Browser::CreateParams(guest_browser->profile(), true)); + content::WebContents* original_contents = + guest_browser->tab_strip_model()->GetActiveWebContents(); + content::WebContents* contents = + content::WebContents::Create(content::WebContents::CreateParams( + original_contents->GetBrowserContext())); + ASSERT_TRUE(contents); + ASSERT_TRUE(contents->GetBrowserContext()->IsOffTheRecord()); + contents->SetDelegate(delegate); + delegate->tab_strip_model()->AppendWebContents(contents, true); + int index = delegate->tab_strip_model()->GetIndexOfWebContents(contents); + delegate->tab_strip_model()->ActivateTabAt(index, true); + ASSERT_EQ(contents, delegate->tab_strip_model()->GetActiveWebContents()); + + SecurityStyleTestObserver observer(contents); + + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(contents); + ASSERT_TRUE(helper); + + // Navigate to an HTTP page. Use a non-local hostname so that it is + // not considered secure. + GURL http_url = + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); + ui_test_utils::NavigateToURL(delegate, http_url); + + security_state::SecurityInfo security_info; + helper->GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::NONE, security_info.security_level); + EXPECT_EQ(0u, observer.latest_explanations().neutral_explanations.size()); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); + + // No console notification should occur. + EXPECT_TRUE(delegate->console_messages().empty()); +} + +// Tests that the security level of a HTTP page is NEUTRAL when MarkHttpAs is +// not set. +IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperIncognitoTest, + SecurityLevelNeutralByDefaultForHTTP) { + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(contents); + + ASSERT_TRUE(contents->GetBrowserContext()->IsOffTheRecord()); + + SecurityStyleTestObserver observer(contents); + + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(contents); + ASSERT_TRUE(helper); + + // Navigate to an HTTP page. Use a non-local hostname so that it is + // not considered secure. + GURL http_url = + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); + ui_test_utils::NavigateToURL(browser(), http_url); + + security_state::SecurityInfo security_info; + helper->GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::NONE, security_info.security_level); + EXPECT_EQ(0u, observer.latest_explanations().neutral_explanations.size()); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, observer.latest_security_style()); +} + +// Tests that the security level of a HTTP page is downgraded to DANGEROUS when +// MarkHttpAsDangerous is enabled. +IN_PROC_BROWSER_TEST_F(SecurityStateTabHelperIncognitoTest, + SecurityLevelDangerousWhenMarkHttpAsDangerous) { + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsDangerous); + + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(contents); + ASSERT_TRUE(contents->GetBrowserContext()->IsOffTheRecord()); + + SecurityStyleTestObserver observer(contents); + + SecurityStateTabHelper* helper = + SecurityStateTabHelper::FromWebContents(contents); + ASSERT_TRUE(helper); + + // Navigate to an HTTP page. Use a non-local hostname so that it is + // not considered secure. + GURL http_url = + GetURLWithNonLocalHostname(embedded_test_server(), "/title1.html"); + ui_test_utils::NavigateToURL(browser(), http_url); + + security_state::SecurityInfo security_info; + helper->GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + EXPECT_EQ(security_state::DANGEROUS, security_info.security_level); + EXPECT_EQ(blink::kWebSecurityStyleInsecure, observer.latest_security_style()); +} + // Visit a valid HTTPS page, then a broken HTTPS page, and then go back, // and test that the observed security style matches. #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index f163c14..2321021 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3289,6 +3289,8 @@ "app_list/profile_loader.cc", "app_list/profile_loader.h", "app_list/profile_store.h", + "app_list/search/answer_card_result.cc", + "app_list/search/answer_card_result.h", "app_list/search/answer_card_search_provider.cc", "app_list/search/answer_card_search_provider.h", "app_list/search/app_result.cc",
diff --git a/chrome/browser/ui/app_list/search/answer_card_result.cc b/chrome/browser/ui/app_list/search/answer_card_result.cc new file mode 100644 index 0000000..38665ee --- /dev/null +++ b/chrome/browser/ui/app_list/search/answer_card_result.cc
@@ -0,0 +1,79 @@ +// 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/ui/app_list/search/answer_card_result.h" + +#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "third_party/WebKit/public/platform/WebMouseEvent.h" + +namespace app_list { + +AnswerCardResult::AnswerCardResult(Profile* profile, + AppListControllerDelegate* list_controller, + const std::string& result_url, + const base::string16& result_title, + views::View* web_view, + content::WebContents* web_contents) + : WebContentsObserver(web_contents), + profile_(profile), + list_controller_(list_controller), + mouse_event_callback_(base::Bind(&AnswerCardResult::HandleMouseEvent, + base::Unretained(this))) { + set_display_type(DISPLAY_CARD); + set_id(result_url); + set_relevance(1); + set_view(web_view); + set_title(result_title); + // web_contents may be null if the result is being duplicated after the + // search provider's WebContents was destroyed. + if (web_contents) { + content::RenderViewHost* const rvh = web_contents->GetRenderViewHost(); + if (rvh) { + rvh->GetWidget()->AddMouseEventCallback(mouse_event_callback_); + } + } +} + +AnswerCardResult::~AnswerCardResult() { + // WebContentsObserver::web_contents() returns nullptr after destruction of + // WebContents. + if (web_contents()) { + content::RenderViewHost* const rvh = web_contents()->GetRenderViewHost(); + if (rvh) { + rvh->GetWidget()->RemoveMouseEventCallback(mouse_event_callback_); + } + } +} + +std::unique_ptr<SearchResult> AnswerCardResult::Duplicate() const { + return base::MakeUnique<AnswerCardResult>(profile_, list_controller_, id(), + title(), view(), web_contents()); +} + +void AnswerCardResult::Open(int event_flags) { + list_controller_->OpenURL(profile_, GURL(id()), ui::PAGE_TRANSITION_GENERATED, + ui::DispositionFromEventFlags(event_flags)); +} + +bool AnswerCardResult::HandleMouseEvent(const blink::WebMouseEvent& event) { + switch (event.GetType()) { + case blink::WebInputEvent::kMouseMove: + case blink::WebInputEvent::kMouseEnter: + if (!is_mouse_in_view()) + SetIsMouseInView(true); + break; + case blink::WebInputEvent::kMouseLeave: + if (is_mouse_in_view()) + SetIsMouseInView(false); + break; + default: + break; + } + + return false; +} + +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/answer_card_result.h b/chrome/browser/ui/app_list/search/answer_card_result.h new file mode 100644 index 0000000..2f7e56bc --- /dev/null +++ b/chrome/browser/ui/app_list/search/answer_card_result.h
@@ -0,0 +1,50 @@ +// 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_UI_APP_LIST_SEARCH_ANSWER_CARD_RESULT_H_ +#define CHROME_BROWSER_UI_APP_LIST_SEARCH_ANSWER_CARD_RESULT_H_ + +#include <memory> +#include <string> + +#include "content/public/browser/render_widget_host.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/app_list/search_result.h" + +class AppListControllerDelegate; +class Profile; + +namespace app_list { + +// Result of AnswerCardSearchProvider. +class AnswerCardResult : public SearchResult, + public content::WebContentsObserver { + public: + AnswerCardResult(Profile* profile, + AppListControllerDelegate* list_controller, + const std::string& result_url, + const base::string16& result_title, + views::View* web_view, + content::WebContents* web_contents); + + ~AnswerCardResult() override; + + // SearchResult overrides: + std::unique_ptr<SearchResult> Duplicate() const override; + + void Open(int event_flags) override; + + private: + bool HandleMouseEvent(const blink::WebMouseEvent& event); + + Profile* const profile_; // Unowned + AppListControllerDelegate* const list_controller_; // Unowned + const content::RenderWidgetHost::MouseEventCallback mouse_event_callback_; + + DISALLOW_COPY_AND_ASSIGN(AnswerCardResult); +}; + +} // namespace app_list + +#endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_ANSWER_CARD_RESULT_H_
diff --git a/chrome/browser/ui/app_list/search/answer_card_result_unittest.cc b/chrome/browser/ui/app_list/search/answer_card_result_unittest.cc new file mode 100644 index 0000000..8825d16 --- /dev/null +++ b/chrome/browser/ui/app_list/search/answer_card_result_unittest.cc
@@ -0,0 +1,175 @@ +// Copyright 2014 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/ui/app_list/search/answer_card_result.h" + +#include <memory> + +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/app_list/app_list_test_util.h" +#include "chrome/browser/ui/app_list/test/test_app_list_controller_delegate.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/browser/web_contents.h" +#include "third_party/WebKit/public/platform/WebMouseEvent.h" +#include "ui/app_list/search_result_observer.h" +#include "ui/views/view.h" + +namespace app_list { +namespace test { + +namespace { + +constexpr char kResultUrl[] = "http://google.com/search?q=weather"; +constexpr char kResultTitle[] = "The weather is fine"; + +} // namespace + +class AnswerCardResultTest : public AppListTestBase, + public app_list::SearchResultObserver { + public: + AnswerCardResultTest() {} + + void DeleteWebContents() { web_contents_.reset(nullptr); } + + std::unique_ptr<AnswerCardResult> CreateResult( + const std::string& result_url, + const base::string16& result_title) const { + return base::MakeUnique<AnswerCardResult>( + profile_.get(), app_list_controller_delegate_.get(), result_url, + result_title, view_.get(), web_contents_.get()); + } + + const GURL& GetLastOpenedUrl() const { + return app_list_controller_delegate_->last_opened_url(); + } + + void VerifyLastMouseHoverEvent(bool expected_mouse_in_view, + SearchResult* result) { + ASSERT_TRUE(received_hover_event_); + EXPECT_EQ(expected_mouse_in_view, result->is_mouse_in_view()); + received_hover_event_ = false; + } + + void InjectMouseEvent(blink::WebInputEvent::Type type) { + web_contents_->GetRenderViewHost()->GetWidget()->ForwardMouseEvent( + blink::WebMouseEvent(type, blink::WebInputEvent::kNoModifiers, + blink::WebInputEvent::kTimeStampForTesting)); + } + + views::View* view() const { return view_.get(); } + + // AppListTestBase overrides: + void SetUp() override { + AppListTestBase::SetUp(); + + web_contents_.reset( + content::WebContents::Create(content::WebContents::CreateParams( + profile_.get(), content::SiteInstance::Create(profile_.get())))); + view_ = base::MakeUnique<views::View>(); + app_list_controller_delegate_ = + base::MakeUnique<::test::TestAppListControllerDelegate>(); + } + + void TearDown() override { + ASSERT_FALSE(received_hover_event_); + AppListTestBase::TearDown(); + } + + // SearchResultObserver overrides: + void OnViewHoverStateChanged() override { + ASSERT_FALSE(received_hover_event_); + received_hover_event_ = true; + } + + private: + std::unique_ptr<views::View> view_; + std::unique_ptr<content::WebContents> web_contents_; + bool received_hover_event_ = false; + std::unique_ptr<::test::TestAppListControllerDelegate> + app_list_controller_delegate_; + + DISALLOW_COPY_AND_ASSIGN(AnswerCardResultTest); +}; + +TEST_F(AnswerCardResultTest, Basic) { + std::unique_ptr<AnswerCardResult> result = + CreateResult(kResultUrl, base::ASCIIToUTF16(kResultTitle)); + + EXPECT_EQ(kResultUrl, result->id()); + EXPECT_EQ(base::ASCIIToUTF16(kResultTitle), result->title()); + EXPECT_EQ(SearchResult::DISPLAY_CARD, result->display_type()); + EXPECT_EQ(1, result->relevance()); + EXPECT_EQ(view(), result->view()); + + result->Open(ui::EF_NONE); + EXPECT_EQ(kResultUrl, GetLastOpenedUrl().spec()); + + std::unique_ptr<SearchResult> result1 = result->Duplicate(); + + EXPECT_EQ(kResultUrl, result1->id()); + EXPECT_EQ(base::ASCIIToUTF16(kResultTitle), result1->title()); + EXPECT_EQ(SearchResult::DISPLAY_CARD, result1->display_type()); + EXPECT_EQ(1, result1->relevance()); + EXPECT_EQ(view(), result1->view()); +} + +TEST_F(AnswerCardResultTest, NullWebContents) { + DeleteWebContents(); + + // Shouldn't crash with null WebContents. + std::unique_ptr<AnswerCardResult> result = + CreateResult(kResultUrl, base::ASCIIToUTF16(kResultTitle)); + std::unique_ptr<SearchResult> result1 = result->Duplicate(); +} + +TEST_F(AnswerCardResultTest, EarlyDeleteWebContents) { + // Shouldn't crash with WebContents gets deleted while search result exists. + std::unique_ptr<AnswerCardResult> result = + CreateResult(kResultUrl, base::ASCIIToUTF16(kResultTitle)); + + DeleteWebContents(); + + result->Duplicate(); +} + +TEST_F(AnswerCardResultTest, MouseEvents) { + std::unique_ptr<SearchResult> result; + { + // Duplicate the result, so that we know that the copy still generates + // events. + std::unique_ptr<AnswerCardResult> result_original = + CreateResult(kResultUrl, base::ASCIIToUTF16(kResultTitle)); + result = result_original->Duplicate(); + } + + result->AddObserver(this); + + ASSERT_FALSE(result->is_mouse_in_view()); + + InjectMouseEvent(blink::WebInputEvent::kMouseLeave); + ASSERT_FALSE(result->is_mouse_in_view()); + + InjectMouseEvent(blink::WebInputEvent::kMouseEnter); + VerifyLastMouseHoverEvent(true, result.get()); + + InjectMouseEvent(blink::WebInputEvent::kMouseEnter); + // Not using VerifyLastMouseHoverEvent will effectively check that second + // Enter event didn't invoke a callback. + ASSERT_TRUE(result->is_mouse_in_view()); + + InjectMouseEvent(blink::WebInputEvent::kMouseLeave); + VerifyLastMouseHoverEvent(false, result.get()); + + InjectMouseEvent(blink::WebInputEvent::kMouseLeave); + // Not using VerifyLastMouseHoverEvent will effectively check that second + // Leave event didn't invoke a callback. + ASSERT_FALSE(result->is_mouse_in_view()); + + InjectMouseEvent(blink::WebInputEvent::kMouseMove); + VerifyLastMouseHoverEvent(true, result.get()); +} + +} // namespace test +} // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/answer_card_search_provider.cc b/chrome/browser/ui/app_list/search/answer_card_search_provider.cc index 19f01330..8dcb330 100644 --- a/chrome/browser/ui/app_list/search/answer_card_search_provider.cc +++ b/chrome/browser/ui/app_list/search/answer_card_search_provider.cc
@@ -9,6 +9,7 @@ #include "base/metrics/user_metrics.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/search/answer_card_result.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "content/public/browser/navigation_handle.h" @@ -19,11 +20,9 @@ #include "content/public/common/renderer_preferences.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" -#include "third_party/WebKit/public/platform/WebMouseEvent.h" #include "ui/app_list/app_list_features.h" #include "ui/app_list/app_list_model.h" #include "ui/app_list/search_box_model.h" -#include "ui/app_list/search_result.h" #include "ui/views/controls/webview/web_contents_set_background_color.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/widget/widget.h" @@ -76,87 +75,15 @@ DISALLOW_COPY_AND_ASSIGN(SearchAnswerWebView); }; -class SearchAnswerResult : public SearchResult, - public content::WebContentsObserver { - public: - SearchAnswerResult(Profile* profile, - const std::string& result_url, - const base::string16& result_title, - views::View* web_view, - content::WebContents* web_contents) - : WebContentsObserver(web_contents), - profile_(profile), - mouse_event_callback_(base::Bind(&SearchAnswerResult::HandleMouseEvent, - base::Unretained(this))) { - set_display_type(DISPLAY_CARD); - set_id(result_url); - set_relevance(1); - set_view(web_view); - set_title(result_title); - // web_contents may be null if the result is being duplicated after the - // search provider's WebContents was destroyed. - if (web_contents) { - content::RenderViewHost* const rvh = web_contents->GetRenderViewHost(); - if (rvh) { - rvh->GetWidget()->AddMouseEventCallback(mouse_event_callback_); - } - } - } - - ~SearchAnswerResult() override { - // WebContentsObserver::web_contents() returns nullptr after destruction of - // WebContents. - if (web_contents()) { - content::RenderViewHost* const rvh = web_contents()->GetRenderViewHost(); - if (rvh) { - rvh->GetWidget()->RemoveMouseEventCallback(mouse_event_callback_); - } - } - } - - // SearchResult overrides: - std::unique_ptr<SearchResult> Duplicate() const override { - return base::MakeUnique<SearchAnswerResult>(profile_, id(), title(), view(), - web_contents()); - } - - void Open(int event_flags) override { - chrome::NavigateParams params(profile_, GURL(id()), - ui::PAGE_TRANSITION_GENERATED); - params.disposition = ui::DispositionFromEventFlags(event_flags); - chrome::Navigate(¶ms); - } - - private: - bool HandleMouseEvent(const blink::WebMouseEvent& event) { - switch (event.GetType()) { - case blink::WebInputEvent::kMouseMove: - case blink::WebInputEvent::kMouseEnter: - if (!is_mouse_in_view()) - SetIsMouseInView(true); - break; - case blink::WebInputEvent::kMouseLeave: - if (is_mouse_in_view()) - SetIsMouseInView(false); - break; - default: - break; - } - - return false; - } - - Profile* const profile_; - const content::RenderWidgetHost::MouseEventCallback mouse_event_callback_; -}; - } // namespace AnswerCardSearchProvider::AnswerCardSearchProvider( Profile* profile, - app_list::AppListModel* model) + app_list::AppListModel* model, + AppListControllerDelegate* list_controller) : profile_(profile), model_(model), + list_controller_(list_controller), web_view_(base::MakeUnique<SearchAnswerWebView>(profile)), web_contents_( content::WebContents::Create(content::WebContents::CreateParams( @@ -356,9 +283,10 @@ SearchProvider::Results results; if (is_available) { results.reserve(1); - results.emplace_back(base::MakeUnique<SearchAnswerResult>( - profile_, result_url_, base::UTF8ToUTF16(result_title_), - web_view_.get(), web_contents_.get())); + results.emplace_back(base::MakeUnique<AnswerCardResult>( + profile_, list_controller_, result_url_, + base::UTF8ToUTF16(result_title_), web_view_.get(), + web_contents_.get())); } SwapResults(&results); }
diff --git a/chrome/browser/ui/app_list/search/answer_card_search_provider.h b/chrome/browser/ui/app_list/search/answer_card_search_provider.h index d2996e40..4a989cba 100644 --- a/chrome/browser/ui/app_list/search/answer_card_search_provider.h +++ b/chrome/browser/ui/app_list/search/answer_card_search_provider.h
@@ -14,6 +14,7 @@ #include "ui/app_list/search_provider.h" #include "url/gurl.h" +class AppListControllerDelegate; class Profile; namespace app_list { @@ -36,7 +37,9 @@ public content::WebContentsDelegate, public content::WebContentsObserver { public: - AnswerCardSearchProvider(Profile* profile, app_list::AppListModel* model); + AnswerCardSearchProvider(Profile* profile, + app_list::AppListModel* model, + AppListControllerDelegate* list_controller); ~AnswerCardSearchProvider() override; @@ -77,6 +80,9 @@ // Unowned pointer to app list model. app_list::AppListModel* const model_; + // Unowned pointer to app list controller. + AppListControllerDelegate* const list_controller_; + // Web view for the web contents managed by this class. const std::unique_ptr<views::WebView> web_view_;
diff --git a/chrome/browser/ui/app_list/search/search_controller_factory.cc b/chrome/browser/ui/app_list/search/search_controller_factory.cc index 6220d78..4753768 100644 --- a/chrome/browser/ui/app_list/search/search_controller_factory.cc +++ b/chrome/browser/ui/app_list/search/search_controller_factory.cc
@@ -88,9 +88,9 @@ webstore_group_id, base::MakeUnique<WebstoreProvider>(profile, list_controller)); if (features::IsAnswerCardEnabled()) { - controller->AddProvider( - answer_card_group_id, - base::MakeUnique<AnswerCardSearchProvider>(profile, model)); + controller->AddProvider(answer_card_group_id, + base::MakeUnique<AnswerCardSearchProvider>( + profile, model, list_controller)); } if (IsSuggestionsSearchProviderEnabled()) { size_t suggestions_group_id =
diff --git a/chrome/browser/ui/bookmarks/bookmark_bar_constants.h b/chrome/browser/ui/bookmarks/bookmark_bar_constants.h index f80b23f..dddb974 100644 --- a/chrome/browser/ui/bookmarks/bookmark_bar_constants.h +++ b/chrome/browser/ui/bookmarks/bookmark_bar_constants.h
@@ -20,9 +20,9 @@ // points) because of the visual overlap with the main toolbar. When using this // to compute values other than the actual height of the toolbar, be sure to add // |kVisualHeightOffset|. -const int kMinimumBookmarkBarHeight = 25; +const int kMinimumBookmarkBarHeight = 26; #elif defined(TOOLKIT_VIEWS) -const int kMinimumBookmarkBarHeight = 27; +const int kMinimumBookmarkBarHeight = 28; #endif } // namespace chrome
diff --git a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc index b5ef1a0..5e41940f 100644 --- a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc +++ b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.cc
@@ -12,6 +12,9 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profiles_state.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/chromium_strings.h" @@ -20,6 +23,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" +#include "components/signin/core/browser/signin_error_controller.h" #include "third_party/libphonenumber/phonenumber_api.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/color_utils.h" @@ -75,14 +79,22 @@ IDS_BOOKMARK_BUBBLE_DESKTOP_TO_IOS_PROMO_TITLE_V3}}; bool IsEligibleForIOSPromotion( - PrefService* prefs, - const syncer::SyncService* sync_service, + Profile* profile, desktop_ios_promotion::PromotionEntryPoint entry_point) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kForceDesktopIOSPromotion)) { return true; } + // Don't show promotion if there has been authentication error, because this + // will prevent the recovery phone number from showing. + const SigninErrorController* signin_error_controller = + profiles::GetSigninErrorController(profile); + if (signin_error_controller && signin_error_controller->HasError()) + return false; + + const browser_sync::ProfileSyncService* sync_service = + ProfileSyncServiceFactory::GetForProfile(profile); // Promotion should only show for english locale. PrefService* local_state = g_browser_process->local_state(); std::string locale = base::i18n::GetConfiguredLocale(); @@ -111,6 +123,7 @@ if (is_dismissed || show_count >= impression_cap) return false; + PrefService* prefs = profile->GetPrefs(); // Don't show the promotion if the user have used any entry point to recieve // SMS on the last 7 days. double last_impression = prefs->GetDouble(prefs::kIOSPromotionLastImpression);
diff --git a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h index 4adcc342..2253a32 100644 --- a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h +++ b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h
@@ -10,16 +10,12 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/image/image_skia.h" -namespace syncer { -class SyncService; -} - namespace user_prefs { class PrefRegistrySyncable; } class PrefRegistrySimple; -class PrefService; +class Profile; namespace desktop_ios_promotion { @@ -71,8 +67,7 @@ {prefs::kNumberHistoryPageIOSPromoShown, prefs::kHistoryPageIOSPromoDismissed}}; -bool IsEligibleForIOSPromotion(PrefService* prefs, - const syncer::SyncService* sync_service, +bool IsEligibleForIOSPromotion(Profile* profile, PromotionEntryPoint entry_point); // Returns the SMS ID to be used with send SMS API call.
diff --git a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util_unittest.cc b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util_unittest.cc index 3d726fd..f28b062 100644 --- a/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util_unittest.cc +++ b/chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util_unittest.cc
@@ -4,32 +4,63 @@ #include "chrome/browser/ui/desktop_ios_promotion/desktop_ios_promotion_util.h" +#include <memory> + #include "base/i18n/rtl.h" #include "base/memory/ptr_util.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/prefs/browser_prefs.h" +#include "chrome/browser/signin/signin_error_controller_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" +#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/profile_sync_test_util.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" #include "components/browser_sync/profile_sync_service.h" +#include "components/browser_sync/test_profile_sync_service.h" #include "components/prefs/pref_service.h" +#include "components/signin/core/browser/fake_auth_status_provider.h" +#include "components/signin/core/browser/signin_manager.h" #include "components/sync/driver/fake_sync_service.h" #include "components/sync_preferences/testing_pref_service_syncable.h" +#include "content/public/test/test_browser_thread_bundle.h" + +typedef GoogleServiceAuthError AuthError; namespace { -class TestSyncService : public syncer::FakeSyncService { +class TestSyncService : public browser_sync::TestProfileSyncService { public: - // FakeSyncService overrides. + explicit TestSyncService(Profile* profile) + : browser_sync::TestProfileSyncService( + CreateProfileSyncServiceParamsForTest(profile)) {} + bool IsSyncAllowed() const override { return is_sync_allowed_; } void set_sync_allowed(bool sync_allowed) { is_sync_allowed_ = sync_allowed; } private: bool is_sync_allowed_ = true; + DISALLOW_COPY_AND_ASSIGN(TestSyncService); }; +std::unique_ptr<KeyedService> BuildFakeSyncService( + content::BrowserContext* context) { + return base::MakeUnique<TestSyncService>( + static_cast<TestingProfile*>(context)); +} + +constexpr int kSMSEntrypointSavePasswordBubble = + 1 + << static_cast<int>(desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE); + +constexpr int kSMSEntrypointBookmarksBubble = + 1 + << static_cast<int>(desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE); + } // namespace class DesktopIOSPromotionUtilTest : public testing::Test { @@ -41,11 +72,23 @@ local_state_.reset(new TestingPrefServiceSimple); TestingBrowserProcess::GetGlobal()->SetLocalState(local_state_.get()); desktop_ios_promotion::RegisterLocalPrefs(local_state_->registry()); - pref_service_ = new sync_preferences::TestingPrefServiceSyncable(); - desktop_ios_promotion::RegisterProfilePrefs(pref_service_->registry()); + auto pref_service = + base::MakeUnique<sync_preferences::TestingPrefServiceSyncable>(); + chrome::RegisterUserProfilePrefs(pref_service->registry()); + TestingProfile::Builder profile_builder; + profile_builder.SetPrefService(std::move(pref_service)); + profile_builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(), + &BuildFakeSyncService); + profile_ = profile_builder.Build(); + sync_service_ = static_cast<TestSyncService*>( + ProfileSyncServiceFactory::GetForProfile(profile_.get())); + mock_signin_ = static_cast<SigninManagerBase*>( + SigninManagerFactory::GetForProfile(profile_.get())); + mock_signin_->SetAuthenticatedAccountInfo("test", "test"); } void TearDown() override { + profile_.reset(); // Ensure that g_accept_requests gets set back to true after test execution. TestingBrowserProcess::GetGlobal()->SetLocalState(nullptr); local_state_.reset(); @@ -53,10 +96,11 @@ PrefService* local_state() { return local_state_.get(); } - TestSyncService* sync_service() { return &fake_sync_service_; } - sync_preferences::TestingPrefServiceSyncable* prefs() { - return pref_service_; - } + TestSyncService* sync_service() { return sync_service_; } + + PrefService* prefs() { return profile_->GetPrefs(); } + + Profile* profile() { return profile_.get(); } double GetDoubleNDayOldDate(int days) { base::Time time_result = @@ -64,12 +108,12 @@ return time_result.ToDoubleT(); } - protected: - std::unique_ptr<TestingPrefServiceSimple> local_state_; - sync_preferences::TestingPrefServiceSyncable* pref_service_; - TestSyncService fake_sync_service_; - private: + TestSyncService* sync_service_ = nullptr; + content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<TestingPrefServiceSimple> local_state_; + SigninManagerBase* mock_signin_ = nullptr; + std::unique_ptr<TestingProfile> profile_; DISALLOW_COPY_AND_ASSIGN(DesktopIOSPromotionUtilTest); }; @@ -77,8 +121,8 @@ desktop_ios_promotion::PromotionEntryPoint entry_point = desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE; // By default the promo is off. - EXPECT_FALSE(desktop_ios_promotion::IsEligibleForIOSPromotion( - prefs(), nullptr, entry_point)); + EXPECT_FALSE( + desktop_ios_promotion::IsEligibleForIOSPromotion(profile(), entry_point)); // Enable the promotion and assign the entry_point finch parameter. base::FieldTrialList field_trial_list(nullptr); @@ -101,6 +145,7 @@ std::string locales[] = {"en-US", "en-CA", "en-AU", "es-US"}; constexpr struct { bool is_sync_allowed; + bool signin_error; int locale_index; bool is_dismissed; int show_count; @@ -110,36 +155,44 @@ bool promo_done; bool result; } kTestData[] = { - // {sync allowed, locale, dismissed before, impression count, seen days + // {sync allowed, signin error exist, locale, dismissed before, impression + // count, seen days // ago, bitmask with entry points seen, is user eligible, flow was // completed before, expected result } - {false, 0, false, 0, 1, 0, false, false, false}, - {false, 1, false, 0, 3, 0, true, false, false}, - {true, 3, false, 0, 4, 0, true, false, false}, - {true, 2, false, 0, 10, 0, true, false, false}, - {true, 0, true, 1, 3, 0, true, false, false}, - {true, 0, false, 3, 1, 0, true, false, false}, - {true, 0, false, 1, 3, - 1 << static_cast<int>( - desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE), - true, false, false}, - {true, 0, false, 0, 4, - 1 << static_cast<int>( - desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_BUBBLE), - true, false, false}, - {true, 0, false, 1, 10, 0, false, false, false}, - {true, 0, false, 0, 1, 0, true, true, false}, - {true, 1, false, 1, 1, 0, true, false, true}, - {true, 1, false, 0, 2, 0, true, false, true}, - {true, 0, false, 0, 8, - 1 << static_cast<int>( - desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE), - true, false, true}, + {false, false, 0, false, 0, 1, 0, false, false, false}, + {false, false, 1, false, 0, 3, 0, true, false, false}, + {true, false, 3, false, 0, 4, 0, true, false, false}, + {true, false, 2, false, 0, 10, 0, true, false, false}, + {true, false, 0, true, 1, 3, 0, true, false, false}, + {true, false, 0, false, 3, 1, 0, true, false, false}, + {true, false, 0, false, 1, 3, kSMSEntrypointSavePasswordBubble, true, + false, false}, + {true, false, 0, false, 0, 4, kSMSEntrypointBookmarksBubble, true, false, + false}, + {true, false, 0, false, 1, 10, 0, false, false, false}, + {true, false, 0, false, 0, 1, 0, true, true, false}, + {true, true, 1, false, 1, 1, 0, true, false, false}, + {true, false, 1, false, 1, 1, 0, true, false, true}, + {true, false, 1, false, 0, 2, 0, true, false, true}, + {true, true, 0, false, 0, 8, kSMSEntrypointSavePasswordBubble, true, + false, false}, + {true, false, 0, false, 0, 8, kSMSEntrypointSavePasswordBubble, true, + false, true}, }; std::string locale = base::i18n::GetConfiguredLocale(); + FakeAuthStatusProvider auth_provider( + SigninErrorControllerFactory::GetForProfile(profile())); + for (const auto& test_case : kTestData) { SCOPED_TRACE(testing::Message("#test_case = ") << (&test_case - kTestData)); sync_service()->set_sync_allowed(test_case.is_sync_allowed); + const GoogleServiceAuthError error( + test_case.signin_error + ? GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS + : GoogleServiceAuthError::NONE); + + auth_provider.SetAuthError("test", error); + local_state()->SetBoolean(prefs::kSavePasswordsBubbleIOSPromoDismissed, test_case.is_dismissed); local_state()->SetInteger(prefs::kNumberSavePasswordsBubbleIOSPromoShown, @@ -153,7 +206,7 @@ test_case.is_user_eligible); prefs()->SetBoolean(prefs::kIOSPromotionDone, test_case.promo_done); EXPECT_EQ(test_case.result, - IsEligibleForIOSPromotion(prefs(), sync_service(), entry_point)); + IsEligibleForIOSPromotion(profile(), entry_point)); } base::i18n::SetICUDefaultLocale(locale); }
diff --git a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc index 6d0dce9..d5cd143 100644 --- a/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc +++ b/chrome/browser/ui/passwords/manage_passwords_bubble_model.cc
@@ -461,7 +461,7 @@ #if defined(OS_WIN) // Desktop to mobile promotion only enabled on windows. if (desktop_ios_promotion::IsEligibleForIOSPromotion( - prefs, sync_service, + GetProfile(), desktop_ios_promotion::PromotionEntryPoint::SAVE_PASSWORD_BUBBLE)) { interaction_keeper_->ReportInteractions(this); title_brand_link_range_ = gfx::Range();
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc index ed2397d..34d93b7 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.cc
@@ -34,10 +34,8 @@ #include "ui/views/window/dialog_client_view.h" #if defined(OS_WIN) -#include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_bubble_view.h" #include "chrome/browser/ui/views/desktop_ios_promotion/desktop_ios_promotion_footnote_view.h" -#include "components/browser_sync/profile_sync_service.h" #endif using base::UserMetricsAction; @@ -202,7 +200,8 @@ views::View* BookmarkBubbleView::CreateFootnoteView() { #if defined(OS_WIN) if (!is_showing_ios_promotion_ && - IsIOSPromotionEligible( + desktop_ios_promotion::IsEligibleForIOSPromotion( + profile_, desktop_ios_promotion::PromotionEntryPoint::BOOKMARKS_FOOTNOTE)) { footnote_view_ = new DesktopIOSPromotionFootnoteView(profile_, this); return footnote_view_; @@ -230,7 +229,8 @@ bool BookmarkBubbleView::Accept() { #if defined(OS_WIN) using desktop_ios_promotion::PromotionEntryPoint; - if (IsIOSPromotionEligible(PromotionEntryPoint::BOOKMARKS_BUBBLE)) { + if (desktop_ios_promotion::IsEligibleForIOSPromotion( + profile_, PromotionEntryPoint::BOOKMARKS_BUBBLE)) { ShowIOSPromotion(PromotionEntryPoint::BOOKMARKS_BUBBLE); return false; } @@ -416,16 +416,6 @@ } #if defined(OS_WIN) - -bool BookmarkBubbleView::IsIOSPromotionEligible( - desktop_ios_promotion::PromotionEntryPoint entry_point) { - PrefService* prefs = profile_->GetPrefs(); - const browser_sync::ProfileSyncService* sync_service = - ProfileSyncServiceFactory::GetForProfile(profile_); - return desktop_ios_promotion::IsEligibleForIOSPromotion(prefs, sync_service, - entry_point); -} - void BookmarkBubbleView::ShowIOSPromotion( desktop_ios_promotion::PromotionEntryPoint entry_point) { DCHECK(!is_showing_ios_promotion_);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h index 8adbc07..e60642fe 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h
@@ -119,10 +119,6 @@ void ApplyEdits(); #if defined(OS_WIN) - // Check eligibility to show the iOS promotion from a specific entry point. - bool IsIOSPromotionEligible( - desktop_ios_promotion::PromotionEntryPoint entry_point); - // Shows the iOS promotion. void ShowIOSPromotion(desktop_ios_promotion::PromotionEntryPoint entry_point); #endif
diff --git a/chrome/browser/ui/views/frame/browser_view_unittest.cc b/chrome/browser/ui/views/frame/browser_view_unittest.cc index 3a13912..de6477ba7 100644 --- a/chrome/browser/ui/views/frame/browser_view_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_view_unittest.cc
@@ -6,6 +6,7 @@ #include "base/macros.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" #include "chrome/browser/ui/views/frame/browser_view_layout.h" @@ -114,6 +115,9 @@ BookmarkBarView* bookmark_bar = browser_view()->GetBookmarkBarView(); EXPECT_FALSE(bookmark_bar->visible()); EXPECT_FALSE(bookmark_bar->IsDetached()); + EXPECT_EQ(devtools_web_view->y(), bookmark_bar->height()); + EXPECT_EQ(chrome::kMinimumBookmarkBarHeight, + bookmark_bar->GetMinimumSize().height()); chrome::ExecuteCommand(browser, IDC_SHOW_BOOKMARK_BAR); EXPECT_TRUE(bookmark_bar->visible()); EXPECT_FALSE(bookmark_bar->IsDetached());
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc index 624d469..5fc23338 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
@@ -55,7 +55,6 @@ ~PermissionsBubbleDialogDelegateView() override; void CloseBubble(); - void SizeToContents(); // BubbleDialogDelegateView: bool ShouldShowCloseButton() const override; @@ -69,6 +68,7 @@ int GetDefaultDialogButton() const override; int GetDialogButtons() const override; base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; + void SizeToContents() override; // Updates the anchor's arrow and view. Also repositions the bubble so it's // displayed in the correct location.
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc index 4d403d8a..ab599f61 100644 --- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc +++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.cc
@@ -14,29 +14,30 @@ #include "base/guid.h" #include "base/memory/ptr_util.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/android/offline_pages/offline_page_model_factory.h" #include "chrome/browser/android/offline_pages/prefetch/prefetch_background_task.h" #include "chrome/browser/android/offline_pages/request_coordinator_factory.h" #include "chrome/browser/offline_pages/prefetch/prefetch_service_factory.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/common/channel_info.h" +#include "chrome/common/chrome_content_client.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/offline_page_feature.h" +#include "components/offline_pages/core/prefetch/generate_page_bundle_request.h" +#include "components/offline_pages/core/prefetch/get_operation_request.h" #include "components/offline_pages/core/prefetch/prefetch_service.h" #include "content/public/browser/web_ui.h" #include "net/base/network_change_notifier.h" namespace offline_internals { -OfflineInternalsUIMessageHandler::OfflineInternalsUIMessageHandler() - : offline_page_model_(nullptr), - request_coordinator_(nullptr), - prefetch_service_(nullptr), - weak_ptr_factory_(this) {} +namespace { -OfflineInternalsUIMessageHandler::~OfflineInternalsUIMessageHandler() {} - -std::string OfflineInternalsUIMessageHandler::GetStringFromDeletePageResult( +std::string GetStringFromDeletePageResult( offline_pages::DeletePageResult value) { switch (value) { case offline_pages::DeletePageResult::SUCCESS: @@ -56,7 +57,7 @@ return "Unknown"; } -std::string OfflineInternalsUIMessageHandler::GetStringFromDeleteRequestResults( +std::string GetStringFromDeleteRequestResults( const offline_pages::MultipleItemStatuses& results) { // If any requests failed, return "failure", else "success". for (const auto& result : results) { @@ -67,10 +68,62 @@ return "Success"; } -std::string OfflineInternalsUIMessageHandler::GetStringFromSavePageStatus() { +std::string GetStringFromSavePageStatus() { return "Available"; } +std::string GetStringFromPrefetchRequestStatus( + offline_pages::PrefetchRequestStatus status) { + switch (status) { + case offline_pages::PrefetchRequestStatus::SUCCESS: + return "Success"; + case offline_pages::PrefetchRequestStatus::SHOULD_RETRY_WITHOUT_BACKOFF: + return "Retry w/out backoff"; + case offline_pages::PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF: + return "Retry w/ backoff"; + case offline_pages::PrefetchRequestStatus::SHOULD_SUSPEND: + return "Suspend"; + default: + NOTREACHED(); + return "Unknown"; + } +} + +std::string GetStringRenderPageInfoList( + const std::vector<offline_pages::RenderPageInfo>& pages) { + std::string str("[\n"); + bool first = true; + for (const auto& page : pages) { + if (first) + first = false; + else + str += ",\n"; + str += base::StringPrintf( + " {\n" + " url: \"%s\",\n" + " redirect_url: \"%s\",\n" + " status: %d,\n" + " body_name: \"%s\",\n" + " body_length: %lld\n" + " }", + page.url.c_str(), page.redirect_url.c_str(), + static_cast<int>(page.status), page.body_name.c_str(), + static_cast<long long>(page.body_length)); + } + str += "\n]"; + return str; +} + +} // namespace + +OfflineInternalsUIMessageHandler::OfflineInternalsUIMessageHandler() + : offline_page_model_(nullptr), + request_coordinator_(nullptr), + prefetch_service_(nullptr), + weak_ptr_factory_(this) {} + +OfflineInternalsUIMessageHandler::~OfflineInternalsUIMessageHandler() {} + void OfflineInternalsUIMessageHandler::HandleDeleteSelectedPages( const base::ListValue* args) { std::string callback_id; @@ -257,6 +310,55 @@ ResolveJavascriptCallback(*callback_id, base::Value("Cancelled.")); } +void OfflineInternalsUIMessageHandler::HandleGeneratePageBundle( + const base::ListValue* args) { + AllowJavascript(); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + + std::string data; + CHECK(args->GetString(1, &data)); + std::vector<std::string> page_urls = base::SplitStringUsingSubstr( + data, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + + generate_page_bundle_request_.reset( + new offline_pages::GeneratePageBundleRequest( + GetUserAgent(), "GCM ID", 1000000, page_urls, chrome::GetChannel(), + Profile::FromWebUI(web_ui())->GetRequestContext(), + base::Bind( + &OfflineInternalsUIMessageHandler::HandlePrefetchRequestCallback, + weak_ptr_factory_.GetWeakPtr(), callback_id))); +} + +void OfflineInternalsUIMessageHandler::HandleGetOperation( + const base::ListValue* args) { + AllowJavascript(); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + + std::string name; + CHECK(args->GetString(1, &name)); + base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name); + + get_operation_request_.reset(new offline_pages::GetOperationRequest( + name, chrome::GetChannel(), + Profile::FromWebUI(web_ui())->GetRequestContext(), + base::Bind( + &OfflineInternalsUIMessageHandler::HandlePrefetchRequestCallback, + weak_ptr_factory_.GetWeakPtr(), callback_id))); +} + +void OfflineInternalsUIMessageHandler::HandlePrefetchRequestCallback( + std::string callback_id, + offline_pages::PrefetchRequestStatus status, + const std::string& operation_name, + const std::vector<offline_pages::RenderPageInfo>& pages) { + ResolveJavascriptCallback( + base::Value(callback_id), + base::Value(GetStringFromPrefetchRequestStatus(status) + "\n" + + operation_name + "\n" + GetStringRenderPageInfoList(pages))); +} + void OfflineInternalsUIMessageHandler::HandleSetRecordRequestQueue( const base::ListValue* args) { AllowJavascript(); @@ -400,6 +502,14 @@ "cancelNwake", base::Bind(&OfflineInternalsUIMessageHandler::HandleCancelNwake, weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "generatePageBundle", + base::Bind(&OfflineInternalsUIMessageHandler::HandleGeneratePageBundle, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "getOperation", + base::Bind(&OfflineInternalsUIMessageHandler::HandleGetOperation, + weak_ptr_factory_.GetWeakPtr())); // Get the offline page model associated with this web ui. Profile* profile = Profile::FromWebUI(web_ui());
diff --git a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h index 9fc42c6..61da1724 100644 --- a/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h +++ b/chrome/browser/ui/webui/offline/offline_internals_ui_message_handler.h
@@ -15,11 +15,14 @@ #include "components/offline_pages/core/background/save_page_request.h" #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/offline_store_types.h" +#include "components/offline_pages/core/prefetch/prefetch_types.h" #include "content/public/browser/web_ui_message_handler.h" namespace offline_pages { class PrefetchService; enum class GetRequestsResult; +class GeneratePageBundleRequest; +class GetOperationRequest; } namespace offline_internals { @@ -73,6 +76,12 @@ // Cancels an NWake signal. void HandleCancelNwake(const base::ListValue* args); + // Sends and processes the request to generate page bundle. + void HandleGeneratePageBundle(const base::ListValue* args); + + // Sends and processes a request to get the info about an operation. + void HandleGetOperation(const base::ListValue* args); + // Callback for async GetAllPages calls. void HandleStoredPagesCallback( std::string callback_id, @@ -93,16 +102,18 @@ std::string callback_id, const offline_pages::MultipleItemStatuses& results); - // Turns a DeletePageResult enum into logical string. - std::string GetStringFromDeletePageResult( - offline_pages::DeletePageResult value); + // Callback for GeneratePageBundle/GetOperation request calls. + void HandlePrefetchRequestCallback( + std::string callback_id, + offline_pages::PrefetchRequestStatus status, + const std::string& operation_name, + const std::vector<offline_pages::RenderPageInfo>& pages); - // Summarizes the MultipleItemStatuses vector with a string. - std::string GetStringFromDeleteRequestResults( - const offline_pages::MultipleItemStatuses& result); - - // Turns a SavePageRequest::Status into logical string. - std::string GetStringFromSavePageStatus(); + // Callback for GetOperation calls. + void HandleGetOperationCallback( + std::string callback_id, + offline_pages::PrefetchRequestStatus status, + const std::vector<offline_pages::RenderPageInfo>& pages); // Offline page model to call methods on. offline_pages::OfflinePageModel* offline_page_model_; @@ -113,6 +124,10 @@ // Prefetch service for prefetching service logs and actions. offline_pages::PrefetchService* prefetch_service_; + std::unique_ptr<offline_pages::GeneratePageBundleRequest> + generate_page_bundle_request_; + std::unique_ptr<offline_pages::GetOperationRequest> get_operation_request_; + // Factory for creating references in callbacks. base::WeakPtrFactory<OfflineInternalsUIMessageHandler> weak_ptr_factory_;
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc index 2814faff..2d32a54 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.cc
@@ -173,7 +173,7 @@ ->DispatchGetCapabilityRequested( destination_id, base::Bind(&ExtensionPrinterHandler::WrapGetCapabilityCallback, - weak_ptr_factory_.GetWeakPtr(), callback, destination_id)); + weak_ptr_factory_.GetWeakPtr(), callback)); } void ExtensionPrinterHandler::StartPrint( @@ -300,9 +300,8 @@ void ExtensionPrinterHandler::WrapGetCapabilityCallback( const PrinterHandler::GetCapabilityCallback& callback, - const std::string& destination_id, const base::DictionaryValue& capability) { - callback.Run(destination_id, capability); + callback.Run(capability); } void ExtensionPrinterHandler::WrapPrintCallback(
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h index 183d172..266cc117 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler.h
@@ -102,7 +102,6 @@ bool done); void WrapGetCapabilityCallback( const PrinterHandler::GetCapabilityCallback& callback, - const std::string& destination_id, const base::DictionaryValue& capability); void WrapPrintCallback(const PrinterHandler::PrintCallback& callback, bool success,
diff --git a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc index 668f8d6d6..94d1ab7 100644 --- a/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/extension_printer_handler_unittest.cc
@@ -203,12 +203,9 @@ // Used as a callback to StartGetCapability in tests. // Increases |*call_count| and records values returned by StartGetCapability. void RecordCapability(size_t* call_count, - std::string* destination_id_out, std::unique_ptr<base::DictionaryValue>* capability_out, - const std::string& destination_id, const base::DictionaryValue& capability) { ++(*call_count); - *destination_id_out = destination_id; capability_out->reset(capability.DeepCopy()); } @@ -609,12 +606,10 @@ TEST_F(ExtensionPrinterHandlerTest, GetCapability) { size_t call_count = 0; - std::string destination_id; std::unique_ptr<base::DictionaryValue> capability; extension_printer_handler_->StartGetCapability( - kPrinterId, - base::Bind(&RecordCapability, &call_count, &destination_id, &capability)); + kPrinterId, base::Bind(&RecordCapability, &call_count, &capability)); EXPECT_EQ(0u, call_count); @@ -631,7 +626,6 @@ fake_api->TriggerNextGetCapabilityCallback(*original_capability); EXPECT_EQ(1u, call_count); - EXPECT_EQ(kPrinterId, destination_id); ASSERT_TRUE(capability.get()); EXPECT_TRUE(capability->Equals(original_capability.get())) << *capability << ", expected: " << *original_capability; @@ -639,12 +633,10 @@ TEST_F(ExtensionPrinterHandlerTest, GetCapability_Reset) { size_t call_count = 0; - std::string destination_id; std::unique_ptr<base::DictionaryValue> capability; extension_printer_handler_->StartGetCapability( - kPrinterId, - base::Bind(&RecordCapability, &call_count, &destination_id, &capability)); + kPrinterId, base::Bind(&RecordCapability, &call_count, &capability)); EXPECT_EQ(0u, call_count);
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index e0a11e502..16b30f20 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -682,7 +682,7 @@ AllowJavascript(); if (!PrivetPrintingEnabled()) { - RejectJavascriptCallback(base::Value(callback_id), base::Value(false)); + RejectJavascriptCallback(base::Value(callback_id), base::Value()); } #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) using local_discovery::ServiceDiscoverySharedClient; @@ -701,20 +701,30 @@ printer_lister_->Stop(); } ResolveJavascriptCallback(base::Value(privet_callback_id_), base::Value()); + privet_callback_id_ = ""; #endif } void PrintPreviewHandler::HandleGetPrivetPrinterCapabilities( const base::ListValue* args) { -#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) - std::string name; - bool success = args->GetString(0, &name); - DCHECK(success); + AllowJavascript(); - CreatePrivetHTTP( - name, base::Bind(&PrintPreviewHandler::PrivetCapabilitiesUpdateClient, - weak_factory_.GetWeakPtr())); + std::string callback_id; + std::string printer_name; + if (!args->GetString(0, &callback_id) || !args->GetString(1, &printer_name) || + callback_id.empty() || printer_name.empty()) { + RejectJavascriptCallback(base::Value(callback_id), base::Value()); + return; + } +#if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) + if (CreatePrivetHTTP( + printer_name, + base::Bind(&PrintPreviewHandler::PrivetCapabilitiesUpdateClient, + weak_factory_.GetWeakPtr(), callback_id))) { + return; + } #endif + RejectJavascriptCallback(base::Value(callback_id), base::Value()); } void PrintPreviewHandler::HandleGetExtensionPrinters( @@ -747,15 +757,21 @@ void PrintPreviewHandler::HandleGetExtensionPrinterCapabilities( const base::ListValue* args) { - std::string printer_id; - bool ok = args->GetString(0, &printer_id); - DCHECK(ok); + AllowJavascript(); + + std::string callback_id; + std::string printer_name; + if (!args->GetString(0, &callback_id) || !args->GetString(1, &printer_name) || + callback_id.empty() || printer_name.empty()) { + RejectJavascriptCallback(base::Value(callback_id), base::Value()); + return; + } EnsureExtensionPrinterHandlerSet(); extension_printer_handler_->StartGetCapability( - printer_id, + printer_name, base::Bind(&PrintPreviewHandler::OnGotExtensionPrinterCapabilities, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), callback_id)); } void PrintPreviewHandler::HandleGetPreview(const base::ListValue* args) { @@ -1071,10 +1087,15 @@ void PrintPreviewHandler::HandleGetPrinterCapabilities( const base::ListValue* args) { + AllowJavascript(); + + std::string callback_id; std::string printer_name; - bool ret = args->GetString(0, &printer_name); - if (!ret || printer_name.empty()) + if (!args->GetString(0, &callback_id) || !args->GetString(1, &printer_name) || + callback_id.empty() || printer_name.empty()) { + RejectJavascriptCallback(base::Value(callback_id), base::Value()); return; + } if (printer_name == kLocalPdfPrinterId) { auto printer_info = base::MakeUnique<base::DictionaryValue>(); @@ -1082,13 +1103,13 @@ printer_info->Set( printing::kPrinterCapabilities, GetPdfCapabilities(g_browser_process->GetApplicationLocale())); - SendPrinterCapabilities(printer_name, std::move(printer_info)); + SendPrinterCapabilities(callback_id, printer_name, std::move(printer_info)); return; } printing::PrinterSetupCallback cb = base::Bind(&PrintPreviewHandler::SendPrinterCapabilities, - weak_factory_.GetWeakPtr(), printer_name); + weak_factory_.GetWeakPtr(), callback_id, printer_name); printer_backend_proxy()->ConfigurePrinterAndFetchCapabilities(printer_name, cb); @@ -1307,19 +1328,18 @@ } void PrintPreviewHandler::SendPrinterCapabilities( + const std::string& callback_id, const std::string& printer_name, std::unique_ptr<base::DictionaryValue> settings_info) { // Check that |settings_info| is valid. if (settings_info && settings_info->Get("capabilities", nullptr)) { VLOG(1) << "Get printer capabilities finished"; - web_ui()->CallJavascriptFunctionUnsafe("updateWithPrinterCapabilities", - *settings_info); + ResolveJavascriptCallback(base::Value(callback_id), *settings_info); return; } VLOG(1) << "Get printer capabilities failed"; - web_ui()->CallJavascriptFunctionUnsafe("failedToGetPrinterCapabilities", - base::Value(printer_name)); + RejectJavascriptCallback(base::Value(callback_id), base::Value()); } void PrintPreviewHandler::SendPrinterSetup( @@ -1570,21 +1590,30 @@ } void PrintPreviewHandler::PrivetCapabilitiesUpdateClient( + const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { - if (!PrivetUpdateClient(std::move(http_client))) + if (!PrivetUpdateClient(callback_id, std::move(http_client))) return; privet_capabilities_operation_ = privet_http_client_->CreateCapabilitiesOperation( base::Bind(&PrintPreviewHandler::OnPrivetCapabilities, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), callback_id)); privet_capabilities_operation_->Start(); } bool PrintPreviewHandler::PrivetUpdateClient( + const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { if (!http_client) { - SendPrivetCapabilitiesError(privet_http_resolution_->GetName()); + if (callback_id.empty()) { + // This was an attempt to print to a privet printer and has failed. + base::Value http_code_value(-1); + web_ui()->CallJavascriptFunctionUnsafe("onPrivetPrintFailed", + http_code_value); + } else { // Capabilities update failed + RejectJavascriptCallback(base::Value(callback_id), base::Value()); + } privet_http_resolution_.reset(); return false; } @@ -1604,7 +1633,7 @@ std::string capabilities, gfx::Size page_size, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client) { - if (!PrivetUpdateClient(std::move(http_client))) + if (!PrivetUpdateClient("", std::move(http_client))) return; StartPrivetLocalPrint(print_ticket, capabilities, page_size); @@ -1645,49 +1674,52 @@ privet_local_print_operation_->Start(); } - void PrintPreviewHandler::OnPrivetCapabilities( + const std::string& callback_id, const base::DictionaryValue* capabilities) { std::string name = privet_capabilities_operation_->GetHTTPClient()->GetName(); if (!capabilities || capabilities->HasKey(cloud_print::kPrivetKeyError) || !printer_lister_) { - SendPrivetCapabilitiesError(name); + RejectJavascriptCallback(base::Value(callback_id), base::Value()); return; } - base::DictionaryValue printer_info; const cloud_print::DeviceDescription* description = printer_lister_->GetDeviceDescription(name); if (!description) { - SendPrivetCapabilitiesError(name); + RejectJavascriptCallback(base::Value(callback_id), base::Value()); return; } - FillPrinterDescription(name, *description, true, &printer_info); - - web_ui()->CallJavascriptFunctionUnsafe("onPrivetCapabilitiesSet", - printer_info, *capabilities); + std::unique_ptr<base::DictionaryValue> printer_info = + base::MakeUnique<base::DictionaryValue>(); + FillPrinterDescription(name, *description, true, printer_info.get()); + base::DictionaryValue printer_info_and_caps; + printer_info_and_caps.SetDictionary("printer", std::move(printer_info)); + std::unique_ptr<base::DictionaryValue> capabilities_copy = + capabilities->CreateDeepCopy(); + printer_info_and_caps.SetDictionary("capabilities", + std::move(capabilities_copy)); + ResolveJavascriptCallback(base::Value(callback_id), printer_info_and_caps); privet_capabilities_operation_.reset(); } -void PrintPreviewHandler::SendPrivetCapabilitiesError( - const std::string& device_name) { - base::Value name_value(device_name); - web_ui()->CallJavascriptFunctionUnsafe("failedToGetPrivetPrinterCapabilities", - name_value); -} - void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& device_name, const std::string& ticket, const std::string& capabilities, const gfx::Size& page_size) { - CreatePrivetHTTP( - device_name, - base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient, - weak_factory_.GetWeakPtr(), ticket, capabilities, page_size)); + if (!CreatePrivetHTTP( + device_name, + base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient, + weak_factory_.GetWeakPtr(), ticket, capabilities, + page_size))) { + base::Value http_code_value(-1); + web_ui()->CallJavascriptFunctionUnsafe("onPrivetPrintFailed", + http_code_value); + } } bool PrintPreviewHandler::CreatePrivetHTTP( @@ -1697,10 +1729,8 @@ const cloud_print::DeviceDescription* device_description = printer_lister_ ? printer_lister_->GetDeviceDescription(name) : NULL; - if (!device_description) { - SendPrivetCapabilitiesError(name); + if (!device_description) return false; - } privet_http_factory_ = cloud_print::PrivetHTTPAsynchronousFactory::CreateInstance( @@ -1776,16 +1806,13 @@ } void PrintPreviewHandler::OnGotExtensionPrinterCapabilities( - const std::string& printer_id, + const std::string& callback_id, const base::DictionaryValue& capabilities) { if (capabilities.empty()) { - web_ui()->CallJavascriptFunctionUnsafe( - "failedToGetExtensionPrinterCapabilities", base::Value(printer_id)); + RejectJavascriptCallback(base::Value(callback_id), base::Value()); return; } - - web_ui()->CallJavascriptFunctionUnsafe("onExtensionCapabilitiesSet", - base::Value(printer_id), capabilities); + ResolveJavascriptCallback(base::Value(callback_id), capabilities); } void PrintPreviewHandler::OnExtensionPrintResult(bool success,
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 61133eb6..f1884810 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -230,6 +230,7 @@ // printer capabilities information. If |settings_info| is empty, sends // error notification to the Web UI instead. void SendPrinterCapabilities( + const std::string& callback_id, const std::string& printer_name, std::unique_ptr<base::DictionaryValue> settings_info); @@ -285,8 +286,10 @@ void StartPrivetLister(const scoped_refptr< local_discovery::ServiceDiscoverySharedClient>& client); void StopPrivetLister(); - void OnPrivetCapabilities(const base::DictionaryValue* capabilities); + void OnPrivetCapabilities(const std::string& callback_id, + const base::DictionaryValue* capabilities); void PrivetCapabilitiesUpdateClient( + const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client); void PrivetLocalPrintUpdateClient( std::string print_ticket, @@ -294,6 +297,7 @@ gfx::Size page_size, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client); bool PrivetUpdateClient( + const std::string& callback_id, std::unique_ptr<cloud_print::PrivetHTTPClient> http_client); void StartPrivetLocalPrint(const std::string& print_ticket, const std::string& capabilities, @@ -337,10 +341,10 @@ // Called when an extension reports the set of print capabilites for a // printer. - // |printer_id|: The id of the printer whose capabilities are reported. + // |callback_id|: The Javascript callback to reject or resolve // |capabilities|: The printer capabilities. void OnGotExtensionPrinterCapabilities( - const std::string& printer_id, + const std::string& callback_id, const base::DictionaryValue& capabilities); // Called when an extension print job is completed.
diff --git a/chrome/browser/ui/webui/print_preview/printer_handler.h b/chrome/browser/ui/webui/print_preview/printer_handler.h index ccf12af9e2..58b215f6 100644 --- a/chrome/browser/ui/webui/print_preview/printer_handler.h +++ b/chrome/browser/ui/webui/print_preview/printer_handler.h
@@ -35,8 +35,7 @@ using GetPrintersCallback = base::Callback<void(const base::ListValue& printers, bool done)>; using GetCapabilityCallback = - base::Callback<void(const std::string& printer_id, - const base::DictionaryValue& capability)>; + base::Callback<void(const base::DictionaryValue& capability)>; using PrintCallback = base::Callback<void(bool success, const std::string& error)>; using GetPrinterInfoCallback =
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index a76c765..2a8196d 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -569,13 +569,6 @@ // Forces the maximum disk space to be used by the media cache, in bytes. const char kMediaCacheSize[] = "media-cache-size"; -// Enables the recording of metrics reports but disables reporting. In contrast -// to kDisableMetrics, this executes all the code that a normal client would -// use for reporting, except the report is dropped rather than sent to the -// server. This is useful for finding issues in the metrics code during UI and -// performance tests. -const char kMetricsRecordingOnly[] = "metrics-recording-only"; - // Allows setting a different destination ID for connection-monitoring GCM // messages. Useful when running against a non-prod management server. const char kMonitoringDestinationID[] = "monitoring-destination-id";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index bd0145c..dec100fe 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -167,7 +167,6 @@ extern const char kLoadMediaRouterComponentExtension[]; extern const char kMakeDefaultBrowser[]; extern const char kMediaCacheSize[]; -extern const char kMetricsRecordingOnly[]; extern const char kMonitoringDestinationID[]; extern const char kNetLogCaptureMode[]; extern const char kNoDefaultBrowserCheck[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 3d183dc..7e40976 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3153,7 +3153,6 @@ "../browser/page_load_metrics/observers/page_load_metrics_observer_test_harness.h", "../browser/page_load_metrics/observers/previews_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/protocol_page_load_metrics_observer_unittest.cc", - "../browser/page_load_metrics/observers/resource_tracking_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/service_worker_page_load_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/subresource_filter_metrics_observer_unittest.cc", "../browser/page_load_metrics/observers/tab_restore_page_load_metrics_observer_unittest.cc", @@ -4868,6 +4867,7 @@ "../browser/ui/app_list/arc/arc_app_unittest.cc", "../browser/ui/app_list/extension_app_model_builder_unittest.cc", "../browser/ui/app_list/profile_loader_unittest.cc", + "../browser/ui/app_list/search/answer_card_result_unittest.cc", "../browser/ui/app_list/search/app_search_provider_unittest.cc", "../browser/ui/app_list/search/history_unittest.cc", "../browser/ui/app_list/search/launcher_search/launcher_search_icon_image_loader_unittest.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java index e0919ad..60899e8 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCaseBase.java
@@ -377,13 +377,6 @@ } @Override - protected void runTest() throws Throwable { - String perfTagAnalysisString = mTestCommon.setupPotentialPerfTest(); - super.runTest(); - mTestCommon.endPerfTest(perfTagAnalysisString); - } - - @Override protected Map<String, BaseParameter> createAvailableParameters() { Map<String, BaseParameter> availableParameters = super.createAvailableParameters(); availableParameters.put(AddFakeAccountToAppParameter.PARAMETER_TAG,
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java index c26b1ac..219ebce5e 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestCommon.java
@@ -23,11 +23,8 @@ import org.chromium.base.ApplicationStatus; import org.chromium.base.ApplicationStatus.ActivityStateListener; import org.chromium.base.Log; -import org.chromium.base.PerfTraceEvent; import org.chromium.base.ThreadUtils; -import org.chromium.base.annotations.SuppressFBWarnings; import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.PerfTest; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -60,11 +57,9 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.ui.base.PageTransition; -import java.io.File; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; import java.util.Calendar; -import java.util.LinkedList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -668,122 +663,6 @@ mCallback.getActivity(), expectedScale); } - /** - * This method creates a special string that tells the python test harness what - * trace calls to track for this particular test run. It can support multiple trace calls for - * each test and will make a new graph entry for all of them. It should be noted that this - * method eats all exceptions. This is so that it can never be the cause of a test failure. - * We still need to call this method even if we know the test will not run (ie: willTestRun is - * false). This is because this method lets the python test harness know not to expect any - * perf output in this case. In the case that the autoTrace parameter is set for the current - * test method, this will also start the PerfTrace facility automatically. - * - * @return A specially formatted string that contains which JSON perf markers to look at. This - * will be analyzed by the perf test harness. - */ - @SuppressFBWarnings({ - "REC_CATCH_EXCEPTION", "RV_RETURN_VALUE_IGNORED_BAD_PRACTICE", }) - String setupPotentialPerfTest() { - File perfFile = mCallback.getInstrumentation().getTargetContext().getFileStreamPath( - PERF_OUTPUT_FILE); - perfFile.delete(); - PerfTraceEvent.setOutputFile(perfFile); - - String perfAnnotationString = ""; - - try { - Method method = getClass().getMethod(mCallback.getTestName(), (Class[]) null); - PerfTest annotation = method.getAnnotation(PerfTest.class); - if (annotation != null) { - StringBuilder annotationData = new StringBuilder(); - annotationData.append(String.format(PERF_ANNOTATION_FORMAT, method.getName())); - - // Grab the minimum number of trace calls we will track (if names(), - // graphNames(), and graphValues() do not have the same number of elements, we - // will track as many as we can given the data available. - final int maxIndex = Math.min(annotation.traceNames().length, - Math.min(annotation.graphNames().length, annotation.seriesNames().length)); - - List<String> allNames = new LinkedList<>(); - for (int i = 0; i < maxIndex; ++i) { - // Prune out all of ',' and ';' from the strings. Replace them with '-'. - String name = annotation.traceNames()[i].replaceAll("[,;]", "-"); - allNames.add(name); - String graphName = annotation.graphNames()[i].replaceAll("[,;]", "-"); - String seriesName = annotation.seriesNames()[i].replaceAll("[,;]", "-"); - if (annotation.traceTiming()) { - annotationData.append(name) - .append(",") - .append(graphName) - .append(",") - .append(seriesName) - .append(';'); - } - - // If memory tracing is enabled, add an additional graph for each one - // defined to track timing perf that will track the corresponding memory - // usage. - // Keep the series name the same, but just append a memory identifying - // prefix to the graph. - if (annotation.traceMemory()) { - String memName = PerfTraceEvent.makeMemoryTraceNameFromTimingName(name); - String memGraphName = PerfTraceEvent.makeSafeTraceName( - graphName, MEMORY_TRACE_GRAPH_SUFFIX); - annotationData.append(memName) - .append(",") - .append(memGraphName) - .append(",") - .append(seriesName) - .append(';'); - allNames.add(memName); - } - } - // We only record perf trace events for the names explicitly listed. - PerfTraceEvent.setFilter(allNames); - - // Figure out if we should automatically start or stop the trace. - if (annotation.autoTrace()) { - PerfTraceEvent.setEnabled(true); - } - PerfTraceEvent.setTimingTrackingEnabled(annotation.traceTiming()); - PerfTraceEvent.setMemoryTrackingEnabled(annotation.traceMemory()); - - perfAnnotationString = annotationData.toString(); - } - } catch (Exception ex) { - // Eat exception here. - } - - return perfAnnotationString; - } - - /** - * This handles cleaning up the performance component of this test if it was a UI Perf test. - * This includes potentially shutting down PerfTraceEvent. This method eats all exceptions so - * that it can never be the cause of a test failure. The test harness will wait for - * {@code perfTagAnalysisString} to show up in the logcat before processing the JSON perf file, - * giving this method the chance to flush and dump the performance data before the harness reads - * it. - * - * @param perfTagAnalysisString A specially formatted string that tells the perf test harness - * which perf tags to analyze. - */ - void endPerfTest(String perfTagAnalysisString) { - try { - Method method = getClass().getMethod(mCallback.getTestName(), (Class[]) null); - PerfTest annotation = method.getAnnotation(PerfTest.class); - if (annotation != null) { - if (PerfTraceEvent.enabled()) { - PerfTraceEvent.setEnabled(false); - } - - System.out.println(perfTagAnalysisString); - } - } catch (NoSuchMethodException ex) { - // Eat exception here. - } - } - public interface ChromeTestCommonCallback<T extends ChromeActivity> { String getTestName(); void setActivity(T t);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 32db790..0ab29e9 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -59,14 +59,7 @@ base.evaluate(); } }, description); - return new Statement() { - @Override - public void evaluate() throws Throwable { - String perfTagAnalysisString = mTestCommon.setupPotentialPerfTest(); - superBase.evaluate(); - mTestCommon.endPerfTest(perfTagAnalysisString); - } - }; + return superBase; } /**
diff --git a/chrome/test/data/webui/print_preview/native_layer_stub.js b/chrome/test/data/webui/print_preview/native_layer_stub.js index 51f80161..73ba1244 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.js +++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -14,6 +14,7 @@ 'getPrinters', 'getExtensionPrinters', 'getPrivetPrinters', + 'getPrinterCapabilities', 'setupPrinter' ]); @@ -46,6 +47,14 @@ this.localDestinationInfos_ = []; /** + * @private {!Map<string, + * !Promise<!print_preview.PrinterCapabilitiesResponse>} + * A map from destination IDs to the responses to be sent when + * |getPrinterCapabilities| is called for the ID. + */ + this.localDestinationCapabilities_ = new Map(); + + /** * @private {!print_preview.PrinterSetupResponse} The response to be sent * on a |setupPrinter| call. */ @@ -55,18 +64,6 @@ * @private {boolean} Whether the printer setup request should be rejected. */ this.shouldRejectPrinterSetup_ = false; - - /** - * @private {string} The destination id to watch for counting calls to - * |getLocalDestinationCapabilities|. - */ - this.destinationToWatch_ = ''; - - /** - * @private {number} The number of calls to - * |getLocalDestinationCapabilities| with id = |destinationToWatch_|. - */ - this.getLocalDestinationCapabilitiesCallCount_ = 0; } NativeLayerStub.prototype = { @@ -97,6 +94,12 @@ }, /** @override */ + getPrinterCapabilities: function(printerId) { + this.methodCalled('getPrinterCapabilities', printerId); + return this.localDestinationCapabilities_.get(printerId); + }, + + /** @override */ setupPrinter: function(printerId) { this.methodCalled('setupPrinter', printerId); return this.shouldRejectPrinterSetup_ ? @@ -106,10 +109,7 @@ /** Stubs for |print_preview.NativeLayer| methods that call C++ handlers. */ previewReadyForTest: function() {}, - startGetLocalDestinationCapabilities: function(destinationId) { - if (destinationId == this.destinationToWatch_) - this.getLocalDestinationCapabilitiesCallCount_++; - }, + startGetPreview: function(destination, printTicketStore, documentInfo, generateDraft, requestId) { this.generateDraft_ = generateDraft; @@ -125,15 +125,6 @@ this.eventTarget_ = eventTarget; }, - /** - * @return {boolean} Whether capabilities have been requested exactly once - * for |destinationToWatch_|. - */ - didGetCapabilitiesOnce: function(destinationId) { - return (destinationId == this.destinationToWatch_ && - this.getLocalDestinationCapabilitiesCallCount_ == 1); - }, - /** @return {boolean} Whether a new draft was requested for preview. */ generateDraft: function() { return this.generateDraft_; }, @@ -141,16 +132,6 @@ isPrintStarted: function() { return this.printStarted_; }, /** - * @param {string} destinationId The destination ID to watch for - * |getLocalDestinationCapabilities| calls. - * Resets |getLocalDestinationCapabilitiesCallCount_|. - */ - setDestinationToWatch: function(destinationId) { - this.destinationToWatch_ = destinationId; - this.getLocalDestinationCapabilitiesCallCount_ = 0; - }, - - /** * @param {!print_preview.NativeInitialSettings} settings The settings * to return as a response to |getInitialSettings|. */ @@ -167,6 +148,18 @@ }, /** + * @param {!print_preview.PrinterCapabilitiesResponse} response The + * response to send for the destination whose ID is in the response. + * @param {boolean?} opt_reject Whether to reject the callback for this + * destination. Defaults to false (will resolve callback) if not + * provided. + */ + setLocalDestinationCapabilities: function(response, opt_reject) { + this.localDestinationCapabilities_.set(response.printerId, + opt_reject ? Promise.reject() : Promise.resolve(response)); + }, + + /** * @param {boolean} reject Whether printSetup requests should be rejected. * @param {!print_preview.PrinterSetupResponse} The response to send when * |setupPrinter| is called.
diff --git a/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js b/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js index eb665ca..e5ea6e4 100644 --- a/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js +++ b/chrome/test/data/webui/print_preview/print_preview_destination_search_test.js
@@ -102,31 +102,6 @@ }); }; - function mockSetupCall(destId, nativeLayerMock) { - assert (!cr.isChromeOS); - nativeLayerMock.setDestinationToWatch(destId); - var resolver = new PromiseResolver(); - - resolver.promise.then( - function(result) { - // Simulate the native layer dispatching capabilities. - var capsSetEvent = - new Event(print_preview.NativeLayer.EventType.CAPABILITIES_SET); - capsSetEvent.settingsInfo = result; - destinationStore_.onLocalDestinationCapabilitiesSet_(capsSetEvent); - expectTrue(nativeLayerMock.didGetCapabilitiesOnce(destId)); - }.bind(this), - function() { - var failEvent = new Event( - print_preview.NativeLayer.EventType.GET_CAPABILITIES_FAIL); - failEvent.destinationId = destId; - destinationStore_.onGetCapabilitiesFail_(failEvent); - expectTrue(nativeLayerMock.didGetCapabilitiesOnce(destId)); - }.bind(this)); - - return resolver; - }; - function requestSetup(destId, destinationSearch) { var origin = cr.isChromeOS ? print_preview.DestinationOrigin.CROS : print_preview.DestinationOrigin.LOCAL; @@ -176,16 +151,17 @@ if (cr.isChromeOS) { nativeLayer_.setSetupPrinterResponse(true, { printerId: destId, success: false,}); - requestSetup(destId, destinationSearch_); - return nativeLayer_.whenCalled('setupPrinter').then( - function(actualDestId) { - assertEquals(destId, actualDestId); - }); } else { - var resolver = mockSetupCall(destId, nativeLayer_); - requestSetup(destId, destinationSearch_); - resolver.reject(destId); + nativeLayer_.setLocalDestinationCapabilities({printerId: destId, + capabilities: getCaps()}, + true); } + requestSetup(destId, destinationSearch_); + var callback = cr.isChromeOS ? 'setupPrinter' : 'getPrinterCapabilities'; + return nativeLayer_.whenCalled(callback).then( + function(actualDestId) { + assertEquals(destId, actualDestId); + }); }); test('ReceiveSuccessfulSetup', function() { @@ -197,32 +173,22 @@ }; if (cr.isChromeOS) nativeLayer_.setSetupPrinterResponse(false, response); + else + nativeLayer_.setLocalDestinationCapabilities({printerId: destId, + capabilities: getCaps()}); var waiter = waitForEvent( destinationStore_, print_preview.DestinationStore.EventType.DESTINATION_SELECT); - if (cr.isChromeOS) { - requestSetup(destId, destinationSearch_); - return Promise.all([ - nativeLayer_.whenCalled('setupPrinter'), waiter - ]).then(function(results) { - assertEquals(destId, results[0]); - - // after setup succeeds and event arrives, the destination should - // be selected. - assertNotEquals(null, destinationStore_.selectedDestination); - assertEquals(destId, destinationStore_.selectedDestination.id); - }); - } else { //!cr.isChromeOS - var resolver = mockSetupCall(destId, nativeLayer_); - requestSetup(destId, destinationSearch_); - resolver.resolve(response); - return waiter.then(function() { - // after setup succeeds, the destination should be selected. - assertNotEquals(null, destinationStore_.selectedDestination); - assertEquals(destId, destinationStore_.selectedDestination.id); - }); - } + requestSetup(destId, destinationSearch_); + var callback = cr.isChromeOS ? 'setupPrinter' : 'getPrinterCapabilities'; + return Promise.all([nativeLayer_.whenCalled(callback), waiter]).then( + function(results) { + assertEquals(destId, results[0]); + // after setup succeeds, the destination should be selected. + assertNotEquals(null, destinationStore_.selectedDestination); + assertEquals(destId, destinationStore_.selectedDestination.id); + }); }); if (cr.isChromeOS) {
diff --git a/chrome/test/data/webui/print_preview/print_preview_tests.js b/chrome/test/data/webui/print_preview/print_preview_tests.js index e70b7c3..33ddef3 100644 --- a/chrome/test/data/webui/print_preview/print_preview_tests.js +++ b/chrome/test/data/webui/print_preview/print_preview_tests.js
@@ -40,44 +40,39 @@ } /** - * Start loading the local destinations using the destination infos currently - * stored in |localDestinationInfos|. + * Sets settings and destinations and local destination that is the system + * default. + * @param {print_preview.PrinterCapabilitiesResponse=} opt_device The + * response to use for printer capabilities when the printer represented + * by |opt_device| is loaded. To avoid crashing when initialize() is + * called, |opt_device| should represent the printer that will be selected + * when print preview is first opened, i.e. the system default + * destination, or the most recently used destination or destination + * selected by the rules string if these parameters are defined in + * initialSettings.serializedAppStateStr_. + * If |opt_device| is not provided, a default device with ID 'FooDevice' + * will be used. + * @return {!Promise<print_preview.PrinterCapabilitiesResponse>} a + * promise that will resolve when getPrinterCapabilities has been + * called for the device (either default or provided). */ - function setLocalDestinations() { + function setupSettingsAndDestinationsWithCapabilities(opt_device) { + nativeLayer.setInitialSettings(initialSettings); nativeLayer.setLocalDestinations(localDestinationInfos); - printPreview.destinationStore_.startLoadLocalDestinations(); - } + opt_device = opt_device || getCddTemplate('FooDevice', 'FooName'); + nativeLayer.setLocalDestinationCapabilities(opt_device); - /** - * Initializes print preview with the initial settings currently stored in - * |initialSettings|, waits for the getInitialSettings promise to resolve, - * and loads local destinations using destination infos currently stored in - * |localDestinationInfos|. - * @return {!Promise<!Array<!print_preview.LocalDestinationInfo>>} a - * promise that will resolve when getPrinters has been resolved by - * the native layer stub. - */ - function setupSettingsAndDestinations() { - setInitialSettings(); + printPreview.initialize(); return nativeLayer.whenCalled('getInitialSettings').then(function() { - setLocalDestinations(); - return nativeLayer.whenCalled('getPrinters'); + printPreview.destinationStore_.startLoadLocalDestinations(); + return Promise.all([ + nativeLayer.whenCalled('getPrinters'), + nativeLayer.whenCalled('getPrinterCapabilities') + ]); }); } /** - * Dispatch the CAPABILITIES_SET event. This call is NOT async and will - * happen in the same thread. - * @param {!Object} device The device whose capabilities should be dispatched. - */ - function setCapabilities(device) { - var capsSetEvent = - new Event(print_preview.NativeLayer.EventType.CAPABILITIES_SET); - capsSetEvent.settingsInfo = device; - nativeLayer.getEventTarget().dispatchEvent(capsSetEvent); - } - - /** * Verify that |section| visibility matches |visible|. * @param {HTMLDivElement} section The section to check. * @param {boolean} visible The expected state of visibility. @@ -102,11 +97,13 @@ /** * @param {string} printerId - * @return {!Object} + * @param {string=} opt_printerName Defaults to an empty string. + * @return {!print_preview.PrinterCapabilitiesResponse} */ - function getCddTemplate(printerId) { + function getCddTemplate(printerId, opt_printerName) { return { printerId: printerId, + printerName: opt_printerName || '', capabilities: { version: '1.0', printer: { @@ -215,7 +212,6 @@ * and verifies it is displayed. */ function startAdvancedSettingsTest(device) { - setCapabilities(device); expandMoreSettings(); // Check that the advanced options settings section is visible. @@ -285,7 +281,7 @@ // Test some basic assumptions about the print preview WebUI. test('PrinterList', function() { - return setupSettingsAndDestinations().then(function() { + return setupSettingsAndDestinationsWithCapabilities().then(function() { var recentList = $('destination-search').querySelector('.recent-list ul'); var localList = @@ -315,7 +311,7 @@ // Test that the printer list is structured correctly after calling // addCloudPrinters with an empty list. test('PrinterListCloudEmpty', function() { - return setupSettingsAndDestinations().then(function() { + return setupSettingsAndDestinationsWithCapabilities().then(function() { var cloudPrintEnableEvent = new Event( print_preview.NativeLayer.EventType.CLOUD_PRINT_ENABLE); cloudPrintEnableEvent.baseCloudPrintUrl = 'cloudprint url'; @@ -381,7 +377,7 @@ }, ], }); - + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings'); }); @@ -397,7 +393,7 @@ origin: origin, account: '', capabilities: 0, - name: '', + name: 'One', extensionId: '', extensionName: '', }, { @@ -405,7 +401,7 @@ origin: origin, account: '', capabilities: 0, - name: '', + name: 'Two', extensionId: '', extensionName: '', }, { @@ -413,24 +409,28 @@ origin: origin, account: '', capabilities: 0, - name: '', + name: 'Three', extensionId: '', extensionName: '', }, ], }); + // Set all three of these destinations in the local destination infos + // (represents currently available printers), plus an extra destination. + localDestinationInfos = [ + { printerName: 'One', deviceName: 'ID1' }, + { printerName: 'Two', deviceName: 'ID2' }, + { printerName: 'Three', deviceName: 'ID3' }, + { printerName: 'Four', deviceName: 'ID4' } + ]; - setInitialSettings(); + // Set up capabilities for ID1. This should be the device that should hav + // its capabilities fetched, since it is the most recent. If another + // device is selected the native layer will reject the callback. + var device = getCddTemplate('ID1', 'One'); - return nativeLayer.whenCalled('getInitialSettings').then( + return setupSettingsAndDestinationsWithCapabilities(device).then( function() { - // Set capabilities for the three recently used destinations + 1 - // more. - setCapabilities(getCddTemplate('ID1')); - setCapabilities(getCddTemplate('ID2')); - setCapabilities(getCddTemplate('ID3')); - setCapabilities(getCddTemplate('ID4')); - // The most recently used destination should be the currently // selected one. This is ID1. assertEquals( @@ -461,22 +461,17 @@ // It also makes sure these rules do override system default destination. initialSettings.serializedDefaultDestinationSelectionRulesStr_ = JSON.stringify({namePattern: '.*Bar.*'}); - // Set this early as the app state selection string will trigger a load - // of local destinations on initialization. - nativeLayer.setLocalDestinations(localDestinationInfos); - setInitialSettings(); - return nativeLayer.whenCalled('getInitialSettings').then(function() { - return nativeLayer.whenCalled('getPrinters').then(function() { - assertEquals('BarDevice', - printPreview.destinationStore_.selectedDestination.id); - }); - }); + return setupSettingsAndDestinationsWithCapabilities( + getCddTemplate('BarDevice', 'BarName')).then(function() { + assertEquals('BarDevice', + printPreview.destinationStore_.selectedDestination.id); + }); }); test('SystemDialogLinkIsHiddenInAppKioskMode', function() { if (!cr.isChromeOS) initialSettings.isInAppKioskMode_ = true; - + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('FooDevice')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings').then( function() { @@ -491,62 +486,65 @@ checkSectionVisible($('layout-settings'), false); checkSectionVisible($('color-settings'), false); checkSectionVisible($('copies-settings'), false); + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + option: [{is_default: true, type: 'STANDARD_COLOR'}] + }; + delete device.capabilities.printer.copies; - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - option: [{is_default: true, type: 'STANDARD_COLOR'}] - }; - delete device.capabilities.printer.copies; - setCapabilities(device); + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { + checkSectionVisible($('layout-settings'), true); + checkSectionVisible($('color-settings'), false); + checkSectionVisible($('copies-settings'), false); - checkSectionVisible($('layout-settings'), true); - checkSectionVisible($('color-settings'), false); - checkSectionVisible($('copies-settings'), false); - - return whenAnimationDone('other-options-collapsible'); - }); + return whenAnimationDone('other-options-collapsible'); + }); }); // When the source is 'PDF' and 'Save as PDF' option is selected, we hide // the fit to page option. test('PrintToPDFSelectedCapabilities', function() { - // Add PDF printer. + // Setup initial settings initialSettings.isDocumentModifiable_ = false; initialSettings.systemDefaultDestinationId_ = 'Save as PDF'; - setInitialSettings(); - return nativeLayer.whenCalled('getInitialSettings').then(function() { - var device = { - printerId: 'Save as PDF', - capabilities: { - version: '1.0', - printer: { - page_orientation: { - option: [ - {type: 'AUTO', is_default: true}, - {type: 'PORTRAIT'}, - {type: 'LANDSCAPE'} - ] - }, - color: { - option: [ - {type: 'STANDARD_COLOR', is_default: true} - ] - }, - media_size: { - option: [ - { name: 'NA_LETTER', - width_microns: 0, - height_microns: 0, - is_default: true - } - ] - } + // Set PDF printer + var device = { + printerId: 'Save as PDF', + capabilities: { + version: '1.0', + printer: { + page_orientation: { + option: [ + {type: 'AUTO', is_default: true}, + {type: 'PORTRAIT'}, + {type: 'LANDSCAPE'} + ] + }, + color: { + option: [ + {type: 'STANDARD_COLOR', is_default: true} + ] + }, + media_size: { + option: [ + { name: 'NA_LETTER', + width_microns: 0, + height_microns: 0, + is_default: true + } + ] } } - }; - setCapabilities(device); + } + }; + nativeLayer.setLocalDestinationCapabilities(device); + + setInitialSettings(); + return nativeLayer.whenCalled('getInitialSettings').then(function() { + return nativeLayer.whenCalled('getPrinterCapabilities'); + }).then(function() { var otherOptions = $('other-options-settings'); // If rasterization is an option, other options should be visible. // If not, there should be no available other options. @@ -565,9 +563,7 @@ // When the source is 'HTML', we always hide the fit to page option and show // media size option. test('SourceIsHTMLCapabilities', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var fitToPage = otherOptions.querySelector('#fit-to-page-container'); var rasterize; @@ -601,9 +597,7 @@ // we show/hide the fit to page option and hide media size selection. test('SourceIsPDFCapabilities', function() { initialSettings.isDocumentModifiable_ = false; - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var scalingSettings = $('scaling-settings'); var fitToPageContainer = @@ -637,9 +631,7 @@ // we show/hide the fit to page option and hide media size selection. test('ScalingUnchecksFitToPage', function() { initialSettings.isDocumentModifiable_ = false; - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var scalingSettings = $('scaling-settings'); @@ -675,9 +667,7 @@ // the copies value if capability is supported by printer. test('CheckNumCopiesPrintPreset', function() { initialSettings.isDocumentModifiable_ = false; - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { // Indicate that the number of copies print preset is set for source // PDF. var printPresetOptions = { @@ -704,9 +694,7 @@ // duplex setting if capability is supported by printer. test('CheckDuplexPrintPreset', function() { initialSettings.isDocumentModifiable_ = false; - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { // Indicate that the duplex print preset is set to 'long edge' for // source PDF. var printPresetOptions = { @@ -731,9 +719,7 @@ // Make sure that custom margins controls are properly set up. test('CustomMarginsControlsCheck', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { printPreview.printTicketStore_.marginsType.updateValue( print_preview.ticket_items.MarginsTypeValue.CUSTOM); @@ -751,9 +737,7 @@ // Page layout has zero margins. Hide header and footer option. test('PageLayoutHasNoMarginsHideHeaderFooter', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var headerFooter = otherOptions.querySelector('#header-footer-container'); @@ -780,9 +764,7 @@ // Page layout has half-inch margins. Show header and footer option. test('PageLayoutHasMarginsShowHeaderFooter', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var headerFooter = otherOptions.querySelector('#header-footer-container'); @@ -810,9 +792,7 @@ // Page layout has zero top and bottom margins. Hide header and footer // option. test('ZeroTopAndBottomMarginsHideHeaderFooter', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var headerFooter = otherOptions.querySelector('#header-footer-container'); @@ -840,9 +820,7 @@ // Page layout has zero top and half-inch bottom margin. Show header and // footer option. test('ZeroTopAndNonZeroBottomMarginShowHeaderFooter', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); var headerFooter = otherOptions.querySelector('#header-footer-container'); @@ -869,18 +847,17 @@ // Check header footer availability with small (label) page size. test('SmallPaperSizeHeaderFooter', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.media_size = { - 'option': [ - {'name': 'SmallLabel', 'width_microns': 38100, - 'height_microns': 12700, 'is_default': false}, - {'name': 'BigLabel', 'width_microns': 50800, - 'height_microns': 76200, 'is_default': true} - ] - }; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.media_size = { + 'option': [ + {'name': 'SmallLabel', 'width_microns': 38100, + 'height_microns': 12700, 'is_default': false}, + {'name': 'BigLabel', 'width_microns': 50800, + 'height_microns': 76200, 'is_default': true} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { var otherOptions = $('other-options-settings'); var headerFooter = otherOptions.querySelector('#header-footer-container'); @@ -911,16 +888,16 @@ // Test that the color settings, one option, standard monochrome. test('ColorSettingsMonochrome', function() { - return setupSettingsAndDestinations().then(function() { - // Only one option, standard monochrome. - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'is_default': true, 'type': 'STANDARD_MONOCHROME'} - ] - }; - setCapabilities(device); + // Only one option, standard monochrome. + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'is_default': true, 'type': 'STANDARD_MONOCHROME'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), false); return whenAnimationDone('more-settings'); @@ -929,17 +906,17 @@ // Test that the color settings, one option, custom monochrome. test('ColorSettingsCustomMonochrome', function() { - return setupSettingsAndDestinations().then(function() { - // Only one option, standard monochrome. - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'is_default': true, 'type': 'CUSTOM_MONOCHROME', - 'vendor_id': '42'} - ] - }; - setCapabilities(device); + // Only one option, standard monochrome. + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'is_default': true, 'type': 'CUSTOM_MONOCHROME', + 'vendor_id': '42'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), false); return whenAnimationDone('more-settings'); @@ -948,15 +925,15 @@ // Test that the color settings, one option, standard color. test('ColorSettingsColor', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'is_default': true, 'type': 'STANDARD_COLOR'} - ] - }; - setCapabilities(device); + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'is_default': true, 'type': 'STANDARD_COLOR'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), false); return whenAnimationDone('more-settings'); @@ -965,15 +942,14 @@ // Test that the color settings, one option, custom color. test('ColorSettingsCustomColor', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '42'} - ] - }; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '42'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), false); return whenAnimationDone('more-settings'); @@ -983,16 +959,15 @@ // Test that the color settings, two options, both standard, defaults to // color. test('ColorSettingsBothStandardDefaultColor', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'type': 'STANDARD_MONOCHROME'}, - {'is_default': true, 'type': 'STANDARD_COLOR'} - ] - }; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'type': 'STANDARD_MONOCHROME'}, + {'is_default': true, 'type': 'STANDARD_COLOR'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), true); expectEquals( 'color', @@ -1006,16 +981,15 @@ // Test that the color settings, two options, both standard, defaults to // monochrome. test('ColorSettingsBothStandardDefaultMonochrome', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'is_default': true, 'type': 'STANDARD_MONOCHROME'}, - {'type': 'STANDARD_COLOR'} - ] - }; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'is_default': true, 'type': 'STANDARD_MONOCHROME'}, + {'type': 'STANDARD_COLOR'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), true); expectEquals( 'bw', @@ -1029,16 +1003,15 @@ // Test that the color settings, two options, both custom, defaults to // color. test('ColorSettingsBothCustomDefaultColor', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.color = { - 'option': [ - {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'}, - {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '43'} - ] - }; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.color = { + 'option': [ + {'type': 'CUSTOM_MONOCHROME', 'vendor_id': '42'}, + {'is_default': true, 'type': 'CUSTOM_COLOR', 'vendor_id': '43'} + ] + }; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { checkSectionVisible($('color-settings'), true); expectEquals( 'color', @@ -1052,9 +1025,7 @@ // Test to verify that duplex settings are set according to the printer // capabilities. test('DuplexSettingsTrue', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var otherOptions = $('other-options-settings'); checkSectionVisible(otherOptions, true); duplexContainer = otherOptions.querySelector('#duplex-container'); @@ -1068,11 +1039,10 @@ // Test to verify that duplex settings are set according to the printer // capabilities. test('DuplexSettingsFalse', function() { - return setupSettingsAndDestinations().then(function() { - var device = getCddTemplate('FooDevice'); - delete device.capabilities.printer.duplex; - setCapabilities(device); - + var device = getCddTemplate('FooDevice'); + delete device.capabilities.printer.duplex; + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { // Check that it is collapsed. var otherOptions = $('other-options-settings'); checkSectionVisible(otherOptions, false); @@ -1089,9 +1059,7 @@ // Test that changing the selected printer updates the preview. test('PrinterChangeUpdatesPreview', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { var previewGenerator = mock(print_preview.PreviewGenerator); previewArea.previewGenerator_ = previewGenerator.proxy(); @@ -1099,28 +1067,31 @@ // destination that will therefore dispatch ticket item change events. previewGenerator.expects(exactly(9)).requestPreview(); - var barDestination = - printPreview.destinationStore_.destinations().find( - function(d) { - return d.id == 'BarDevice'; - }); - - printPreview.destinationStore_.selectDestination(barDestination); - + // Setup capabilities for BarDevice. var device = getCddTemplate('BarDevice'); device.capabilities.printer.color = { 'option': [ {'is_default': true, 'type': 'STANDARD_MONOCHROME'} ] }; - setCapabilities(device); + nativeLayer.setLocalDestinationCapabilities(device); + // Select BarDevice + var barDestination = + printPreview.destinationStore_.destinations().find( + function(d) { + return d.id == 'BarDevice'; + }); + printPreview.destinationStore_.selectDestination(barDestination); + return nativeLayer.whenCalled('getPrinterCapabilities', 'BarDevice'); + }).then(function(){ return whenAnimationDone('more-settings'); }); }); // Test that error message is displayed when plugin doesn't exist. test('NoPDFPluginErrorMessage', function() { + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('FooDevice')); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings').then(function() { var previewAreaEl = $('preview-area'); @@ -1148,33 +1119,32 @@ // Test custom localized paper names. test('CustomPaperNames', function() { - return setupSettingsAndDestinations().then(function() { - var customLocalizedMediaName = 'Vendor defined localized media name'; - var customMediaName = 'Vendor defined media name'; + var customLocalizedMediaName = 'Vendor defined localized media name'; + var customMediaName = 'Vendor defined media name'; - var device = getCddTemplate('FooDevice'); - device.capabilities.printer.media_size = { - option: [ - { name: 'CUSTOM', - width_microns: 15900, - height_microns: 79400, - is_default: true, - custom_display_name_localized: [ - { locale: navigator.language, - value: customLocalizedMediaName - } - ] - }, - { name: 'CUSTOM', - width_microns: 15900, - height_microns: 79400, - custom_display_name: customMediaName - } - ] - }; + var device = getCddTemplate('FooDevice'); + device.capabilities.printer.media_size = { + option: [ + { name: 'CUSTOM', + width_microns: 15900, + height_microns: 79400, + is_default: true, + custom_display_name_localized: [ + { locale: navigator.language, + value: customLocalizedMediaName + } + ] + }, + { name: 'CUSTOM', + width_microns: 15900, + height_microns: 79400, + custom_display_name: customMediaName + } + ] + }; - setCapabilities(device); - + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { expandMoreSettings(); checkSectionVisible($('media-size-settings'), true); @@ -1197,7 +1167,8 @@ // search box). test('AdvancedSettings1Option', function() { var device = getCddTemplateWithAdvancedSettings('FooDevice'); - return setupSettingsAndDestinations().then(function() { + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { startAdvancedSettingsTest(device); checkElementDisplayed($('advanced-settings'). querySelector('.search-box-area'), false); @@ -1224,7 +1195,8 @@ ] } }); - return setupSettingsAndDestinations().then(function() { + return setupSettingsAndDestinationsWithCapabilities(device) + .then(function() { startAdvancedSettingsTest(device); checkElementDisplayed($('advanced-settings'). @@ -1249,9 +1221,11 @@ }; }), }); - setCapabilities(getCddTemplate('ID1')); - setCapabilities(getCddTemplate('ID2')); - setCapabilities(getCddTemplate('ID3')); + + // Ensure all capabilities are available for fetch. + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID1')); + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID2')) + nativeLayer.setLocalDestinationCapabilities(getCddTemplate('ID3')); // Use a real preview generator. previewArea.previewGenerator_ = @@ -1266,6 +1240,8 @@ expectEquals(-1, previewArea.previewGenerator_.inFlightRequestId_); setInitialSettings(); return nativeLayer.whenCalled('getInitialSettings').then(function() { + return nativeLayer.whenCalled('getPrinterCapabilities', 'ID1'); + }).then(function() { expectEquals(0, previewArea.previewGenerator_.inFlightRequestId_); }); }); @@ -1274,9 +1250,7 @@ // an error and that the preview dialog can be recovered by selecting a // new destination. test('InvalidSettingsError', function() { - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { // Manually enable the print header. This is needed since there is no // plugin during test, so it will be set as disabled normally. printPreview.printHeader_.isEnabled = true; @@ -1319,21 +1293,24 @@ return d.id == 'BarDevice'; }); + nativeLayer.setLocalDestinationCapabilities( + getCddTemplate('BarDevice')); printPreview.destinationStore_.selectDestination(barDestination); - // Dispatch events indicating capabilities were fetched and new - // preview has loaded. - setCapabilities(getCddTemplate('BarDevice')); - var previewDoneEvent = new Event( - print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE); - previewArea.dispatchEvent(previewDoneEvent); + return nativeLayer.whenCalled('getPrinterCapabilities', 'BarDevice') + .then(function() { + // Dispatch event indicating new preview has loaded. + var previewDoneEvent = new Event( + print_preview.PreviewArea.EventType.PREVIEW_GENERATION_DONE); + previewArea.dispatchEvent(previewDoneEvent); - // Has active print button and successfully 'prints', indicating - // recovery from error state. - expectFalse(printButton.disabled); - expectFalse(nativeLayer.isPrintStarted()); - printButton.click(); - expectTrue(nativeLayer.isPrintStarted()); + // Has active print button and successfully 'prints', indicating + // recovery from error state. + expectFalse(printButton.disabled); + expectFalse(nativeLayer.isPrintStarted()); + printButton.click(); + expectTrue(nativeLayer.isPrintStarted()); + }); }); }); @@ -1345,9 +1322,7 @@ new print_preview.PreviewGenerator(printPreview.destinationStore_, printPreview.printTicketStore_, nativeLayer, printPreview.documentInfo_); - return setupSettingsAndDestinations().then(function() { - setCapabilities(getCddTemplate('FooDevice')); - + return setupSettingsAndDestinationsWithCapabilities().then(function() { // The first request should generate draft because there was no // previous print preview draft. expectTrue(nativeLayer.generateDraft());
diff --git a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js index 9f4b7e3..fac6e14 100644 --- a/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js +++ b/chrome/test/data/webui/settings/cr_settings_interactive_ui_tests.js
@@ -67,6 +67,30 @@ /** + * Test fixture for Sync Page. + * @constructor + * @extends {CrSettingsInteractiveUITest} + */ +function CrSettingsSyncPageTest() {} + +CrSettingsSyncPageTest.prototype = { + __proto__: CrSettingsInteractiveUITest.prototype, + + /** @override */ + browsePreload: 'chrome://md-settings/people_page/sync_page.html', + + /** @override */ + extraLibraries: CrSettingsInteractiveUITest.prototype.extraLibraries.concat([ + 'people_page_sync_page_interactive_test.js', + ]), +}; + +TEST_F('CrSettingsSyncPageTest', 'All', function() { + mocha.run(); +}); + + +/** * @constructor * @extends {CrSettingsInteractiveUITest} */
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js b/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js new file mode 100644 index 0000000..d2c42083 --- /dev/null +++ b/chrome/test/data/webui/settings/people_page_sync_page_interactive_test.js
@@ -0,0 +1,31 @@ +// 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. + +suite('sync-page-test', function() { + /** @type {SyncPageElement} */ var testElement; + + setup(function() { + PolymerTest.clearBody(); + + testElement = document.createElement('settings-sync-page'); + document.body.appendChild(testElement); + }); + + test('autofocus correctly after container is shown', function() { + cr.webUIListenerCallback('sync-prefs-changed', {passphraseRequired: true}); + Polymer.dom.flush(); + + var input = testElement.$$('#existingPassphraseInput'); + + var focused = false; + input.addEventListener('focus', function() { + focused = true; + }); + + // Simulate event normally fired by main_page_behavior after subpage + // animation ends. + testElement.fire('show-container'); + assertTrue(focused); + }); +});
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index e921e08..5912703 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -9641.0.0 \ No newline at end of file +9649.0.0 \ No newline at end of file
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider.cc b/chromeos/dbus/services/proxy_resolution_service_provider.cc index a5f6a78..54807c3 100644 --- a/chromeos/dbus/services/proxy_resolution_service_provider.cc +++ b/chromeos/dbus/services/proxy_resolution_service_provider.cc
@@ -26,7 +26,6 @@ struct ProxyResolutionServiceProvider::Request { public: - // Constructor for returning proxy info via an asynchronous D-Bus response. Request(const std::string& source_url, std::unique_ptr<dbus::Response> response, const dbus::ExportedObject::ResponseSender& response_sender, @@ -38,38 +37,15 @@ DCHECK(this->response); DCHECK(!response_sender.is_null()); } - - // Constructor for returning proxy info via a D-Bus signal. - Request(const std::string& source_url, - const std::string& signal_interface, - const std::string& signal_name, - scoped_refptr<net::URLRequestContextGetter> context_getter) - : source_url(source_url), - signal_interface(signal_interface), - signal_name(signal_name), - context_getter(context_getter) { - DCHECK(!signal_interface.empty()); - DCHECK(!signal_name.empty()); - } - ~Request() = default; // URL being resolved. const std::string source_url; // D-Bus response and callback for returning data on resolution completion. - // Either these two members or |signal_interface|/|signal_name| must be - // supplied, but not both. std::unique_ptr<dbus::Response> response; const dbus::ExportedObject::ResponseSender response_sender; - // D-Bus interface and name for emitting result signal after resolution is - // complete. - // TODO(derat): Remove these and associated code after all callers use async - // responses instead of signals: http://crbug.com/446115 - const std::string signal_interface; - const std::string signal_name; - // Used to get the network context associated with the profile used to run // this request. const scoped_refptr<net::URLRequestContextGetter> context_getter; @@ -85,12 +61,8 @@ }; ProxyResolutionServiceProvider::ProxyResolutionServiceProvider( - const std::string& dbus_interface, - const std::string& dbus_method_name, std::unique_ptr<Delegate> delegate) - : dbus_interface_(dbus_interface), - dbus_method_name_(dbus_method_name), - delegate_(std::move(delegate)), + : delegate_(std::move(delegate)), origin_thread_(base::ThreadTaskRunnerHandle::Get()), weak_ptr_factory_(this) {} @@ -104,7 +76,7 @@ exported_object_ = exported_object; VLOG(1) << "ProxyResolutionServiceProvider started"; exported_object_->ExportMethod( - dbus_interface_, dbus_method_name_, + kNetworkProxyServiceInterface, kNetworkProxyServiceResolveProxyMethod, base::Bind(&ProxyResolutionServiceProvider::ResolveProxy, weak_ptr_factory_.GetWeakPtr()), base::Bind(&ProxyResolutionServiceProvider::OnExported, @@ -140,33 +112,13 @@ return; } - // The signal interface and name arguments are optional but must be supplied - // together. - std::string signal_interface, signal_name; - if (reader.HasMoreData() && - (!reader.PopString(&signal_interface) || signal_interface.empty() || - !reader.PopString(&signal_name) || signal_name.empty())) { - LOG(ERROR) << "Method call has invalid interface/name args: " - << method_call->ToString(); - response_sender.Run(dbus::ErrorResponse::FromMethodCall( - method_call, DBUS_ERROR_INVALID_ARGS, "Invalid interface/name args")); - return; - } - std::unique_ptr<dbus::Response> response = dbus::Response::FromMethodCall(method_call); scoped_refptr<net::URLRequestContextGetter> context_getter = delegate_->GetRequestContext(); - // If signal information was supplied, emit a signal instead of including - // proxy information in the response. - std::unique_ptr<Request> request = - !signal_interface.empty() - ? base::MakeUnique<Request>(source_url, signal_interface, signal_name, - context_getter) - : base::MakeUnique<Request>(source_url, std::move(response), - response_sender, context_getter); - + std::unique_ptr<Request> request = base::MakeUnique<Request>( + source_url, std::move(response), response_sender, context_getter); NotifyCallback notify_callback = base::Bind(&ProxyResolutionServiceProvider::NotifyProxyResolved, weak_ptr_factory_.GetWeakPtr()); @@ -180,11 +132,6 @@ base::Bind(&ProxyResolutionServiceProvider::ResolveProxyOnNetworkThread, base::Passed(std::move(request)), origin_thread_, notify_callback)); - - // If we didn't already pass the response to the Request object because we're - // returning data via a signal, send an empty response immediately. - if (response) - response_sender.Run(std::move(response)); } // static @@ -240,22 +187,11 @@ std::unique_ptr<Request> request) { DCHECK(OnOriginThread()); - if (request->response) { - // Reply to the original D-Bus method call. - dbus::MessageWriter writer(request->response.get()); - writer.AppendString(request->proxy_info.ToPacString()); - writer.AppendString(request->error); - request->response_sender.Run(std::move(request->response)); - } else { - // Send a signal to the client. - dbus::Signal signal(request->signal_interface, request->signal_name); - dbus::MessageWriter writer(&signal); - writer.AppendString(request->source_url); - writer.AppendString(request->proxy_info.ToPacString()); - writer.AppendString(request->error); - exported_object_->SendSignal(&signal); - VLOG(1) << "Sending signal: " << signal.ToString(); - } + // Reply to the original D-Bus method call. + dbus::MessageWriter writer(request->response.get()); + writer.AppendString(request->proxy_info.ToPacString()); + writer.AppendString(request->error); + request->response_sender.Run(std::move(request->response)); } } // namespace chromeos
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider.h b/chromeos/dbus/services/proxy_resolution_service_provider.h index 9c750d77..0e3ebdc 100644 --- a/chromeos/dbus/services/proxy_resolution_service_provider.h +++ b/chromeos/dbus/services/proxy_resolution_service_provider.h
@@ -30,30 +30,18 @@ namespace chromeos { -// This class provides proxy resolution service for CrosDBusService. -// It processes proxy resolution requests for ChromeOS clients. +// This class processes proxy resolution requests for Chrome OS clients. // // The following method is exported: // -// Interface: org.chromium.LibCrosServiceInterface (kLibCrosServiceInterface) -// Method: ResolveNetworkProxy (kResolveNetworkProxy) +// Interface: org.chromium.NetworkProxyServiceInterface +// (kNetworkProxyServiceInterface) +// Method: ResolveProxy (kNetworkProxyServiceResolveProxyMethod) // Parameters: string:source_url -// string:signal_interface (optional) -// string:signal_name (optional) // -// Resolves the proxy for |source_url|. If |signal_interface| and -// |signal_name| are supplied, returns an empty reply immediately and -// asynchronously emits a D-Bus signal to the requested destination. -// Otherwise, returns proxy information an asynchronous response without -// emitting a signal. +// Resolves the proxy for |source_url| and returns proxy information via an +// asynchronous response containing two values: // -// The signal (if requested) will contain three values: -// - string:source_url - requested source URL. -// - string:proxy_info - proxy info for the source URL in PAC format -// like "PROXY cache.example.com:12345" -// - string:error_message - error message. Empty if successful. -// -// The method call response (if requested) will contain just two values: // - string:proxy_info - proxy info for the source URL in PAC format // like "PROXY cache.example.com:12345" // - string:error_message - error message. Empty if successful. @@ -61,9 +49,9 @@ // This service can be manually tested using dbus-send: // // % dbus-send --system --type=method_call --print-reply -// --dest=org.chromium.LibCrosService -// /org/chromium/LibCrosService -// org.chromium.LibCrosServiceInterface.ResolveNetworkProxy +// --dest=org.chromium.NetworkProxyService +// /org/chromium/NetworkProxyService +// org.chromium.NetworkProxyServiceInterface.ResolveProxy // string:https://www.google.com/ // class CHROMEOS_EXPORT ProxyResolutionServiceProvider @@ -80,9 +68,7 @@ virtual scoped_refptr<net::URLRequestContextGetter> GetRequestContext() = 0; }; - ProxyResolutionServiceProvider(const std::string& dbus_interface, - const std::string& dbus_method_name, - std::unique_ptr<Delegate> delegate); + explicit ProxyResolutionServiceProvider(std::unique_ptr<Delegate> delegate); ~ProxyResolutionServiceProvider() override; // CrosDBusService::ServiceProviderInterface: @@ -131,8 +117,6 @@ // information to the client over D-Bus. void NotifyProxyResolved(std::unique_ptr<Request> request); - const std::string dbus_interface_; - const std::string dbus_method_name_; std::unique_ptr<Delegate> delegate_; scoped_refptr<dbus::ExportedObject> exported_object_; scoped_refptr<base::SingleThreadTaskRunner> origin_thread_;
diff --git a/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc b/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc index fbb4345..b14be97e 100644 --- a/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc +++ b/chromeos/dbus/services/proxy_resolution_service_provider_unittest.cc
@@ -31,14 +31,6 @@ namespace { -// ProxyResolutionServiceProvider will return the proxy info as a D-Bus -// signal, to the following signal interface and the signal name. -const char kReturnSignalInterface[] = "org.chromium.TestInterface"; -const char kReturnSignalName[] = "TestSignal"; - -// Maximum time to wait for D-Bus signals to be received, in seconds. -int kSignalTimeoutSec = 60; - // Runs pending, non-delayed tasks on |task_runner|. Note that delayed tasks or // additional tasks posted by pending tests will not be run. void RunPendingTasks(scoped_refptr<base::SingleThreadTaskRunner> task_runner) { @@ -196,7 +188,6 @@ proxy_resolver_ = base::MakeUnique<TestProxyResolver>(network_thread_.task_runner()); service_provider_ = base::MakeUnique<ProxyResolutionServiceProvider>( - kNetworkProxyServiceInterface, kNetworkProxyServiceResolveProxyMethod, base::MakeUnique<TestDelegate>(network_thread_.task_runner(), proxy_resolver_.get())); test_helper_.SetUp( @@ -217,94 +208,19 @@ } protected: - // Arguments extracted from a D-Bus signal. - struct SignalInfo { - std::string source_url; - std::string proxy_info; - std::string error_message; - }; - - // Called when a signal is received. - void OnSignalReceived(dbus::Signal* signal) { - EXPECT_EQ(kReturnSignalInterface, signal->GetInterface()); - EXPECT_EQ(kReturnSignalName, signal->GetMember()); - - ASSERT_FALSE(signal_); - signal_ = base::MakeUnique<SignalInfo>(); - - // The signal should contain three strings. - dbus::MessageReader reader(signal); - EXPECT_TRUE(reader.PopString(&signal_->source_url)); - EXPECT_TRUE(reader.PopString(&signal_->proxy_info)); - EXPECT_TRUE(reader.PopString(&signal_->error_message)); - - // Stop the message loop. - ASSERT_FALSE(quit_closure_.is_null()) << "Unexpected D-Bus signal"; - quit_closure_.Run(); - quit_closure_.Reset(); - } - - // Called when connected to a signal. - void OnConnectedToSignal(const std::string& signal_interface, - const std::string& signal_name, - bool success){ - EXPECT_EQ(kReturnSignalInterface, signal_interface); - EXPECT_EQ(kReturnSignalName, signal_name); - EXPECT_TRUE(success); - } - - // Makes a D-Bus call to |service_provider_|'s ResolveProxy method. If - // |request_signal| is true, requests that the proxy information be returned - // via a signal; otherwise it should be included in the response. - // |response_out| is updated to hold the response, and |signal_out| is updated - // to hold information about the emitted signal, if any. - void CallMethod(const std::string& source_url, - bool request_signal, - std::unique_ptr<dbus::Response>* response_out, - std::unique_ptr<SignalInfo>* signal_out) { + // Makes a D-Bus call to |service_provider_|'s ResolveProxy method and returns + // the response. + std::unique_ptr<dbus::Response> CallMethod(const std::string& source_url) { dbus::MethodCall method_call(kNetworkProxyServiceInterface, kNetworkProxyServiceResolveProxyMethod); dbus::MessageWriter writer(&method_call); writer.AppendString(source_url); - if (request_signal) { - writer.AppendString(kReturnSignalInterface); - writer.AppendString(kReturnSignalName); - - // Connect to the signal that will be sent to kReturnSignalInterface and - // kReturnSignalName. - test_helper_.SetUpReturnSignal( - kReturnSignalInterface, kReturnSignalName, - base::Bind(&ProxyResolutionServiceProviderTest::OnSignalReceived, - base::Unretained(this)), - base::Bind(&ProxyResolutionServiceProviderTest::OnConnectedToSignal, - base::Unretained(this))); - } - - *response_out = test_helper_.CallMethod(&method_call); - - // If a signal is being emitted, run the main message loop until it's - // received or we get tired of waiting. - if (request_signal) { - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, quit_closure_, - base::TimeDelta::FromSeconds(kSignalTimeoutSec)); - run_loop.Run(); - } - - *signal_out = std::move(signal_); + return test_helper_.CallMethod(&method_call); } // Thread used to perform network operations. base::Thread network_thread_; - // Information about the last D-Bus signal received by OnSignalReceived(). - std::unique_ptr<SignalInfo> signal_; - - // Closure used to stop the message loop after receiving a D-Bus signal. - base::Closure quit_closure_; - std::unique_ptr<TestProxyResolver> proxy_resolver_; std::unique_ptr<ProxyResolutionServiceProvider> service_provider_; ServiceProviderTestHelper test_helper_; @@ -312,52 +228,9 @@ DISALLOW_COPY_AND_ASSIGN(ProxyResolutionServiceProviderTest); }; -// Tests that synchronously-resolved proxy information is returned via a signal. -TEST_F(ProxyResolutionServiceProviderTest, SignalSync) { +TEST_F(ProxyResolutionServiceProviderTest, Sync) { const char kSourceURL[] = "http://www.gmail.com/"; - - std::unique_ptr<dbus::Response> response; - std::unique_ptr<SignalInfo> signal; - CallMethod(kSourceURL, true /* request_signal */, &response, &signal); - - // An empty response should be returned. - ASSERT_TRUE(response); - EXPECT_FALSE(dbus::MessageReader(response.get()).HasMoreData()); - - // Confirm that the signal is received successfully. - ASSERT_TRUE(signal); - EXPECT_EQ(kSourceURL, signal->source_url); - EXPECT_EQ(proxy_resolver_->proxy_info().ToPacString(), signal->proxy_info); - EXPECT_EQ("", signal->error_message); -} - -// Tests that asynchronously-resolved proxy information is returned via a -// signal. -TEST_F(ProxyResolutionServiceProviderTest, SignalAsync) { - const char kSourceURL[] = "http://www.gmail.com/"; - proxy_resolver_->set_async(true); - proxy_resolver_->mutable_proxy_info()->UseNamedProxy("http://localhost:8080"); - - std::unique_ptr<dbus::Response> response; - std::unique_ptr<SignalInfo> signal; - CallMethod(kSourceURL, true /* request_signal */, &response, &signal); - - // An empty response should be returned. - ASSERT_TRUE(response); - EXPECT_FALSE(dbus::MessageReader(response.get()).HasMoreData()); - - // Confirm that the signal is received successfully. - ASSERT_TRUE(signal); - EXPECT_EQ(kSourceURL, signal->source_url); - EXPECT_EQ(proxy_resolver_->proxy_info().ToPacString(), signal->proxy_info); - EXPECT_EQ("", signal->error_message); -} - -TEST_F(ProxyResolutionServiceProviderTest, ResponseSync) { - const char kSourceURL[] = "http://www.gmail.com/"; - std::unique_ptr<dbus::Response> response; - std::unique_ptr<SignalInfo> signal; - CallMethod(kSourceURL, false /* request_signal */, &response, &signal); + std::unique_ptr<dbus::Response> response = CallMethod(kSourceURL); // The response should contain the proxy info and an empty error. ASSERT_TRUE(response); @@ -367,18 +240,13 @@ EXPECT_TRUE(reader.PopString(&error)); EXPECT_EQ(proxy_resolver_->proxy_info().ToPacString(), proxy_info); EXPECT_EQ("", error); - - // No signal should've been emitted. - EXPECT_FALSE(signal); } -TEST_F(ProxyResolutionServiceProviderTest, ResponseAsync) { +TEST_F(ProxyResolutionServiceProviderTest, Async) { const char kSourceURL[] = "http://www.gmail.com/"; proxy_resolver_->set_async(true); proxy_resolver_->mutable_proxy_info()->UseNamedProxy("http://localhost:8080"); - std::unique_ptr<dbus::Response> response; - std::unique_ptr<SignalInfo> signal; - CallMethod(kSourceURL, false /* request_signal */, &response, &signal); + std::unique_ptr<dbus::Response> response = CallMethod(kSourceURL); // The response should contain the proxy info and an empty error. ASSERT_TRUE(response); @@ -388,17 +256,12 @@ EXPECT_TRUE(reader.PopString(&error)); EXPECT_EQ(proxy_resolver_->proxy_info().ToPacString(), proxy_info); EXPECT_EQ("", error); - - // No signal should've been emitted. - EXPECT_FALSE(signal); } -TEST_F(ProxyResolutionServiceProviderTest, ResponseError) { +TEST_F(ProxyResolutionServiceProviderTest, Error) { const char kSourceURL[] = "http://www.gmail.com/"; proxy_resolver_->set_result(net::ERR_FAILED); - std::unique_ptr<dbus::Response> response; - std::unique_ptr<SignalInfo> signal; - CallMethod(kSourceURL, false /* request_signal */, &response, &signal); + std::unique_ptr<dbus::Response> response = CallMethod(kSourceURL); // The response should contain empty proxy info and a "mandatory proxy config // failed" error (which the error from the resolver will be mapped to). @@ -410,9 +273,6 @@ EXPECT_EQ("DIRECT", proxy_info); EXPECT_EQ(net::ErrorToString(net::ERR_MANDATORY_PROXY_CONFIGURATION_FAILED), error); - - // No signal should've been emitted. - EXPECT_FALSE(signal); } } // namespace chromeos
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index d74d535..82d560c 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -788,7 +788,7 @@ bool ProfileSyncService::IsSyncConfirmationNeeded() const { DCHECK(thread_checker_.CalledOnValidThread()); - return !IsFirstSetupInProgress() && !IsFirstSetupComplete() && + return IsSignedIn() && !IsFirstSetupInProgress() && !IsFirstSetupComplete() && IsSyncRequested(); }
diff --git a/components/browser_sync/profile_sync_service.h b/components/browser_sync/profile_sync_service.h index ddc7d6b0..a47fe59 100644 --- a/components/browser_sync/profile_sync_service.h +++ b/components/browser_sync/profile_sync_service.h
@@ -437,7 +437,7 @@ // Whether sync is currently blocked from starting because the sync // confirmation dialog hasn't been confirmed. - bool IsSyncConfirmationNeeded() const; + virtual bool IsSyncConfirmationNeeded() const; // Returns whether sync is managed, i.e. controlled by configuration // management. If so, the user is not allowed to configure sync.
diff --git a/components/browser_watcher/stability_debugging.cc b/components/browser_watcher/stability_debugging.cc index 3c8cc649..aee484c8 100644 --- a/components/browser_watcher/stability_debugging.cc +++ b/components/browser_watcher/stability_debugging.cc
@@ -4,10 +4,48 @@ #include "components/browser_watcher/stability_debugging.h" +#include <windows.h> + +#include <memory> + #include "base/debug/activity_tracker.h" +#include "build/build_config.h" namespace browser_watcher { +namespace { + +struct VehUnregisterer { + void operator()(void* handle) const { + ::RemoveVectoredExceptionHandler(handle); + } +}; + +using VehHandle = std::unique_ptr<void, VehUnregisterer>; + +uintptr_t GetProgramCounter(const CONTEXT& context) { +#if defined(ARCH_CPU_X86) + return context.Eip; +#elif defined(ARCH_CPU_X86_64) + return context.Rip; +#endif +} + +LONG CALLBACK VectoredExceptionHandler(EXCEPTION_POINTERS* exception_pointers) { + base::debug::GlobalActivityTracker* tracker = + base::debug::GlobalActivityTracker::Get(); + if (tracker) { + EXCEPTION_RECORD* record = exception_pointers->ExceptionRecord; + uintptr_t pc = GetProgramCounter(*exception_pointers->ContextRecord); + tracker->RecordException(reinterpret_cast<void*>(pc), + record->ExceptionAddress, record->ExceptionCode); + } + + return EXCEPTION_CONTINUE_SEARCH; // Continue to the next handler. +} + +} // namespace + void SetStabilityDataBool(base::StringPiece name, bool value) { base::debug::GlobalActivityTracker* global_tracker = base::debug::GlobalActivityTracker::Get(); @@ -26,4 +64,16 @@ global_tracker->process_data().SetInt(name, value); } +void RegisterStabilityVEH() { + // Register a vectored exception handler and request it be first. Note that + // subsequent registrations may also request to be first, in which case this + // one will be bumped. + // TODO(manzagop): Depending on observations, it may be necessary to + // consider refreshing the registration, either periodically or at opportune + // (e.g. risky) times. + static VehHandle veh_handler( + ::AddVectoredExceptionHandler(1, &VectoredExceptionHandler)); + DCHECK(veh_handler); +} + } // namespace browser_watcher
diff --git a/components/browser_watcher/stability_debugging.h b/components/browser_watcher/stability_debugging.h index cc23f69f..145979d 100644 --- a/components/browser_watcher/stability_debugging.h +++ b/components/browser_watcher/stability_debugging.h
@@ -15,6 +15,10 @@ void SetStabilityDataBool(base::StringPiece name, bool value); void SetStabilityDataInt(base::StringPiece name, int64_t value); +// Registers a vectored exception handler that stores exception details to the +// stability file. +void RegisterStabilityVEH(); + } // namespace browser_watcher #endif // COMPONENTS_BROWSER_WATCHER_STABILITY_DEBUGGING_H_
diff --git a/components/browser_watcher/stability_debugging_win_unittest.cc b/components/browser_watcher/stability_debugging_win_unittest.cc index 785ab22be..d4bd107 100644 --- a/components/browser_watcher/stability_debugging_win_unittest.cc +++ b/components/browser_watcher/stability_debugging_win_unittest.cc
@@ -4,84 +4,88 @@ #include "components/browser_watcher/stability_debugging.h" -#include "base/files/file_enumerator.h" +#include <windows.h> + +#include "base/command_line.h" +#include "base/debug/activity_tracker.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/process/process.h" #include "base/test/multiprocess_test.h" -#include "components/browser_watcher/stability_paths.h" +#include "base/test/test_timeouts.h" +#include "components/browser_watcher/stability_report.pb.h" +#include "components/browser_watcher/stability_report_extractor.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/multiprocess_func_list.h" namespace browser_watcher { -class StabilityDebuggingWinMultiProcTest : public base::MultiProcessTest {}; +using base::debug::GlobalActivityTracker; -MULTIPROCESS_TEST_MAIN(DummyProcess) { - return 0; -} +const int kMemorySize = 1 << 20; // 1MiB +const uint32_t exception_code = 42U; +const uint32_t exception_flag_continuable = 0U; -TEST_F(StabilityDebuggingWinMultiProcTest, GetStabilityFileForProcessTest) { - const base::FilePath empty_path; - - // Get the path for the current process. - base::FilePath stability_path; - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, - &stability_path)); - - // Ensure requesting a second time produces the same. - base::FilePath stability_path_two; - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, - &stability_path_two)); - EXPECT_EQ(stability_path, stability_path_two); - - // Ensure a different process has a different stability path. - base::SpawnChildResult spawn_result = SpawnChild("DummyProcess"); - base::FilePath stability_path_other; - ASSERT_TRUE(GetStabilityFileForProcess(spawn_result.process, empty_path, - &stability_path_other)); - EXPECT_NE(stability_path, stability_path_other); -} - -TEST(StabilityDebuggingWinTest, - GetStabilityFilePatternMatchesGetStabilityFileForProcessResult) { - // GetStabilityFileForProcess file names must match GetStabilityFilePattern - // according to - // FileEnumerator's algorithm. We test this by writing out some files and - // validating what is matched. - - base::ScopedTempDir temp_dir; - ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath user_data_dir = temp_dir.GetPath(); - - // Create the stability directory. - base::FilePath stability_dir = GetStabilityDir(user_data_dir); - ASSERT_TRUE(base::CreateDirectory(stability_dir)); - - // Write a stability file. - base::FilePath stability_file; - ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), - user_data_dir, &stability_file)); - { - base::ScopedFILE file(base::OpenFile(stability_file, "w")); - ASSERT_TRUE(file.get()); +class StabilityDebuggingTest : public testing::Test { + public: + StabilityDebuggingTest() {} + ~StabilityDebuggingTest() override { + GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get(); + if (global_tracker) { + global_tracker->ReleaseTrackerForCurrentThreadForTesting(); + delete global_tracker; + } } - // Write a file that shouldn't match. - base::FilePath non_matching_file = - stability_dir.AppendASCII("non_matching.foo"); - { - base::ScopedFILE file(base::OpenFile(non_matching_file, "w")); - ASSERT_TRUE(file.get()); + void SetUp() override { + testing::Test::SetUp(); + + ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); + debug_path_ = temp_dir_.GetPath().AppendASCII("debug.pma"); + + GlobalActivityTracker::CreateWithFile(debug_path_, kMemorySize, 0ULL, "", + 3); } - // Validate only the stability file matches. - base::FileEnumerator enumerator(stability_dir, false /* recursive */, - base::FileEnumerator::FILES, - GetStabilityFilePattern()); - ASSERT_EQ(stability_file, enumerator.Next()); - ASSERT_TRUE(enumerator.Next().empty()); + const base::FilePath& debug_path() { return debug_path_; } + + private: + base::ScopedTempDir temp_dir_; + base::FilePath debug_path_; +}; + +TEST_F(StabilityDebuggingTest, CrashingTest) { + RegisterStabilityVEH(); + + // Raise an exception, then continue. + __try { + ::RaiseException(exception_code, exception_flag_continuable, 0U, nullptr); + } __except (EXCEPTION_CONTINUE_EXECUTION) { + } + + // Collect the report. + StabilityReport report; + ASSERT_EQ(SUCCESS, Extract(debug_path(), &report)); + + // Validate expectations. + ASSERT_EQ(1, report.process_states_size()); + const ProcessState& process_state = report.process_states(0); + ASSERT_EQ(1, process_state.threads_size()); + + bool thread_found = false; + for (const ThreadState& thread : process_state.threads()) { + if (thread.thread_id() == ::GetCurrentThreadId()) { + thread_found = true; + ASSERT_TRUE(thread.has_exception()); + const Exception& exception = thread.exception(); + EXPECT_EQ(exception_code, exception.code()); + EXPECT_NE(0ULL, exception.program_counter()); + EXPECT_NE(0ULL, exception.exception_address()); + EXPECT_NE(0LL, exception.time()); + } + } + ASSERT_TRUE(thread_found); } } // namespace browser_watcher
diff --git a/components/browser_watcher/stability_paths_unittest.cc b/components/browser_watcher/stability_paths_unittest.cc index 4b9eea0..7a8f6ce 100644 --- a/components/browser_watcher/stability_paths_unittest.cc +++ b/components/browser_watcher/stability_paths_unittest.cc
@@ -4,14 +4,87 @@ #include "components/browser_watcher/stability_paths.h" +#include "base/files/file_enumerator.h" +#include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" +#include "base/process/process.h" +#include "base/test/multiprocess_test.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/multiprocess_func_list.h" namespace browser_watcher { +class StabilityPathsMultiProcTest : public base::MultiProcessTest {}; + +MULTIPROCESS_TEST_MAIN(DummyProcess) { + return 0; +} + +TEST_F(StabilityPathsMultiProcTest, GetStabilityFileForProcessTest) { + const base::FilePath empty_path; + + // Get the path for the current process. + base::FilePath stability_path; + ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, + &stability_path)); + + // Ensure requesting a second time produces the same. + base::FilePath stability_path_two; + ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), empty_path, + &stability_path_two)); + EXPECT_EQ(stability_path, stability_path_two); + + // Ensure a different process has a different stability path. + base::SpawnChildResult spawn_result = SpawnChild("DummyProcess"); + base::FilePath stability_path_other; + ASSERT_TRUE(GetStabilityFileForProcess(spawn_result.process, empty_path, + &stability_path_other)); + EXPECT_NE(stability_path, stability_path_other); +} + +TEST(StabilityPathsTest, + GetStabilityFilePatternMatchesGetStabilityFileForProcessResult) { + // GetStabilityFileForProcess file names must match GetStabilityFilePattern + // according to + // FileEnumerator's algorithm. We test this by writing out some files and + // validating what is matched. + + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath user_data_dir = temp_dir.GetPath(); + + // Create the stability directory. + base::FilePath stability_dir = GetStabilityDir(user_data_dir); + ASSERT_TRUE(base::CreateDirectory(stability_dir)); + + // Write a stability file. + base::FilePath stability_file; + ASSERT_TRUE(GetStabilityFileForProcess(base::Process::Current(), + user_data_dir, &stability_file)); + { + base::ScopedFILE file(base::OpenFile(stability_file, "w")); + ASSERT_TRUE(file.get()); + } + + // Write a file that shouldn't match. + base::FilePath non_matching_file = + stability_dir.AppendASCII("non_matching.foo"); + { + base::ScopedFILE file(base::OpenFile(non_matching_file, "w")); + ASSERT_TRUE(file.get()); + } + + // Validate only the stability file matches. + base::FileEnumerator enumerator(stability_dir, false /* recursive */, + base::FileEnumerator::FILES, + GetStabilityFilePattern()); + ASSERT_EQ(stability_file, enumerator.Next()); + ASSERT_TRUE(enumerator.Next().empty()); +} + TEST(StabilityPathsTest, GetStabilityFiles) { base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
diff --git a/components/browser_watcher/stability_report.proto b/components/browser_watcher/stability_report.proto index b1ca52e7..af0dae3c 100644 --- a/components/browser_watcher/stability_report.proto +++ b/components/browser_watcher/stability_report.proto
@@ -142,8 +142,17 @@ map<string, TypedValue> user_data = 9; } -// The state of a thread. +// Details about an exception. // Next id: 5 +message Exception { + optional uint32 code = 1; + optional uint64 program_counter = 2; + optional uint64 exception_address = 3; + optional int64 time = 4; +} + +// The state of a thread. +// Next id: 6 message ThreadState { // The name of the thread, up to a maxiumum length. optional string thread_name = 1; @@ -155,6 +164,10 @@ // stack and |activities| holds the base of the stack (up to a maximum size). optional int32 activity_count = 3; repeated Activity activities = 4; + + // The last exception to be successfully captured. Note this exception may + // have been recovered from. + optional Exception exception = 5; } // The state of a process.
diff --git a/components/browser_watcher/stability_report_extractor.cc b/components/browser_watcher/stability_report_extractor.cc index fd5c185e..a9f71ba 100644 --- a/components/browser_watcher/stability_report_extractor.cc +++ b/components/browser_watcher/stability_report_extractor.cc
@@ -181,6 +181,15 @@ } } +void CollectException(const base::debug::Activity& recorded, + Exception* collected) { + DCHECK(collected); + collected->set_code(recorded.data.exception.code); + collected->set_program_counter(recorded.calling_address); + collected->set_exception_address(recorded.origin_address); + collected->set_time(recorded.time_internal); +} + void CollectThread( const base::debug::ThreadActivityAnalyzer::Snapshot& snapshot, ThreadState* thread_state) { @@ -190,6 +199,12 @@ thread_state->set_thread_id(snapshot.thread_id); thread_state->set_activity_count(snapshot.activity_stack_depth); + if (snapshot.last_exception.activity_type == + base::debug::Activity::ACT_EXCEPTION) { + CollectException(snapshot.last_exception, + thread_state->mutable_exception()); + } + for (size_t i = 0; i < snapshot.activity_stack.size(); ++i) { Activity* collected = thread_state->add_activities();
diff --git a/components/browser_watcher/stability_report_extractor_unittest.cc b/components/browser_watcher/stability_report_extractor_unittest.cc index 63dd24d..d5f50b6 100644 --- a/components/browser_watcher/stability_report_extractor_unittest.cc +++ b/components/browser_watcher/stability_report_extractor_unittest.cc
@@ -15,6 +15,7 @@ #include "base/memory/ptr_util.h" #include "base/metrics/persistent_memory_allocator.h" #include "base/stl_util.h" +#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/crashpad/crashpad/client/crash_report_database.h" @@ -119,6 +120,22 @@ return WrapUnique(new ThreadActivityTracker(mem_base, tracker_mem_size)); } + void PerformBasicReportValidation(const StabilityReport& report) { + // One report with one thread that has the expected name and id. + ASSERT_EQ(1, report.process_states_size()); + const ProcessState& process_state = report.process_states(0); + EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id()); + ASSERT_EQ(1, process_state.threads_size()); + const ThreadState& thread_state = process_state.threads(0); + EXPECT_EQ(base::PlatformThread::GetName(), thread_state.thread_name()); +#if defined(OS_WIN) + EXPECT_EQ(base::PlatformThread::CurrentId(), thread_state.thread_id()); +#elif defined(OS_POSIX) + EXPECT_EQ(base::PlatformThread::CurrentHandle().platform_handle(), + thread_state.thread_id()); +#endif + } + const FilePath& debug_file_path() const { return debug_file_path_; } protected: @@ -163,19 +180,8 @@ ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report)); // Validate the report. - ASSERT_EQ(1, report.process_states_size()); - const ProcessState& process_state = report.process_states(0); - EXPECT_EQ(base::GetCurrentProcId(), process_state.process_id()); - ASSERT_EQ(1, process_state.threads_size()); - - const ThreadState& thread_state = process_state.threads(0); - EXPECT_EQ(base::PlatformThread::GetName(), thread_state.thread_name()); -#if defined(OS_WIN) - EXPECT_EQ(base::PlatformThread::CurrentId(), thread_state.thread_id()); -#elif defined(OS_POSIX) - EXPECT_EQ(base::PlatformThread::CurrentHandle().platform_handle(), - thread_state.thread_id()); -#endif + ASSERT_NO_FATAL_FAILURE(PerformBasicReportValidation(report)); + const ThreadState& thread_state = report.process_states(0).threads(0); EXPECT_EQ(7, thread_state.activity_count()); ASSERT_EQ(6, thread_state.activities_size()); @@ -223,6 +229,48 @@ } } +TEST_F(StabilityReportExtractorThreadTrackerTest, CollectException) { + const void* expected_pc = reinterpret_cast<void*>(0xCAFE); + const void* expected_address = nullptr; + const uint32_t expected_code = 42U; + + // Record an exception. + const int64_t timestamp = base::Time::Now().ToInternalValue(); + tracker_->RecordExceptionActivity(expected_pc, expected_address, + base::debug::Activity::ACT_EXCEPTION, + ActivityData::ForException(expected_code)); + + // Collect report and validate. + StabilityReport report; + ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report)); + + // Validate the presence of the exception. + ASSERT_NO_FATAL_FAILURE(PerformBasicReportValidation(report)); + const ThreadState& thread_state = report.process_states(0).threads(0); + ASSERT_TRUE(thread_state.has_exception()); + const Exception& exception = thread_state.exception(); + EXPECT_EQ(expected_code, exception.code()); + EXPECT_EQ(expected_pc, reinterpret_cast<void*>(exception.program_counter())); + EXPECT_EQ(expected_address, + reinterpret_cast<void*>(exception.exception_address())); + const int64_t tolerance_us = 1000ULL; + EXPECT_LE(std::abs(timestamp - exception.time()), tolerance_us); +} + +TEST_F(StabilityReportExtractorThreadTrackerTest, CollectNoException) { + // Record something. + tracker_->PushActivity(reinterpret_cast<void*>(kTaskOrigin), + base::debug::Activity::ACT_TASK_RUN, + ActivityData::ForTask(kTaskSequenceNum)); + + // Collect report and validate there is no exception. + StabilityReport report; + ASSERT_EQ(SUCCESS, Extract(debug_file_path(), &report)); + ASSERT_NO_FATAL_FAILURE(PerformBasicReportValidation(report)); + const ThreadState& thread_state = report.process_states(0).threads(0); + ASSERT_FALSE(thread_state.has_exception()); +} + // Tests stability report extraction. class StabilityReportExtractorTest : public testing::Test { public:
diff --git a/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom b/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom index 07013fe0..e935de9d57 100644 --- a/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom +++ b/components/chrome_cleaner/public/interfaces/chrome_prompt.mojom
@@ -4,7 +4,14 @@ module chrome_cleaner.mojom; -import "mojo/common/file_path.mojom"; +// IMPORTANT NOTE: Avoid adding dependencies to typemapped .mojom files. +// Enabling typemaps currently (as of July 2017) requires indirectly depending +// on all existing typemap definitions. The Chrome Cleaner is built +// independently from Chromium and would like to avoid these dependencies. + +// Once it's possible to specify a limited subset of typemaps to use, be +// careful not to add dependencies to [Native] mojo structures. The wire format +// for [Native] structs is not guaranteed to be consistent between versions. [Extensible] enum PromptAcceptance { @@ -21,6 +28,10 @@ IGNORED = 4, }; +struct FilePath { + array<uint16> value; +}; + // Service provided by Chrome to prompt the user to start a cleanup if the // Chrome Cleanup Tool detects unwanted software on the system. interface ChromePrompt { @@ -29,6 +40,6 @@ // will be deleted by the Chrome Cleanup Tool. // Returns: // - prompt_acceptance: indicates if the user accepted the prompt. - PromptUser(array<mojo.common.mojom.FilePath> files_to_delete) + PromptUser(array<FilePath> files_to_delete) => (PromptAcceptance prompt_acceptance); };
diff --git a/components/chrome_cleaner/public/typemaps/DEPS b/components/chrome_cleaner/public/typemaps/DEPS new file mode 100644 index 0000000..e9aaaf9 --- /dev/null +++ b/components/chrome_cleaner/public/typemaps/DEPS
@@ -0,0 +1,4 @@ +# Allow the typemaps to access their dependencies. +include_rules = [ + '+base/files/file_path.h', +]
diff --git a/components/chrome_cleaner/public/typemaps/OWNERS b/components/chrome_cleaner/public/typemaps/OWNERS new file mode 100644 index 0000000..adcd752e --- /dev/null +++ b/components/chrome_cleaner/public/typemaps/OWNERS
@@ -0,0 +1,7 @@ +set noparent +file://ipc/SECURITY_OWNERS + +per-file *_struct_traits*.*=set noparent +per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS +per-file *.typemap=set noparent +per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap b/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap new file mode 100644 index 0000000..ec34d5e --- /dev/null +++ b/components/chrome_cleaner/public/typemaps/chrome_prompt.typemap
@@ -0,0 +1,12 @@ +# 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. + +mojom = "//components/chrome_cleaner/public/interfaces/chrome_prompt.mojom" +public_headers = [ "//base/files/file_path.h" ] +traits_headers = [ "//components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.h" ] +sources = [ + "//components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.cc", +] + +type_mappings = [ "chrome_cleaner.mojom.FilePath=base::FilePath" ]
diff --git a/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.cc b/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.cc new file mode 100644 index 0000000..d15c172 --- /dev/null +++ b/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.cc
@@ -0,0 +1,41 @@ +// 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 "components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.h" + +namespace mojo { + +// static +ConstCArray<uint16_t> +StructTraits<chrome_cleaner::mojom::FilePathDataView, base::FilePath>::value( + const base::FilePath& file_path) { +#if defined(OS_WIN) + return ConstCArray<uint16_t>( + file_path.value().size(), + reinterpret_cast<const uint16_t*>(file_path.value().data())); +#else + NOTREACHED(); + return ConstCArray<uint16_t>(); +#endif +} + +// static +bool StructTraits<chrome_cleaner::mojom::FilePathDataView, + base::FilePath>::Read(chrome_cleaner::mojom::FilePathDataView + path_view, + base::FilePath* out) { +#if defined(OS_WIN) + ArrayDataView<uint16_t> view; + path_view.GetValueDataView(&view); + base::FilePath path = base::FilePath(base::string16( + reinterpret_cast<const base::char16*>(view.data()), view.size())); + *out = std::move(path); + return true; +#else + NOTREACHED(); + return false; +#endif +} + +} // namespace mojo
diff --git a/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.h b/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.h new file mode 100644 index 0000000..76d123f --- /dev/null +++ b/components/chrome_cleaner/public/typemaps/chrome_prompt_struct_traits.h
@@ -0,0 +1,22 @@ +// 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 COMPONENTS_CHROME_CLEANER_PUBLIC_TYPEMAPS_CHROME_CLEANER_STRUCT_TRAITS_H_ +#define COMPONENTS_CHROME_CLEANER_PUBLIC_TYPEMAPS_CHROME_CLEANER_STRUCT_TRAITS_H_ + +#include "base/files/file_path.h" +#include "components/chrome_cleaner/public/interfaces/chrome_prompt.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<chrome_cleaner::mojom::FilePathDataView, base::FilePath> { + static ConstCArray<uint16_t> value(const base::FilePath& file_path); + static bool Read(chrome_cleaner::mojom::FilePathDataView path_view, + base::FilePath* out); +}; + +} // namespace mojo + +#endif // COMPONENTS_CHROME_CLEANER_PUBLIC_TYPEMAPS_CHROME_CLEANER_STRUCT_TRAITS_H_
diff --git a/components/download/content/factory/download_service_factory.cc b/components/download/content/factory/download_service_factory.cc index bb2d7b97..b99a024 100644 --- a/components/download/content/factory/download_service_factory.cc +++ b/components/download/content/factory/download_service_factory.cc
@@ -12,6 +12,7 @@ #include "components/download/internal/download_store.h" #include "components/download/internal/model_impl.h" #include "components/download/internal/proto/entry.pb.h" +#include "components/download/internal/scheduler/scheduler_impl.h" #include "components/leveldb_proto/proto_database_impl.h" namespace download { @@ -42,10 +43,11 @@ std::move(entry_db)); auto model = base::MakeUnique<ModelImpl>(std::move(store)); auto device_status_listener = base::MakeUnique<DeviceStatusListener>(); + auto scheduler = base::MakeUnique<SchedulerImpl>(nullptr, client_set.get()); auto controller = base::MakeUnique<ControllerImpl>( std::move(client_set), std::move(config), std::move(driver), - std::move(model), std::move(device_status_listener), + std::move(model), std::move(device_status_listener), std::move(scheduler), std::move(task_scheduler)); return new DownloadServiceImpl(std::move(controller)); }
diff --git a/components/download/content/internal/download_driver_impl.cc b/components/download/content/internal/download_driver_impl.cc index 99dfd42..0300deb 100644 --- a/components/download/content/internal/download_driver_impl.cc +++ b/components/download/content/internal/download_driver_impl.cc
@@ -47,6 +47,7 @@ entry.bytes_downloaded = item->GetReceivedBytes(); entry.expected_total_size = item->GetTotalBytes(); entry.response_headers = item->GetResponseHeaders(); + entry.url_chain = item->GetUrlChain(); return entry; } @@ -78,40 +79,44 @@ } bool DownloadDriverImpl::IsReady() const { - return client_ && download_manager_; + return client_ && download_manager_ && + download_manager_->IsManagerInitialized(); } void DownloadDriverImpl::Start( - const DownloadParams& params, + const RequestParams& request_params, + const std::string& guid, const net::NetworkTrafficAnnotationTag& traffic_annotation) { - DCHECK(!params.request_params.url.is_empty()); - DCHECK(!params.guid.empty()); + DCHECK(!request_params.url.is_empty()); + DCHECK(!guid.empty()); if (!download_manager_) return; content::StoragePartition* storage_partition = content::BrowserContext::GetStoragePartitionForSite( - download_manager_->GetBrowserContext(), params.request_params.url); + download_manager_->GetBrowserContext(), request_params.url); DCHECK(storage_partition); std::unique_ptr<content::DownloadUrlParameters> download_url_params( new content::DownloadUrlParameters( - params.request_params.url, storage_partition->GetURLRequestContext(), + request_params.url, storage_partition->GetURLRequestContext(), traffic_annotation)); - // TODO(xingliu): Handle the request headers from |params|, need to tweak - // download network stack. - // Make content::DownloadManager handle potential guid collision and return - // an error to fail the download cleanly. - download_url_params->set_guid(params.guid); + // TODO(xingliu): Make content::DownloadManager handle potential guid + // collision and return an error to fail the download cleanly. + for (net::HttpRequestHeaders::Iterator it(request_params.request_headers); + it.GetNext();) { + download_url_params->add_request_header(it.name(), it.value()); + } + download_url_params->set_guid(guid); download_url_params->set_transient(true); - download_url_params->set_method(params.request_params.method); - download_url_params->set_file_path(file_dir_.AppendASCII(params.guid)); + download_url_params->set_method(request_params.method); + download_url_params->set_file_path(file_dir_.AppendASCII(guid)); download_manager_->DownloadUrl(std::move(download_url_params)); } -void DownloadDriverImpl::Cancel(const std::string& guid) { +void DownloadDriverImpl::Remove(const std::string& guid) { if (!download_manager_) return; content::DownloadItem* item = download_manager_->GetDownloadByGuid(guid); @@ -173,7 +178,11 @@ item->AddObserver(this); DCHECK(client_); DriverEntry entry = CreateDriverEntry(item); - client_->OnDownloadCreated(entry); + + // Only notifies the client about new downloads. Exsting download data will be + // loaded before the driver is ready. + if (IsReady()) + client_->OnDownloadCreated(entry); } void DownloadDriverImpl::OnManagerInitialized() {
diff --git a/components/download/content/internal/download_driver_impl.h b/components/download/content/internal/download_driver_impl.h index 61bc64f..5330733 100644 --- a/components/download/content/internal/download_driver_impl.h +++ b/components/download/content/internal/download_driver_impl.h
@@ -36,9 +36,10 @@ void Initialize(DownloadDriver::Client* client) override; bool IsReady() const override; void Start( - const DownloadParams& params, + const RequestParams& request_params, + const std::string& guid, const net::NetworkTrafficAnnotationTag& traffic_annotation) override; - void Cancel(const std::string& guid) override; + void Remove(const std::string& guid) override; void Pause(const std::string& guid) override; void Resume(const std::string& guid) override; base::Optional<DriverEntry> Find(const std::string& guid) override;
diff --git a/components/download/internal/controller.h b/components/download/internal/controller.h index 26011a0b..7ed4804 100644 --- a/components/download/internal/controller.h +++ b/components/download/internal/controller.h
@@ -18,6 +18,23 @@ struct SchedulingParams; struct StartupStatus; +// The type of completion when the download entry transits to complete state. +// TODO(xingliu): Implement timeout and unknown failure types. +enum class CompletionType { + // The download is successfully finished. + SUCCEED = 0, + // The download is interrupted and failed. + FAIL = 1, + // The download is aborted by the client. + ABORT = 2, + // The download is timed out and the connection is closed. + TIMEOUT = 3, + // The download is failed for unknown reasons. + UNKNOWN = 4, + // The download is cancelled. + CANCEL = 5, +}; + // The core Controller responsible for gluing various DownloadService components // together to manage the active downloads. class Controller {
diff --git a/components/download/internal/controller_impl.cc b/components/download/internal/controller_impl.cc index c5e6782..75870bae 100644 --- a/components/download/internal/controller_impl.cc +++ b/components/download/internal/controller_impl.cc
@@ -9,14 +9,31 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "components/download/internal/client_set.h" #include "components/download/internal/config.h" #include "components/download/internal/entry.h" #include "components/download/internal/entry_utils.h" #include "components/download/internal/model.h" +#include "components/download/internal/scheduler/scheduler.h" +#include "components/download/internal/stats.h" +#include "components/download/public/client.h" +#include "net/traffic_annotation/network_traffic_annotation.h" namespace download { +namespace { + +// Helper function to transit the state of |entry| to |new_state|. +void TransitTo(Entry* entry, Entry::State new_state, Model* model) { + DCHECK(entry); + if (entry->state == new_state) + return; + entry->state = new_state; + model->Update(*entry); +} + +} // namespace ControllerImpl::ControllerImpl( std::unique_ptr<ClientSet> clients, @@ -24,17 +41,17 @@ std::unique_ptr<DownloadDriver> driver, std::unique_ptr<Model> model, std::unique_ptr<DeviceStatusListener> device_status_listener, + std::unique_ptr<Scheduler> scheduler, std::unique_ptr<TaskScheduler> task_scheduler) : clients_(std::move(clients)), config_(std::move(config)), driver_(std::move(driver)), model_(std::move(model)), device_status_listener_(std::move(device_status_listener)), + scheduler_(std::move(scheduler)), task_scheduler_(std::move(task_scheduler)) {} -ControllerImpl::~ControllerImpl() { - device_status_listener_->Stop(); -} +ControllerImpl::~ControllerImpl() = default; void ControllerImpl::Initialize() { DCHECK(!startup_status_.Complete()); @@ -83,15 +100,19 @@ DCHECK(startup_status_.Ok()); auto* entry = model_->Get(guid); - DCHECK(entry); - if (entry->state == Entry::State::PAUSED || + if (!entry || entry->state == Entry::State::PAUSED || entry->state == Entry::State::COMPLETE || entry->state == Entry::State::WATCHDOG) { return; } - // TODO(dtrainor): Pause the download. + TransitTo(entry, Entry::State::PAUSED, model_.get()); + UpdateDriverState(*entry); + + // Pausing a download may yield a concurrent slot to start a new download, and + // may change the scheduling criteria. + ActivateMoreDownloads(); } void ControllerImpl::ResumeDownload(const std::string& guid) { @@ -103,23 +124,28 @@ if (entry->state != Entry::State::PAUSED) return; - // TODO(dtrainor): Resume the download. + TransitTo(entry, Entry::State::ACTIVE, model_.get()); + UpdateDriverState(*entry); + + ActivateMoreDownloads(); } void ControllerImpl::CancelDownload(const std::string& guid) { DCHECK(startup_status_.Ok()); auto* entry = model_->Get(guid); - DCHECK(entry); + if (!entry) + return; if (entry->state == Entry::State::NEW) { // Check if we're currently trying to add the download. DCHECK(start_callbacks_.find(entry->guid) != start_callbacks_.end()); HandleStartDownloadResponse(entry->client, entry->guid, DownloadParams::StartResult::CLIENT_CANCELLED); + return; } - // TODO(dtrainor): Cancel the download. + HandleCompleteDownload(CompletionType::CANCEL, guid); } void ControllerImpl::ChangeDownloadCriteria(const std::string& guid, @@ -127,9 +153,18 @@ DCHECK(startup_status_.Ok()); auto* entry = model_->Get(guid); - DCHECK(entry); + if (!entry || entry->scheduling_params == params) { + DVLOG(1) << "Try to update the same scheduling parameters."; + return; + } - // TODO(dtrainor): Change the criteria of the download. + UpdateDriverState(*entry); + + // Update the scheduling parameters. + entry->scheduling_params = params; + model_->Update(*entry); + + ActivateMoreDownloads(); } DownloadClient ControllerImpl::GetOwnerOfDownload(const std::string& guid) { @@ -194,15 +229,51 @@ AttemptToFinalizeSetup(); } -void ControllerImpl::OnDownloadCreated(const DriverEntry& download) {} +void ControllerImpl::OnDownloadCreated(const DriverEntry& download) { + Entry* entry = model_->Get(download.guid); + if (!entry) { + // TODO(xingliu): Log non download service initiated downloads. + return; + } + + download::Client* client = clients_->GetClient(entry->client); + DCHECK(client); + using ShouldDownload = download::Client::ShouldDownload; + ShouldDownload should_download = client->OnDownloadStarted( + download.guid, download.url_chain, download.response_headers); + if (should_download == ShouldDownload::ABORT) { + HandleCompleteDownload(CompletionType::ABORT, entry->guid); + } +} void ControllerImpl::OnDownloadFailed(const DriverEntry& download, int reason) { + Entry* entry = model_->Get(download.guid); + if (!entry) + return; + + HandleCompleteDownload(CompletionType::FAIL, download.guid); } void ControllerImpl::OnDownloadSucceeded(const DriverEntry& download, - const base::FilePath& path) {} + const base::FilePath& path) { + Entry* entry = model_->Get(download.guid); + if (!entry) + return; -void ControllerImpl::OnDownloadUpdated(const DriverEntry& download) {} + HandleCompleteDownload(CompletionType::SUCCEED, download.guid); +} + +void ControllerImpl::OnDownloadUpdated(const DriverEntry& download) { + Entry* entry = model_->Get(download.guid); + if (!entry) + return; + + DCHECK_EQ(download.state, DriverEntry::State::IN_PROGRESS); + + download::Client* client = clients_->GetClient(entry->client); + if (client) + client->OnDownloadUpdated(download.guid, download.bytes_downloaded); +} void ControllerImpl::OnModelReady(bool success) { DCHECK(!startup_status_.model_ok.has_value()); @@ -227,9 +298,12 @@ HandleStartDownloadResponse(client, guid, DownloadParams::StartResult::ACCEPTED); - auto* entry = model_->Get(guid); + Entry* entry = model_->Get(guid); DCHECK(entry); DCHECK_EQ(Entry::State::NEW, entry->state); + TransitTo(entry, Entry::State::AVAILABLE, model_.get()); + + ActivateMoreDownloads(); // TODO(dtrainor): Make sure we're running all of the downloads we care about. } @@ -237,7 +311,12 @@ void ControllerImpl::OnItemUpdated(bool success, DownloadClient client, const std::string& guid) { - // TODO(dtrainor): Fail and clean up the download if necessary. + Entry* entry = model_->Get(guid); + DCHECK(entry); + if (entry->state == Entry::State::COMPLETE || + entry->state == Entry::State::WATCHDOG) { + driver_->Remove(guid); + } } void ControllerImpl::OnItemRemoved(bool success, @@ -247,7 +326,8 @@ } void ControllerImpl::OnDeviceStatusChanged(const DeviceStatus& device_status) { - NOTIMPLEMENTED(); + UpdateDriverStates(); + ActivateMoreDownloads(); } void ControllerImpl::AttemptToFinalizeSetup() { @@ -265,12 +345,16 @@ device_status_listener_->Start(this); CancelOrphanedRequests(); ResolveInitialRequestStates(); + UpdateDriverStates(); PullCurrentRequestStatus(); // TODO(dtrainor): Post this so that the initialization step is finalized // before Clients can take action. NotifyClientsOfStartup(); ProcessScheduledTasks(); + + // Pull the initial straw if active downloads haven't reach maximum. + ActivateMoreDownloads(); } void ControllerImpl::CancelOrphanedRequests() { @@ -282,8 +366,10 @@ guids_to_remove.push_back(entry->guid); } - for (auto guid : guids_to_remove) { - // TODO(dtrainor): Remove the download. + for (const auto& guid : guids_to_remove) { + model_->Remove(guid); + // TODO(xingliu): Use file monitor to delete the files. + driver_->Remove(guid); } } @@ -291,6 +377,53 @@ // TODO(dtrainor): Implement. } +void ControllerImpl::UpdateDriverStates() { + DCHECK(startup_status_.Complete()); + + for (auto* const entry : model_->PeekEntries()) + UpdateDriverState(*entry); +} + +void ControllerImpl::UpdateDriverState(const Entry& entry) { + base::Optional<DriverEntry> driver_entry = driver_->Find(entry.guid); + + bool meets_device_criteria = device_status_listener_->CurrentDeviceStatus() + .MeetsCondition(entry.scheduling_params) + .MeetsRequirements(); + switch (entry.state) { + case Entry::State::ACTIVE: + if (!meets_device_criteria) { + driver_->Pause(entry.guid); + break; + } + // Start or resume the download if it should be running. + if (!driver_entry.has_value()) { + driver_->Start(entry.request_params, entry.guid, + NO_TRAFFIC_ANNOTATION_YET); + break; + } + if (driver_entry->state != DriverEntry::State::IN_PROGRESS) { + driver_->Resume(entry.guid); + } + break; + case Entry::State::PAUSED: + // Pause the in progress downloads that should not be running. + if (driver_entry.has_value() && + driver_entry->state == DriverEntry::State::IN_PROGRESS) { + driver_->Pause(entry.guid); + } + break; + // Fall through. + case Entry::State::AVAILABLE: + case Entry::State::NEW: + case Entry::State::COMPLETE: + case Entry::State::WATCHDOG: + break; + default: + NOTREACHED(); + } +} + void ControllerImpl::PullCurrentRequestStatus() { // TODO(dtrainor): Implement. } @@ -329,4 +462,36 @@ FROM_HERE, base::Bind(callback, guid, result)); } +void ControllerImpl::HandleCompleteDownload(CompletionType type, + const std::string& guid) { + Entry* entry = model_->Get(guid); + DCHECK(entry); + stats::LogDownloadCompletion(type); + + if (entry->state == Entry::State::COMPLETE || + entry->state == Entry::State::WATCHDOG) { + DVLOG(1) << "Download is already completed."; + return; + } + + // TODO(xingliu): Notify the client based on completion type. + TransitTo(entry, Entry::State::COMPLETE, model_.get()); + ActivateMoreDownloads(); +} + +void ControllerImpl::ActivateMoreDownloads() { + // TODO(xingliu): Check the configuration to throttle downloads. + Entry* next = scheduler_->Next( + model_->PeekEntries(), device_status_listener_->CurrentDeviceStatus()); + + while (next) { + DCHECK_EQ(Entry::State::AVAILABLE, next->state); + TransitTo(next, Entry::State::ACTIVE, model_.get()); + UpdateDriverState(*next); + next = scheduler_->Next(model_->PeekEntries(), + device_status_listener_->CurrentDeviceStatus()); + } + scheduler_->Reschedule(model_->PeekEntries()); +} + } // namespace download
diff --git a/components/download/internal/controller_impl.h b/components/download/internal/controller_impl.h index 3e7a852..fa151fe 100644 --- a/components/download/internal/controller_impl.h +++ b/components/download/internal/controller_impl.h
@@ -12,6 +12,7 @@ #include "base/optional.h" #include "components/download/internal/controller.h" #include "components/download/internal/download_driver.h" +#include "components/download/internal/entry.h" #include "components/download/internal/model.h" #include "components/download/internal/scheduler/device_status_listener.h" #include "components/download/internal/startup_status.h" @@ -24,6 +25,7 @@ class ClientSet; class DownloadDriver; class Model; +class Scheduler; struct Configuration; struct SchedulingParams; @@ -41,6 +43,7 @@ std::unique_ptr<DownloadDriver> driver, std::unique_ptr<Model> model, std::unique_ptr<DeviceStatusListener> device_status_listener, + std::unique_ptr<Scheduler> scheduler, std::unique_ptr<TaskScheduler> task_scheduler); ~ControllerImpl() override; @@ -94,6 +97,14 @@ // resolve state issues during startup. void ResolveInitialRequestStates(); + // Updates the driver states based on the states of entries in download + // service. + void UpdateDriverStates(); + + // Processes the download based on the state of |entry|. May start, pause + // or resume a download accordingly. + void UpdateDriverState(const Entry& entry); + // Notifies all Client in |clients_| that this controller is initialized and // lets them know which download requests we are aware of for their // DownloadClient. @@ -120,6 +131,12 @@ bool needs_reschedule, stats::ScheduledTaskStatus status); + void HandleCompleteDownload(CompletionType type, const std::string& guid); + + // Find more available entries to download, until the number of active entries + // reached maximum. + void ActivateMoreDownloads(); + std::unique_ptr<ClientSet> clients_; std::unique_ptr<Configuration> config_; @@ -127,6 +144,7 @@ std::unique_ptr<DownloadDriver> driver_; std::unique_ptr<Model> model_; std::unique_ptr<DeviceStatusListener> device_status_listener_; + std::unique_ptr<Scheduler> scheduler_; std::unique_ptr<TaskScheduler> task_scheduler_; // Internal state.
diff --git a/components/download/internal/controller_impl_unittest.cc b/components/download/internal/controller_impl_unittest.cc index 6cecf73..7503be05 100644 --- a/components/download/internal/controller_impl_unittest.cc +++ b/components/download/internal/controller_impl_unittest.cc
@@ -17,6 +17,7 @@ #include "components/download/internal/config.h" #include "components/download/internal/entry.h" #include "components/download/internal/model_impl.h" +#include "components/download/internal/scheduler/scheduler.h" #include "components/download/internal/test/entry_utils.h" #include "components/download/internal/test/mock_client.h" #include "components/download/internal/test/test_device_status_listener.h" @@ -41,14 +42,27 @@ MOCK_METHOD1(CancelTask, void(DownloadTaskType)); }; +class MockScheduler : public Scheduler { + public: + MockScheduler() = default; + ~MockScheduler() override = default; + + MOCK_METHOD1(Reschedule, void(const Model::EntryList&)); + MOCK_METHOD2(Next, Entry*(const Model::EntryList&, const DeviceStatus&)); +}; + class DownloadServiceControllerImplTest : public testing::Test { public: DownloadServiceControllerImplTest() : task_runner_(new base::TestSimpleTaskRunner), handle_(task_runner_), + controller_(nullptr), client_(nullptr), driver_(nullptr), - store_(nullptr) { + store_(nullptr), + model_(nullptr), + device_status_listener_(nullptr), + scheduler_(nullptr) { start_callback_ = base::Bind(&DownloadServiceControllerImplTest::StartCallback, base::Unretained(this)); @@ -71,13 +85,19 @@ clients->insert(std::make_pair(DownloadClient::TEST, std::move(client))); auto client_set = base::MakeUnique<ClientSet>(std::move(clients)); auto model = base::MakeUnique<ModelImpl>(std::move(store)); - auto device_status_listener = base::MakeUnique<TestDeviceStatusListener>(); + auto device_status_listener = + base::MakeUnique<test::TestDeviceStatusListener>(); + auto scheduler = base::MakeUnique<MockScheduler>(); auto task_scheduler = base::MakeUnique<MockTaskScheduler>(); + model_ = model.get(); + device_status_listener_ = device_status_listener.get(); + scheduler_ = scheduler.get(); + controller_ = base::MakeUnique<ControllerImpl>( std::move(client_set), std::move(config), std::move(driver), std::move(model), std::move(device_status_listener), - std::move(task_scheduler)); + std::move(scheduler), std::move(task_scheduler)); } protected: @@ -100,6 +120,9 @@ test::MockClient* client_; test::TestDownloadDriver* driver_; test::TestStore* store_; + ModelImpl* model_; + test::TestDeviceStatusListener* device_status_listener_; + MockScheduler* scheduler_; DownloadParams::StartCallback start_callback_; @@ -122,6 +145,8 @@ EXPECT_TRUE(controller_->GetStartupStatus()->model_ok.value()); EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); driver_->MakeReady(); EXPECT_TRUE(controller_->GetStartupStatus()->Complete()); @@ -144,6 +169,8 @@ EXPECT_TRUE(controller_->GetStartupStatus()->driver_ok.value()); EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>()); EXPECT_TRUE(controller_->GetStartupStatus()->Complete()); @@ -165,6 +192,8 @@ EXPECT_CALL( *client_, OnServiceInitialized(testing::UnorderedElementsAreArray(expected_guids))); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); controller_->Initialize(); driver_->MakeReady(); @@ -188,6 +217,8 @@ std::vector<Entry> entries = {entry}; EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); controller_->Initialize(); driver_->MakeReady(); @@ -202,6 +233,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadAccepted) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); // Set up the Controller. controller_->Initialize(); @@ -214,6 +247,8 @@ EXPECT_CALL(*this, StartCallback(params.guid, DownloadParams::StartResult::ACCEPTED)) .Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); controller_->StartDownload(params); // TODO(dtrainor): Compare the full DownloadParams with the full Entry. @@ -224,6 +259,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBackoff) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); Entry entry = test::BuildBasicEntry(); std::vector<Entry> entries = {entry}; @@ -252,6 +289,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithDuplicateGuidInModel) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); Entry entry = test::BuildBasicEntry(); std::vector<Entry> entries = {entry}; @@ -280,6 +319,10 @@ testing::InSequence sequence; EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); // Set up the Controller. controller_->Initialize(); @@ -305,6 +348,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithBadClient) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); // Set up the Controller. controller_->Initialize(); @@ -326,6 +371,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithClientCancel) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); // Set up the Controller. controller_->Initialize(); @@ -349,6 +396,8 @@ TEST_F(DownloadServiceControllerImplTest, AddDownloadFailsWithInternalError) { EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); // Set up the Controller. controller_->Initialize(); @@ -368,4 +417,182 @@ task_runner_->RunUntilIdle(); } +TEST_F(DownloadServiceControllerImplTest, Pause) { + // Setup download service test data. + Entry entry1 = test::BuildBasicEntry(); + Entry entry2 = test::BuildBasicEntry(); + Entry entry3 = test::BuildBasicEntry(); + entry1.state = Entry::State::AVAILABLE; + entry2.state = Entry::State::ACTIVE; + entry3.state = Entry::State::COMPLETE; + std::vector<Entry> entries = {entry1, entry2, entry3}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(3); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(3); + + // Set the network status to disconnected so no entries will be polled from + // the scheduler. + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + // Setup download driver test data. + DriverEntry driver_entry1, driver_entry2, driver_entry3; + driver_entry1.guid = entry1.guid; + driver_entry1.state = DriverEntry::State::IN_PROGRESS; + driver_entry2.guid = entry2.guid; + driver_entry2.state = DriverEntry::State::IN_PROGRESS; + driver_entry3.guid = entry3.guid; + driver_->AddTestData( + std::vector<DriverEntry>{driver_entry1, driver_entry2, driver_entry3}); + + // Pause in progress available entry. + EXPECT_EQ(Entry::State::AVAILABLE, model_->Get(entry1.guid)->state); + controller_->PauseDownload(entry1.guid); + EXPECT_TRUE(driver_->Find(entry1.guid)->paused); + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entry1.guid)->state); + + // Pause in progress active entry. + controller_->PauseDownload(entry2.guid); + EXPECT_TRUE(driver_->Find(entry2.guid)->paused); + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entry2.guid)->state); + + // Entries in complete states can't be paused. + controller_->PauseDownload(entry3.guid); + EXPECT_FALSE(driver_->Find(entry3.guid)->paused); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entry3.guid)->state); + + task_runner_->RunUntilIdle(); +} + +TEST_F(DownloadServiceControllerImplTest, Resume) { + // Setupd download service test data. + Entry entry1 = test::BuildBasicEntry(); + Entry entry2 = test::BuildBasicEntry(); + entry1.state = Entry::State::PAUSED; + entry2.state = Entry::State::ACTIVE; + std::vector<Entry> entries = {entry1, entry2}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(2); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(2); + + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + // Setup download driver test data. + DriverEntry driver_entry1, driver_entry2; + driver_entry1.guid = entry1.guid; + driver_entry1.paused = true; + driver_entry2.guid = entry2.guid; + driver_entry2.paused = false; + driver_->AddTestData(std::vector<DriverEntry>{driver_entry1, driver_entry2}); + + // Resume the paused download. + device_status_listener_->SetDeviceStatus( + DeviceStatus(BatteryStatus::CHARGING, NetworkStatus::UNMETERED)); + EXPECT_EQ(Entry::State::PAUSED, model_->Get(entry1.guid)->state); + controller_->ResumeDownload(entry1.guid); + EXPECT_FALSE(driver_->Find(entry1.guid)->paused); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry1.guid)->state); + + // Entries in paused state can't be resumed. + controller_->ResumeDownload(entry2.guid); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry2.guid)->state); + EXPECT_FALSE(driver_->Find(entry2.guid)->paused); + + task_runner_->RunUntilIdle(); +} + +TEST_F(DownloadServiceControllerImplTest, Cancel) { + Entry entry = test::BuildBasicEntry(); + entry.state = Entry::State::ACTIVE; + std::vector<Entry> entries = {entry}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(2); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(2); + + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + DriverEntry driver_entry; + driver_entry.guid = entry.guid; + driver_->AddTestData(std::vector<DriverEntry>{driver_entry}); + + controller_->CancelDownload(entry.guid); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entry.guid)->state); + + task_runner_->RunUntilIdle(); +} + +TEST_F(DownloadServiceControllerImplTest, OnDownloadFailed) { + Entry entry = test::BuildBasicEntry(); + entry.state = Entry::State::ACTIVE; + std::vector<Entry> entries = {entry}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(2); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(2); + + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + DriverEntry driver_entry; + driver_entry.guid = entry.guid; + + driver_->NotifyDownloadFailed(driver_entry, 1); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entry.guid)->state); +} + +TEST_F(DownloadServiceControllerImplTest, OnDownloadSucceeded) { + Entry entry = test::BuildBasicEntry(); + entry.state = Entry::State::ACTIVE; + std::vector<Entry> entries = {entry}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(2); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(2); + + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + DriverEntry driver_entry; + driver_entry.guid = entry.guid; + driver_entry.bytes_downloaded = 1024; + base::FilePath path = base::FilePath::FromUTF8Unsafe("123"); + + driver_->NotifyDownloadSucceeded(driver_entry, path); + EXPECT_EQ(Entry::State::COMPLETE, model_->Get(entry.guid)->state); +} + +TEST_F(DownloadServiceControllerImplTest, OnDownloadUpdated) { + Entry entry = test::BuildBasicEntry(); + entry.state = Entry::State::ACTIVE; + std::vector<Entry> entries = {entry}; + + EXPECT_CALL(*client_, OnServiceInitialized(_)).Times(1); + EXPECT_CALL(*scheduler_, Next(_, _)).Times(1); + EXPECT_CALL(*scheduler_, Reschedule(_)).Times(1); + + controller_->Initialize(); + store_->TriggerInit(true, base::MakeUnique<std::vector<Entry>>(entries)); + driver_->MakeReady(); + + DriverEntry driver_entry; + driver_entry.state = DriverEntry::State::IN_PROGRESS; + driver_entry.guid = entry.guid; + driver_entry.bytes_downloaded = 1024; + + EXPECT_CALL(*client_, + OnDownloadUpdated(entry.guid, driver_entry.bytes_downloaded)); + driver_->NotifyDownloadUpdate(driver_entry); + EXPECT_EQ(Entry::State::ACTIVE, model_->Get(entry.guid)->state); +} + } // namespace download
diff --git a/components/download/internal/download_driver.h b/components/download/internal/download_driver.h index 704233ec..149e4160 100644 --- a/components/download/internal/download_driver.h +++ b/components/download/internal/download_driver.h
@@ -17,7 +17,7 @@ namespace download { -struct DownloadParams; +struct RequestParams; // The interface that includes all the operations to interact with low level // download library functionalities. @@ -52,19 +52,20 @@ // Initialize the driver to receive download updates. virtual void Initialize(Client* client) = 0; - // Returns if the driver is ready. Returns false when the driver is not - // initialized by the client, or low level download library has been shut - // down. + // Returns if the driver is ready after the low level library has loaded all + // the data. Returns false when the driver is not initialized by the client, + // or low level download library has been shut down. virtual bool IsReady() const = 0; // Starts a new download. virtual void Start( - const DownloadParams& params, + const RequestParams& request_params, + const std::string& guid, const net::NetworkTrafficAnnotationTag& traffic_annotation) = 0; // Cancels an existing download, all data associated with this download should // be removed. - virtual void Cancel(const std::string& guid) = 0; + virtual void Remove(const std::string& guid) = 0; // Pauses the download. virtual void Pause(const std::string& guid) = 0; @@ -72,7 +73,7 @@ // Resumes the download virtual void Resume(const std::string& guid) = 0; - // Find a download record from low level download library. + // Finds a download record from low level download library. virtual base::Optional<DriverEntry> Find(const std::string& guid) = 0; };
diff --git a/components/download/internal/driver_entry.h b/components/download/internal/driver_entry.h index a21a431..52f421b 100644 --- a/components/download/internal/driver_entry.h +++ b/components/download/internal/driver_entry.h
@@ -6,8 +6,10 @@ #define COMPONENTS_DOWNLOAD_INTERNAL_DRIVER_ENTRY_H_ #include <string> +#include <vector> #include "base/memory/ref_counted.h" +#include "url/gurl.h" namespace net { class HttpResponseHeaders; @@ -54,6 +56,10 @@ // The response headers for the most recent download request. scoped_refptr<const net::HttpResponseHeaders> response_headers; + + // The url chain of the download. Download may encounter redirects, and + // fetches the content from the last url in the chain. + std::vector<GURL> url_chain; }; } // namespace download
diff --git a/components/download/internal/entry_utils.cc b/components/download/internal/entry_utils.cc index b02ec79..211f8ae2 100644 --- a/components/download/internal/entry_utils.cc +++ b/components/download/internal/entry_utils.cc
@@ -52,5 +52,12 @@ return criteria; } +bool EntryBetterThan(const Entry& lhs, const Entry& rhs) { + return lhs.scheduling_params.priority > rhs.scheduling_params.priority || + (lhs.scheduling_params.priority == rhs.scheduling_params.priority && + lhs.scheduling_params.cancel_time < + rhs.scheduling_params.cancel_time); +} + } // namespace util } // namespace download
diff --git a/components/download/internal/entry_utils.h b/components/download/internal/entry_utils.h index 7e46cdba..a50244b 100644 --- a/components/download/internal/entry_utils.h +++ b/components/download/internal/entry_utils.h
@@ -33,10 +33,14 @@ const std::set<DownloadClient>& clients, const std::vector<Entry*>& entries); -// Get the least strict scheduling criteria from |entries|, the criteria is used -// to schedule platform background tasks. +// Gets the least strict scheduling criteria from |entries|, the criteria is +// used to schedule platform background tasks. Criteria GetSchedulingCriteria(const Model::EntryList& entries); +// Returns if |lhs| entry is a better candidate to be the next download than +// |rhs| based on their priority and cancel time. +bool EntryBetterThan(const Entry& lhs, const Entry& rhs); + } // namespace util } // namespace download
diff --git a/components/download/internal/scheduler/device_status.cc b/components/download/internal/scheduler/device_status.cc index 54fc152..b206ddf 100644 --- a/components/download/internal/scheduler/device_status.cc +++ b/components/download/internal/scheduler/device_status.cc
@@ -17,6 +17,9 @@ : battery_status(BatteryStatus::NOT_CHARGING), network_status(NetworkStatus::DISCONNECTED) {} +DeviceStatus::DeviceStatus(BatteryStatus battery, NetworkStatus network) + : battery_status(battery), network_status(network) {} + bool DeviceStatus::operator==(const DeviceStatus& rhs) const { return network_status == rhs.network_status && battery_status == rhs.battery_status;
diff --git a/components/download/internal/scheduler/device_status.h b/components/download/internal/scheduler/device_status.h index c1870313..43c3b22 100644 --- a/components/download/internal/scheduler/device_status.h +++ b/components/download/internal/scheduler/device_status.h
@@ -27,6 +27,8 @@ // Contains battery and network status. struct DeviceStatus { DeviceStatus(); + DeviceStatus(BatteryStatus battery, NetworkStatus network); + struct Result { Result(); bool MeetsRequirements() const;
diff --git a/components/download/internal/scheduler/device_status_listener.h b/components/download/internal/scheduler/device_status_listener.h index b02e169..4a94608 100644 --- a/components/download/internal/scheduler/device_status_listener.h +++ b/components/download/internal/scheduler/device_status_listener.h
@@ -40,6 +40,9 @@ // The observer that listens to device status change events. Observer* observer_; + // If we are actively listening to network and battery change events. + bool listening_; + private: // net::NetworkChangeNotifier implementation. void OnConnectionTypeChanged( @@ -51,9 +54,6 @@ // Notifies |observers_| about device status change. void NotifyStatusChange(); - // If we are actively listening to network and battery change events. - bool listening_; - DISALLOW_COPY_AND_ASSIGN(DeviceStatusListener); };
diff --git a/components/download/internal/scheduler/scheduler.h b/components/download/internal/scheduler/scheduler.h index 3cb0034..36e0d49 100644 --- a/components/download/internal/scheduler/scheduler.h +++ b/components/download/internal/scheduler/scheduler.h
@@ -26,6 +26,8 @@ // The sequence of polling on entries with exactly same states is undefined. virtual Entry* Next(const Model::EntryList& entries, const DeviceStatus& device_status) = 0; + + virtual ~Scheduler() {} }; // Interface to schedule platform dependent background tasks that can run after @@ -34,6 +36,7 @@ public: virtual void ScheduleDownloadTask(const Criteria& criteria) = 0; virtual void CancelDownloadTask() = 0; + virtual ~PlatformTaskScheduler() {} }; } // namespace download
diff --git a/components/download/internal/scheduler/scheduler_impl.cc b/components/download/internal/scheduler/scheduler_impl.cc index 1233dda..3a638b6 100644 --- a/components/download/internal/scheduler/scheduler_impl.cc +++ b/components/download/internal/scheduler/scheduler_impl.cc
@@ -4,12 +4,32 @@ #include "components/download/internal/scheduler/scheduler_impl.h" +#include "components/download/internal/client_set.h" #include "components/download/internal/entry_utils.h" #include "components/download/internal/scheduler/device_status.h" #include "components/download/public/download_params.h" namespace download { +namespace { + +// Returns a vector of elements contained in the |set|. +template <typename T> +std::vector<T> ToList(const std::set<T>& set) { + std::vector<T> list; + for (const auto& element : set) { + list.push_back(element); + } + return list; +} + +} // namespace + +SchedulerImpl::SchedulerImpl(PlatformTaskScheduler* platform_scheduler, + const ClientSet* clients) + : SchedulerImpl(platform_scheduler, + ToList<DownloadClient>(clients->GetRegisteredClients())) {} + SchedulerImpl::SchedulerImpl(PlatformTaskScheduler* platform_scheduler, const std::vector<DownloadClient>& clients) : platform_scheduler_(platform_scheduler), @@ -61,7 +81,6 @@ // are UI priority entries for other clients. if (!entry || ui_priority) { entry = candidate; - DCHECK(entry); // Load balancing between clients. current_client_index_ = (index + i + 1) % download_clients_.size(); @@ -94,11 +113,7 @@ // Find the most appropriate download based on priority and cancel time. Entry* candidate = candidates[entry->client]; - if (!candidate || - (current_params.priority > candidate->scheduling_params.priority || - (current_params.priority == candidate->scheduling_params.priority && - entry->scheduling_params.cancel_time < - candidate->scheduling_params.cancel_time))) { + if (!candidate || util::EntryBetterThan(*entry, *candidate)) { candidates[entry->client] = entry; } }
diff --git a/components/download/internal/scheduler/scheduler_impl.h b/components/download/internal/scheduler/scheduler_impl.h index 30c2969..cfac7cd 100644 --- a/components/download/internal/scheduler/scheduler_impl.h +++ b/components/download/internal/scheduler/scheduler_impl.h
@@ -15,6 +15,8 @@ namespace download { +class ClientSet; + // Scheduler implementation that // 1. Creates platform background task based on the states of download entries. // 2. Polls the next entry to be processed by the service mainly according to @@ -24,8 +26,10 @@ class SchedulerImpl : public Scheduler { public: SchedulerImpl(PlatformTaskScheduler* platform_scheduler, + const ClientSet* clients); + SchedulerImpl(PlatformTaskScheduler* platform_scheduler, const std::vector<DownloadClient>& clients); - ~SchedulerImpl(); + ~SchedulerImpl() override; // Scheduler implementation. void Reschedule(const Model::EntryList& entries) override;
diff --git a/components/download/internal/stats.cc b/components/download/internal/stats.cc index 762204d..b532f879 100644 --- a/components/download/internal/stats.cc +++ b/components/download/internal/stats.cc
@@ -34,5 +34,9 @@ // TODO(shaktisahu): Log |task_type| and |status|. } +void LogDownloadCompletion(CompletionType type) { + // TODO(xingliu): Log completion. +} + } // namespace stats } // namespace download
diff --git a/components/download/internal/stats.h b/components/download/internal/stats.h index 4ccae0c..7a9cecb 100644 --- a/components/download/internal/stats.h +++ b/components/download/internal/stats.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_ #define COMPONENTS_DOWNLOAD_INTERNAL_STATS_H_ +#include "components/download/internal/controller.h" #include "components/download/public/clients.h" #include "components/download/public/download_params.h" #include "components/download/public/download_task_types.h" @@ -92,6 +93,9 @@ void LogScheduledTaskStatus(DownloadTaskType task_type, ScheduledTaskStatus status); +// Logs download completion event. +void LogDownloadCompletion(CompletionType type); + } // namespace stats } // namespace download
diff --git a/components/download/internal/test/test_device_status_listener.cc b/components/download/internal/test/test_device_status_listener.cc index 7f68952..d7dc52b 100644 --- a/components/download/internal/test/test_device_status_listener.cc +++ b/components/download/internal/test/test_device_status_listener.cc
@@ -5,10 +5,15 @@ #include "components/download/internal/test/test_device_status_listener.h" namespace download { +namespace test { TestDeviceStatusListener::TestDeviceStatusListener() = default; -TestDeviceStatusListener::~TestDeviceStatusListener() = default; +TestDeviceStatusListener::~TestDeviceStatusListener() { + // Mark |listening_| to false to bypass the remove observer calls in the base + // class. + Stop(); +} void TestDeviceStatusListener::NotifyObserver( const DeviceStatus& device_status) { @@ -17,13 +22,20 @@ observer_->OnDeviceStatusChanged(status_); } +void TestDeviceStatusListener::SetDeviceStatus(const DeviceStatus& status) { + status_ = status; +} + void TestDeviceStatusListener::Start(DeviceStatusListener::Observer* observer) { + listening_ = true; observer_ = observer; } void TestDeviceStatusListener::Stop() { status_ = DeviceStatus(); observer_ = nullptr; + listening_ = false; } +} // namespace test } // namespace download
diff --git a/components/download/internal/test/test_device_status_listener.h b/components/download/internal/test/test_device_status_listener.h index 72472eca..1f8bb22 100644 --- a/components/download/internal/test/test_device_status_listener.h +++ b/components/download/internal/test/test_device_status_listener.h
@@ -8,6 +8,7 @@ #include "components/download/internal/scheduler/device_status_listener.h" namespace download { +namespace test { // Test device status listener can directly notify the observer about battery // and network changes, without calling external class methods. @@ -19,6 +20,9 @@ // Notifies observer with current device status. void NotifyObserver(const DeviceStatus& device_status); + // Sets the device status without notifying the observer. + void SetDeviceStatus(const DeviceStatus& status); + // DeviceStatusListener implementation. void Start(DeviceStatusListener::Observer* observer) override; void Stop() override; @@ -27,6 +31,7 @@ DISALLOW_COPY_AND_ASSIGN(TestDeviceStatusListener); }; +} // namespace test } // namespace download #endif // COMPONENTS_DOWNLOAD_INTERNAL_TEST_TEST_DEVICE_STATUS_LISTENER_H_
diff --git a/components/download/internal/test/test_download_driver.cc b/components/download/internal/test/test_download_driver.cc index beffa6a69d..c9f11a4 100644 --- a/components/download/internal/test/test_download_driver.cc +++ b/components/download/internal/test/test_download_driver.cc
@@ -22,6 +22,13 @@ client_->OnDriverReady(is_ready_); } +void TestDownloadDriver::AddTestData(const std::vector<DriverEntry>& entries) { + for (const auto& entry : entries) { + DCHECK(entries_.find(entry.guid) == entries_.end()) << "Existing guid."; + entries_.emplace(entry.guid, entry); + } +} + void TestDownloadDriver::NotifyDownloadUpdate(const DriverEntry& entry) { if (client_) { entries_[entry.guid] = entry; @@ -55,27 +62,40 @@ } void TestDownloadDriver::Start( - const DownloadParams& params, + const RequestParams& params, + const std::string& guid, const net::NetworkTrafficAnnotationTag& traffic_annotation) { DriverEntry entry; - entry.guid = params.guid; + entry.guid = guid; entry.state = DriverEntry::State::IN_PROGRESS; entry.paused = false; entry.bytes_downloaded = 0; entry.expected_total_size = 0; entry.response_headers = base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200"); - entries_[params.guid] = entry; + entries_[guid] = entry; if (client_) client_->OnDownloadCreated(entry); } -void TestDownloadDriver::Cancel(const std::string& guid) {} +void TestDownloadDriver::Remove(const std::string& guid) { + entries_.erase(guid); +} -void TestDownloadDriver::Pause(const std::string& guid) {} +void TestDownloadDriver::Pause(const std::string& guid) { + auto it = entries_.find(guid); + if (it == entries_.end()) + return; + it->second.paused = true; +} -void TestDownloadDriver::Resume(const std::string& guid) {} +void TestDownloadDriver::Resume(const std::string& guid) { + auto it = entries_.find(guid); + if (it == entries_.end()) + return; + it->second.paused = false; +} base::Optional<DriverEntry> TestDownloadDriver::Find(const std::string& guid) { auto it = entries_.find(guid);
diff --git a/components/download/internal/test/test_download_driver.h b/components/download/internal/test/test_download_driver.h index 5e540f65..05fd808 100644 --- a/components/download/internal/test/test_download_driver.h +++ b/components/download/internal/test/test_download_driver.h
@@ -25,6 +25,9 @@ // data initialization. void MakeReady(); + // Adds driver entries data that will be returned + void AddTestData(const std::vector<DriverEntry>& entries); + // Simulates download events from content layer. void NotifyDownloadUpdate(const DriverEntry& entry); void NotifyDownloadFailed(const DriverEntry& entry, int reason); @@ -35,9 +38,10 @@ void Initialize(DownloadDriver::Client* client) override; bool IsReady() const override; void Start( - const DownloadParams& params, + const RequestParams& params, + const std::string& guid, const net::NetworkTrafficAnnotationTag& traffic_annotation) override; - void Cancel(const std::string& guid) override; + void Remove(const std::string& guid) override; void Pause(const std::string& guid) override; void Resume(const std::string& guid) override; base::Optional<DriverEntry> Find(const std::string& guid) override;
diff --git a/components/download/public/client.h b/components/download/public/client.h index 28264e7..43349b6 100644 --- a/components/download/public/client.h +++ b/components/download/public/client.h
@@ -58,7 +58,7 @@ // DownloadParams::cancel_after timeout. virtual void OnDownloadTimedOut(const std::string& guid) = 0; - // Called when the download has been aborted after reaching a treshold where + // Called when the download has been aborted after reaching a threshold where // we decide it is not worth attempting to start again. This could be either // due to a specific number of failed retry attempts or a specific number of // wasted bytes due to the download restarting.
diff --git a/components/download/public/download_params.cc b/components/download/public/download_params.cc index f24d467..8d94dcf 100644 --- a/components/download/public/download_params.cc +++ b/components/download/public/download_params.cc
@@ -13,6 +13,12 @@ network_requirements(NetworkRequirements::NONE), battery_requirements(BatteryRequirements::BATTERY_INSENSITIVE) {} +bool SchedulingParams::operator==(const SchedulingParams& rhs) const { + return network_requirements == rhs.network_requirements && + battery_requirements == rhs.battery_requirements && + priority == rhs.priority && cancel_time == rhs.cancel_time; +} + RequestParams::RequestParams() : method("GET") {} DownloadParams::DownloadParams() : client(DownloadClient::INVALID) {}
diff --git a/components/download/public/download_params.h b/components/download/public/download_params.h index e9885e9..abd18771 100644 --- a/components/download/public/download_params.h +++ b/components/download/public/download_params.h
@@ -67,6 +67,8 @@ SchedulingParams(const SchedulingParams& other) = default; ~SchedulingParams() = default; + bool operator==(const SchedulingParams& rhs) const; + // Cancel the download after this time. Will cancel in-progress downloads. base::Time cancel_time;
diff --git a/components/gcm_driver/BUILD.gn b/components/gcm_driver/BUILD.gn index 2a549fa8..4b61384 100644 --- a/components/gcm_driver/BUILD.gn +++ b/components/gcm_driver/BUILD.gn
@@ -2,12 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") +import("//components/gcm_driver/config.gni") + +buildflag_header("gcm_build_features") { + header = "gcm_build_features.h" + flags = [ "USE_GCM_FROM_PLATFORM=$use_gcm_from_platform" ] +} + static_library("gcm_driver") { sources = [ - "android/component_jni_registrar.cc", - "android/component_jni_registrar.h", - "gcm_account_mapper.cc", - "gcm_account_mapper.h", "gcm_account_tracker.cc", "gcm_account_tracker.h", "gcm_activity.cc", @@ -16,40 +20,22 @@ "gcm_app_handler.h", "gcm_backoff_policy.cc", "gcm_backoff_policy.h", - "gcm_channel_status_request.cc", - "gcm_channel_status_request.h", - "gcm_channel_status_syncer.cc", - "gcm_channel_status_syncer.h", "gcm_client.cc", "gcm_client.h", - "gcm_client_factory.cc", - "gcm_client_factory.h", - "gcm_client_impl.cc", - "gcm_client_impl.h", "gcm_connection_observer.cc", "gcm_connection_observer.h", "gcm_delayed_task_controller.cc", "gcm_delayed_task_controller.h", - "gcm_desktop_utils.cc", - "gcm_desktop_utils.h", "gcm_driver.cc", "gcm_driver.h", - "gcm_driver_android.cc", - "gcm_driver_android.h", "gcm_driver_constants.cc", "gcm_driver_constants.h", - "gcm_driver_desktop.cc", - "gcm_driver_desktop.h", "gcm_internals_constants.cc", "gcm_internals_constants.h", "gcm_internals_helper.cc", "gcm_internals_helper.h", "gcm_profile_service.cc", "gcm_profile_service.h", - "gcm_stats_recorder_android.cc", - "gcm_stats_recorder_android.h", - "gcm_stats_recorder_impl.cc", - "gcm_stats_recorder_impl.h", "registration_info.cc", "registration_info.h", "system_encryptor.cc", @@ -63,6 +49,7 @@ "//components/gcm_driver/instance_id", ] deps = [ + ":gcm_build_features", "//base:i18n", "//components/crx_file", "//components/data_use_measurement/core", @@ -90,8 +77,17 @@ deps += [ "//components/timers" ] } - if (is_android) { - sources -= [ + if (use_gcm_from_platform) { + sources += [ + "android/component_jni_registrar.cc", + "android/component_jni_registrar.h", + "gcm_driver_android.cc", + "gcm_driver_android.h", + "gcm_stats_recorder_android.cc", + "gcm_stats_recorder_android.h", + ] + } else { + sources += [ "gcm_account_mapper.cc", "gcm_account_mapper.h", "gcm_channel_status_request.cc", @@ -109,10 +105,13 @@ "gcm_stats_recorder_impl.cc", "gcm_stats_recorder_impl.h", ] - deps -= [ + deps += [ "//components/crx_file", "//google_apis/gcm", ] + } + + if (is_android) { deps += [ "android:jni_headers" ] } } @@ -122,10 +121,6 @@ sources = [ "fake_gcm_app_handler.cc", "fake_gcm_app_handler.h", - "fake_gcm_client.cc", - "fake_gcm_client.h", - "fake_gcm_client_factory.cc", - "fake_gcm_client_factory.h", "fake_gcm_driver.cc", "fake_gcm_driver.h", ] @@ -140,14 +135,14 @@ "//testing/gtest", ] - if (is_android) { - sources -= [ + if (!use_gcm_from_platform) { + sources += [ "fake_gcm_client.cc", "fake_gcm_client.h", "fake_gcm_client_factory.cc", "fake_gcm_client_factory.h", ] - deps -= [ "//google_apis/gcm:test_support" ] + deps += [ "//google_apis/gcm:test_support" ] } } @@ -155,14 +150,9 @@ testonly = true sources = [ - "gcm_account_mapper_unittest.cc", "gcm_account_tracker_unittest.cc", - "gcm_channel_status_request_unittest.cc", - "gcm_client_impl_unittest.cc", "gcm_delayed_task_controller_unittest.cc", - "gcm_driver_desktop_unittest.cc", "gcm_stats_recorder_android_unittest.cc", - "gcm_stats_recorder_impl_unittest.cc", ] deps = [ @@ -180,8 +170,8 @@ "//third_party/protobuf:protobuf_lite", ] - if (is_android) { - sources -= [ + if (!use_gcm_from_platform) { + sources += [ "gcm_account_mapper_unittest.cc", "gcm_channel_status_request_unittest.cc", "gcm_client_impl_unittest.cc",
diff --git a/components/gcm_driver/config.gni b/components/gcm_driver/config.gni new file mode 100644 index 0000000..9620f1a --- /dev/null +++ b/components/gcm_driver/config.gni
@@ -0,0 +1,9 @@ +# 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. + +declare_args() { + # Use native GCM driver for all non-Android builds. On Android, the platform + # includes GMS which provides the GCM client. + use_gcm_from_platform = is_android +}
diff --git a/components/gcm_driver/gcm_profile_service.cc b/components/gcm_driver/gcm_profile_service.cc index c113aa2..5a2c7f0 100644 --- a/components/gcm_driver/gcm_profile_service.cc +++ b/components/gcm_driver/gcm_profile_service.cc
@@ -15,7 +15,7 @@ #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) #include "base/sequenced_task_runner.h" #include "base/threading/sequenced_worker_pool.h" #include "components/gcm_driver/gcm_driver_android.h" @@ -36,7 +36,7 @@ namespace gcm { -#if !defined(OS_ANDROID) +#if !BUILDFLAG(USE_GCM_FROM_PLATFORM) // Identity observer only has actual work to do when the user is actually signed // in. It ensures that account tracker is taking class GCMProfileService::IdentityObserver : public IdentityProvider::Observer { @@ -117,18 +117,18 @@ gcm_account_tracker_->Start(); } -#endif // !defined(OS_ANDROID) +#endif // !BUILDFLAG(USE_GCM_FROM_PLATFORM) // static bool GCMProfileService::IsGCMEnabled(PrefService* prefs) { -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) return true; #else return prefs->GetBoolean(gcm::prefs::kGCMChannelStatus); -#endif // defined(OS_ANDROID) +#endif // BUILDFLAG(USE_GCM_FROM_PLATFORM) } -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) GCMProfileService::GCMProfileService( base::FilePath path, scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner) { @@ -158,16 +158,16 @@ identity_observer_.reset(new IdentityObserver( profile_identity_provider_.get(), request_context_, driver_.get())); } -#endif // defined(OS_ANDROID) +#endif // BUILDFLAG(USE_GCM_FROM_PLATFORM) GCMProfileService::GCMProfileService() {} GCMProfileService::~GCMProfileService() {} void GCMProfileService::Shutdown() { -#if !defined(OS_ANDROID) +#if !BUILDFLAG(USE_GCM_FROM_PLATFORM) identity_observer_.reset(); -#endif // !defined(OS_ANDROID) +#endif // !BUILDFLAG(USE_GCM_FROM_PLATFORM) if (driver_) { driver_->Shutdown(); driver_.reset(); @@ -176,12 +176,12 @@ void GCMProfileService::SetDriverForTesting(GCMDriver* driver) { driver_.reset(driver); -#if !defined(OS_ANDROID) +#if !BUILDFLAG(USE_GCM_FROM_PLATFORM) if (identity_observer_) { identity_observer_.reset(new IdentityObserver( profile_identity_provider_.get(), request_context_, driver)); } -#endif // !defined(OS_ANDROID) +#endif // !BUILDFLAG(USE_GCM_FROM_PLATFORM) } } // namespace gcm
diff --git a/components/gcm_driver/gcm_profile_service.h b/components/gcm_driver/gcm_profile_service.h index b3305b6..4886b4e 100644 --- a/components/gcm_driver/gcm_profile_service.h +++ b/components/gcm_driver/gcm_profile_service.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" +#include "components/gcm_driver/gcm_build_features.h" #include "components/keyed_service/core/keyed_service.h" #include "components/signin/core/browser/profile_identity_provider.h" #include "components/version_info/version_info.h" @@ -36,7 +37,7 @@ // Providing GCM service, via GCMDriver. class GCMProfileService : public KeyedService { public: -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) GCMProfileService( base::FilePath path, scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner); @@ -74,7 +75,7 @@ std::unique_ptr<ProfileIdentityProvider> profile_identity_provider_; std::unique_ptr<GCMDriver> driver_; -#if !defined(OS_ANDROID) +#if !BUILDFLAG(USE_GCM_FROM_PLATFORM) net::URLRequestContextGetter* request_context_ = nullptr; // Used for both account tracker and GCM.UserSignedIn UMA.
diff --git a/components/gcm_driver/instance_id/BUILD.gn b/components/gcm_driver/instance_id/BUILD.gn index b77c034..ad09767 100644 --- a/components/gcm_driver/instance_id/BUILD.gn +++ b/components/gcm_driver/instance_id/BUILD.gn
@@ -2,10 +2,10 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//components/gcm_driver/config.gni") + static_library("instance_id") { sources = [ - "android/component_jni_registrar.cc", - "android/component_jni_registrar.h", "instance_id.cc", "instance_id.h", "instance_id_driver.cc", @@ -19,12 +19,14 @@ "//crypto", ] - if (is_android) { + if (use_gcm_from_platform) { sources -= [ "instance_id_impl.cc", "instance_id_impl.h", ] sources += [ + "android/component_jni_registrar.cc", + "android/component_jni_registrar.h", "instance_id_android.cc", "instance_id_android.h", ] @@ -65,6 +67,7 @@ ":instance_id", ":test_support", "//base", + "//components/gcm_driver:gcm_build_features", "//google_apis/gcm", "//net:test_support", "//testing/gtest",
diff --git a/components/gcm_driver/instance_id/instance_id_driver_unittest.cc b/components/gcm_driver/instance_id/instance_id_driver_unittest.cc index b8c663fe..86f275e1 100644 --- a/components/gcm_driver/instance_id/instance_id_driver_unittest.cc +++ b/components/gcm_driver/instance_id/instance_id_driver_unittest.cc
@@ -13,14 +13,15 @@ #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/test/scoped_task_environment.h" +#include "components/gcm_driver/gcm_build_features.h" #include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h" #include "components/gcm_driver/instance_id/instance_id.h" #include "testing/gtest/include/gtest/gtest.h" -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) #include "components/gcm_driver/instance_id/instance_id_android.h" #include "components/gcm_driver/instance_id/scoped_use_fake_instance_id_android.h" -#endif // OS_ANDROID +#endif // BUILDFLAG(USE_GCM_FROM_PLATFORM) namespace instance_id { @@ -91,10 +92,10 @@ std::unique_ptr<FakeGCMDriverForInstanceID> gcm_driver_; std::unique_ptr<InstanceIDDriver> driver_; -#if defined(OS_ANDROID) +#if BUILDFLAG(USE_GCM_FROM_PLATFORM) InstanceIDAndroid::ScopedBlockOnAsyncTasksForTesting block_async_; ScopedUseFakeInstanceIDAndroid use_fake_; -#endif // OS_ANDROID +#endif // BUILDFLAG(USE_GCM_FROM_PLATFORM) std::string id_; base::Time creation_time_;
diff --git a/components/metrics/file_metrics_provider_unittest.cc b/components/metrics/file_metrics_provider_unittest.cc index 2b6fbdb..42e38bc7 100644 --- a/components/metrics/file_metrics_provider_unittest.cc +++ b/components/metrics/file_metrics_provider_unittest.cc
@@ -496,7 +496,7 @@ PersistentSystemProfile persistent_profile; persistent_profile.RegisterPersistentAllocator( allocator->memory_allocator()); - persistent_profile.SetSystemProfile(profile_proto); + persistent_profile.SetSystemProfile(profile_proto, true); }); // Register the file and allow the "checker" task to run. @@ -567,7 +567,7 @@ PersistentSystemProfile persistent_profile; persistent_profile.RegisterPersistentAllocator( allocator->memory_allocator()); - persistent_profile.SetSystemProfile(profile_proto); + persistent_profile.SetSystemProfile(profile_proto, true); }); // Register the file and allow the "checker" task to run.
diff --git a/components/metrics/metrics_log.cc b/components/metrics/metrics_log.cc index 4d3123c..ba570a7 100644 --- a/components/metrics/metrics_log.cc +++ b/components/metrics/metrics_log.cc
@@ -123,7 +123,12 @@ if (product != uma_proto_.product()) uma_proto_.set_product(product); - RecordCoreSystemProfile(client_, uma_proto_.mutable_system_profile()); + SystemProfileProto* system_profile = uma_proto()->mutable_system_profile(); + RecordCoreSystemProfile(client_, system_profile); + if (log_type_ == ONGOING_LOG) { + GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( + *system_profile, /*complete=*/false); + } } MetricsLog::~MetricsLog() { @@ -338,8 +343,10 @@ std::string serialized_proto = recorder.SerializeAndRecordEnvironmentToPrefs(*system_profile); - GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( - serialized_proto); + if (log_type_ == ONGOING_LOG) { + GlobalPersistentSystemProfile::GetInstance()->SetSystemProfile( + serialized_proto, /*complete=*/true); + } return serialized_proto; }
diff --git a/components/metrics/metrics_switches.cc b/components/metrics/metrics_switches.cc index 1aef619..f380ff8e 100644 --- a/components/metrics/metrics_switches.cc +++ b/components/metrics/metrics_switches.cc
@@ -7,6 +7,13 @@ namespace metrics { namespace switches { +// Enables the recording of metrics reports but disables reporting. In contrast +// to kDisableMetrics, this executes all the code that a normal client would +// use for reporting, except the report is dropped rather than sent to the +// server. This is useful for finding issues in the metrics code during UI and +// performance tests. +const char kMetricsRecordingOnly[] = "metrics-recording-only"; + // Forces a reset of the one-time-randomized FieldTrials on this client, also // known as the Chrome Variations state. const char kResetVariationState[] = "reset-variation-state";
diff --git a/components/metrics/metrics_switches.h b/components/metrics/metrics_switches.h index b3fe7fd9..bfdf414 100644 --- a/components/metrics/metrics_switches.h +++ b/components/metrics/metrics_switches.h
@@ -10,6 +10,8 @@ // Alphabetical list of switches specific to the metrics component. Document // each in the .cc file. + +extern const char kMetricsRecordingOnly[]; extern const char kResetVariationState[]; } // namespace switches
diff --git a/components/metrics/persistent_system_profile.cc b/components/metrics/persistent_system_profile.cc index dc4e7eb..88b2a76 100644 --- a/components/metrics/persistent_system_profile.cc +++ b/components/metrics/persistent_system_profile.cc
@@ -46,6 +46,7 @@ base::PersistentMemoryAllocator* memory_allocator, size_t min_size) : allocator_(memory_allocator), + has_complete_profile_(false), alloc_reference_(0), alloc_size_(0), end_offset_(0) { @@ -75,6 +76,7 @@ } // Reset member variables. + has_complete_profile_ = false; alloc_reference_ = 0; alloc_size_ = 0; end_offset_ = 0; @@ -264,6 +266,7 @@ // block is reserved now. RecordAllocator allocator(memory_allocator, 1); allocators_.push_back(std::move(allocator)); + all_have_complete_profile_ = false; } void PersistentSystemProfile::DeregisterPersistentAllocator( @@ -278,26 +281,42 @@ } void PersistentSystemProfile::SetSystemProfile( - const std::string& serialized_profile) { + const std::string& serialized_profile, + bool complete) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (allocators_.empty() || serialized_profile.empty()) return; for (auto& allocator : allocators_) { + // Don't overwrite a complete profile with an incomplete one. + if (!complete && allocator.has_complete_profile()) + continue; // A full system profile always starts fresh. allocator.Reset(); // Write out the serialized profile. allocator.Write(kSystemProfileProto, serialized_profile); + // Indicate if this is a complete profile. + if (complete) + allocator.set_complete_profile(); } + + if (complete) + all_have_complete_profile_ = true; } void PersistentSystemProfile::SetSystemProfile( - const SystemProfileProto& profile) { + const SystemProfileProto& profile, + bool complete) { + // Avoid serialization if passed profile is not complete and all allocators + // already have complete ones. + if (!complete && all_have_complete_profile_) + return; + std::string serialized_profile; if (!profile.SerializeToString(&serialized_profile)) return; - SetSystemProfile(serialized_profile); + SetSystemProfile(serialized_profile, complete); } // static
diff --git a/components/metrics/persistent_system_profile.h b/components/metrics/persistent_system_profile.h index 1775dde..2f687811 100644 --- a/components/metrics/persistent_system_profile.h +++ b/components/metrics/persistent_system_profile.h
@@ -31,9 +31,12 @@ base::PersistentMemoryAllocator* memory_allocator); // Stores a complete system profile. Use the version taking the serialized - // version if available to avoid multiple serialization actions. - void SetSystemProfile(const std::string& serialized_profile); - void SetSystemProfile(const SystemProfileProto& profile); + // version if available to avoid multiple serialization actions. The + // |complete| flag indicates that this profile contains all known information + // and can replace whatever exists. If the flag is false, the profile will be + // stored only if there is nothing else already present. + void SetSystemProfile(const std::string& serialized_profile, bool complete); + void SetSystemProfile(const SystemProfileProto& profile, bool complete); // Tests if a persistent memory allocator contains an system profile. static bool HasSystemProfile( @@ -76,6 +79,9 @@ base::PersistentMemoryAllocator* allocator() { return allocator_; } + bool has_complete_profile() { return has_complete_profile_; } + void set_complete_profile() { has_complete_profile_ = true; } + private: // Advance to the next record segment in the memory allocator. bool NextSegment() const; @@ -97,6 +103,9 @@ // This never changes but can't be "const" because vector calls operator=(). base::PersistentMemoryAllocator* allocator_; // Storage location. + // Indicates if a complete profile has been stored. + bool has_complete_profile_; + // These change even though the underlying data may be "const". mutable uint32_t alloc_reference_; // Last storage block. mutable size_t alloc_size_; // Size of the block. @@ -109,6 +118,9 @@ // instances. std::vector<RecordAllocator> allocators_; + // Indicates if a complete profile has been stored to all allocators. + bool all_have_complete_profile_ = false; + THREAD_CHECKER(thread_checker_); DISALLOW_COPY_AND_ASSIGN(PersistentSystemProfile);
diff --git a/components/metrics/persistent_system_profile_unittest.cc b/components/metrics/persistent_system_profile_unittest.cc index 5ca4e898..a2e038a4 100644 --- a/components/metrics/persistent_system_profile_unittest.cc +++ b/components/metrics/persistent_system_profile_unittest.cc
@@ -91,7 +91,7 @@ trial->set_name_id(123); trial->set_group_id(456); - persistent_profile()->SetSystemProfile(proto1); + persistent_profile()->SetSystemProfile(proto1, false); SystemProfileProto proto2; ASSERT_TRUE(PersistentSystemProfile::HasSystemProfile(*memory_allocator())); @@ -107,7 +107,23 @@ trial->set_name_id(78); trial->set_group_id(90); - persistent_profile()->SetSystemProfile(proto1); + persistent_profile()->SetSystemProfile(proto1, true); + + ASSERT_TRUE( + PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2)); + ASSERT_EQ(2, proto2.field_trial_size()); + EXPECT_EQ(123U, proto2.field_trial(0).name_id()); + EXPECT_EQ(456U, proto2.field_trial(0).group_id()); + EXPECT_EQ(78U, proto2.field_trial(1).name_id()); + EXPECT_EQ(90U, proto2.field_trial(1).group_id()); + + // Check that the profile won't be overwritten by a new non-complete profile. + + trial = proto1.add_field_trial(); + trial->set_name_id(0xC0DE); + trial->set_group_id(0xFEED); + + persistent_profile()->SetSystemProfile(proto1, false); ASSERT_TRUE( PersistentSystemProfile::GetSystemProfile(*memory_allocator(), &proto2));
diff --git a/components/metrics_services_manager/metrics_services_manager.cc b/components/metrics_services_manager/metrics_services_manager.cc index 15bfccec..ef4c993 100644 --- a/components/metrics_services_manager/metrics_services_manager.cc +++ b/components/metrics_services_manager/metrics_services_manager.cc
@@ -6,10 +6,12 @@ #include <utility> +#include "base/command_line.h" #include "base/logging.h" #include "components/metrics/metrics_service.h" #include "components/metrics/metrics_service_client.h" #include "components/metrics/metrics_state_manager.h" +#include "components/metrics/metrics_switches.h" #include "components/metrics_services_manager/metrics_services_manager_client.h" #include "components/rappor/rappor_service_impl.h" #include "components/ukm/ukm_service.h" @@ -103,7 +105,8 @@ DCHECK(thread_checker_.CalledOnValidThread()); metrics::MetricsService* metrics = GetMetricsService(); - if (client_->OnlyDoMetricsRecording()) { + const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); + if (cmdline->HasSwitch(metrics::switches::kMetricsRecordingOnly)) { metrics->StartRecordingForTests(); GetRapporServiceImpl()->Update(true, false); return;
diff --git a/components/metrics_services_manager/metrics_services_manager_client.h b/components/metrics_services_manager/metrics_services_manager_client.h index afbd601..5d4e50dc 100644 --- a/components/metrics_services_manager/metrics_services_manager_client.h +++ b/components/metrics_services_manager/metrics_services_manager_client.h
@@ -51,9 +51,6 @@ // Returns whether metrics reporting is enabled. virtual bool IsMetricsReportingEnabled() = 0; - // Whether the metrics services should record but not report metrics. - virtual bool OnlyDoMetricsRecording() = 0; - // Update the running state of metrics services managed by the embedder, for // example, crash reporting. virtual void UpdateRunningServices(bool may_record, bool may_upload) {}
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc index 8fddcfba..94f9155 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_request.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_request.cc
@@ -56,18 +56,19 @@ void GeneratePageBundleRequest::OnCompleted(PrefetchRequestStatus status, const std::string& data) { if (status != PrefetchRequestStatus::SUCCESS) { - callback_.Run(status, std::vector<RenderPageInfo>()); + callback_.Run(status, std::string(), std::vector<RenderPageInfo>()); return; } std::vector<RenderPageInfo> pages; - if (!ParseOperationResponse(data, &pages)) { + std::string operation_name = ParseOperationResponse(data, &pages); + if (operation_name.empty()) { callback_.Run(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, - std::vector<RenderPageInfo>()); + std::string(), std::vector<RenderPageInfo>()); return; } - callback_.Run(PrefetchRequestStatus::SUCCESS, pages); + callback_.Run(PrefetchRequestStatus::SUCCESS, operation_name, pages); } } // offline_pages
diff --git a/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc index 19a313b..17e478a 100644 --- a/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc +++ b/components/offline_pages/core/prefetch/generate_page_bundle_request_unittest.cc
@@ -77,12 +77,15 @@ CreateRequest(callback.Get())); PrefetchRequestStatus status; + std::string operation_name; std::vector<RenderPageInfo> pages; - EXPECT_CALL(callback, Run(_, _)) - .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages))); + EXPECT_CALL(callback, Run(_, _, _)) + .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&operation_name), + SaveArg<2>(&pages))); RespondWithData(""); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, status); + EXPECT_TRUE(operation_name.empty()); EXPECT_TRUE(pages.empty()); } @@ -92,12 +95,15 @@ CreateRequest(callback.Get())); PrefetchRequestStatus status; + std::string operation_name; std::vector<RenderPageInfo> pages; - EXPECT_CALL(callback, Run(_, _)) - .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages))); + EXPECT_CALL(callback, Run(_, _, _)) + .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&operation_name), + SaveArg<2>(&pages))); RespondWithData("Some invalid data"); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, status); + EXPECT_TRUE(operation_name.empty()); EXPECT_TRUE(pages.empty()); }
diff --git a/components/offline_pages/core/prefetch/get_operation_request.cc b/components/offline_pages/core/prefetch/get_operation_request.cc index 59865ff..77d2cd2 100644 --- a/components/offline_pages/core/prefetch/get_operation_request.cc +++ b/components/offline_pages/core/prefetch/get_operation_request.cc
@@ -15,7 +15,7 @@ namespace offline_pages { namespace { -const char kGetOperationURLPath[] = "v1/operations/"; +const char kGetOperationURLPath[] = "v1/"; } // namespace GetOperationRequest::GetOperationRequest( @@ -38,18 +38,19 @@ void GetOperationRequest::OnCompleted(PrefetchRequestStatus status, const std::string& data) { if (status != PrefetchRequestStatus::SUCCESS) { - callback_.Run(status, std::vector<RenderPageInfo>()); + callback_.Run(status, std::string(), std::vector<RenderPageInfo>()); return; } std::vector<RenderPageInfo> pages; - if (!ParseOperationResponse(data, &pages)) { + std::string operation_name = ParseOperationResponse(data, &pages); + if (operation_name.empty()) { callback_.Run(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, - std::vector<RenderPageInfo>()); + std::string(), std::vector<RenderPageInfo>()); return; } - callback_.Run(PrefetchRequestStatus::SUCCESS, pages); + callback_.Run(PrefetchRequestStatus::SUCCESS, operation_name, pages); } } // offline_pages
diff --git a/components/offline_pages/core/prefetch/get_operation_request_unittest.cc b/components/offline_pages/core/prefetch/get_operation_request_unittest.cc index b104888..45f2717 100644 --- a/components/offline_pages/core/prefetch/get_operation_request_unittest.cc +++ b/components/offline_pages/core/prefetch/get_operation_request_unittest.cc
@@ -63,12 +63,15 @@ std::unique_ptr<GetOperationRequest> request(CreateRequest(callback.Get())); PrefetchRequestStatus status; + std::string operation_name; std::vector<RenderPageInfo> pages; - EXPECT_CALL(callback, Run(_, _)) - .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages))); + EXPECT_CALL(callback, Run(_, _, _)) + .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&operation_name), + SaveArg<2>(&pages))); RespondWithData(""); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, status); + EXPECT_TRUE(operation_name.empty()); EXPECT_TRUE(pages.empty()); } @@ -77,12 +80,15 @@ std::unique_ptr<GetOperationRequest> request(CreateRequest(callback.Get())); PrefetchRequestStatus status; + std::string operation_name; std::vector<RenderPageInfo> pages; - EXPECT_CALL(callback, Run(_, _)) - .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages))); + EXPECT_CALL(callback, Run(_, _, _)) + .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&operation_name), + SaveArg<2>(&pages))); RespondWithData("Some invalid data"); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, status); + EXPECT_TRUE(operation_name.empty()); EXPECT_TRUE(pages.empty()); }
diff --git a/components/offline_pages/core/prefetch/prefetch_proto_utils.cc b/components/offline_pages/core/prefetch/prefetch_proto_utils.cc index 0fe5040..0fcdfb7 100644 --- a/components/offline_pages/core/prefetch/prefetch_proto_utils.cc +++ b/components/offline_pages/core/prefetch/prefetch_proto_utils.cc
@@ -123,18 +123,19 @@ } // namespace -bool ParseOperationResponse(const std::string& data, - std::vector<RenderPageInfo>* pages) { +std::string ParseOperationResponse(const std::string& data, + std::vector<RenderPageInfo>* pages) { proto::Operation operation; if (!operation.ParseFromString(data)) { DVLOG(1) << "Failed to parse operation"; - return false; + return std::string(); } - if (operation.done()) - return ParseDoneOperationResponse(operation, pages); - else - return ParsePendingOperationResponse(operation, pages); + std::string name = operation.name(); + bool success = operation.done() + ? ParseDoneOperationResponse(operation, pages) + : ParsePendingOperationResponse(operation, pages); + return success ? name : std::string(); } } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_proto_utils.h b/components/offline_pages/core/prefetch/prefetch_proto_utils.h index cc77de1..92813af 100644 --- a/components/offline_pages/core/prefetch/prefetch_proto_utils.h +++ b/components/offline_pages/core/prefetch/prefetch_proto_utils.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_PROTO_UTILS_H_ #define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_PREFETCH_PROTO_UTILS_H_ +#include <string> #include <vector> #include "components/offline_pages/core/prefetch/prefetch_types.h" @@ -13,9 +14,10 @@ // The fully qualified type name for PageBundle defined in proto. extern const char kPageBundleTypeURL[]; -// Used to parse the Operation serialized in binary proto |data|. -bool ParseOperationResponse(const std::string& data, - std::vector<RenderPageInfo>* pages); +// Parse the Operation serialized in binary proto |data|. Returns the operation +// name if parsing succeeded. Otherwise, empty string is returned. +std::string ParseOperationResponse(const std::string& data, + std::vector<RenderPageInfo>* pages); } // namespace offline_pages
diff --git a/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc b/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc index cd59945..3df538c 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_request_operation_response_unittest.cc
@@ -24,6 +24,7 @@ namespace { const version_info::Channel kTestChannel = version_info::Channel::UNKNOWN; +const char kTestOperationName[] = "operation/test123"; const char kTestURL[] = "http://example.com"; const char kTestURL2[] = "http://example.com/2"; const char kTestURL3[] = "http://example.com/3"; @@ -101,6 +102,7 @@ const std::string& any_type_url, const std::string& any_value) { proto::Operation operation; + operation.set_name(kTestOperationName); operation.set_done(is_done); if (error_code != proto::OK) { operation.mutable_error()->set_code(error_code); @@ -234,6 +236,7 @@ builder_.BuildFromAny(kPageBundleTypeURL, bundle_data)); } + const std::string& operation_name() const { return operation_name_; } const std::vector<RenderPageInfo>& pages() const { return pages_; } private: @@ -242,14 +245,17 @@ builder_.CreateRequest(request_context(), callback.Get()); PrefetchRequestStatus status; + operation_name_.clear(); pages_.clear(); - EXPECT_CALL(callback, Run(_, _)) - .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&pages_))); + EXPECT_CALL(callback, Run(_, _, _)) + .WillOnce(DoAll(SaveArg<0>(&status), SaveArg<1>(&operation_name_), + SaveArg<2>(&pages_))); RespondWithData(response_data); return status; } T builder_; + std::string operation_name_; std::vector<RenderPageInfo> pages_; }; @@ -266,24 +272,28 @@ // No error is set for OK. Thus this will cause the operation // being filled with only done flag. this->SendWithErrorResponse(proto::OK, "")); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } TYPED_TEST(PrefetchRequestOperationResponseTest, ErrorValue) { EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithErrorResponse(proto::UNKNOWN, kErrorMessage)); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } TYPED_TEST(PrefetchRequestOperationResponseTest, InvalidTypeUrl) { EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithAnyResponse("foo", "")); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } TYPED_TEST(PrefetchRequestOperationResponseTest, InvalidValue) { EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithAnyResponse(kPageBundleTypeURL, "foo")); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } @@ -291,6 +301,7 @@ proto::PageBundle bundle; EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithPageBundleResponse(bundle)); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } @@ -299,6 +310,7 @@ bundle.add_archives(); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithPageBundleResponse(bundle)); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } @@ -309,6 +321,7 @@ archive->set_body_length(kTestBodyLength); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithPageBundleResponse(bundle)); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } @@ -319,6 +332,7 @@ page_info->set_redirect_url(kTestURL); EXPECT_EQ(PrefetchRequestStatus::SHOULD_RETRY_WITH_BACKOFF, this->SendWithPageBundleResponse(bundle)); + EXPECT_TRUE(this->operation_name().empty()); EXPECT_TRUE(this->pages().empty()); } @@ -338,6 +352,7 @@ 1000000); EXPECT_EQ(PrefetchRequestStatus::SUCCESS, this->SendWithPageBundleResponse(bundle)); + EXPECT_EQ(kTestOperationName, this->operation_name()); ASSERT_EQ(1u, this->pages().size()); EXPECT_EQ(kTestURL, this->pages().back().url); EXPECT_EQ(kTestURL2, this->pages().back().redirect_url); @@ -383,6 +398,7 @@ EXPECT_EQ(PrefetchRequestStatus::SUCCESS, this->SendWithPageBundleResponse(bundle)); + EXPECT_EQ(kTestOperationName, this->operation_name()); ASSERT_EQ(4u, this->pages().size()); EXPECT_EQ(kTestURL, this->pages().at(0).url); EXPECT_EQ(RenderStatus::PENDING, this->pages().at(0).status);
diff --git a/components/offline_pages/core/prefetch/prefetch_types.h b/components/offline_pages/core/prefetch/prefetch_types.h index 80208f0a..8fb4bbe4 100644 --- a/components/offline_pages/core/prefetch/prefetch_types.h +++ b/components/offline_pages/core/prefetch/prefetch_types.h
@@ -106,6 +106,7 @@ // Callback invoked upon completion of a prefetch request. using PrefetchRequestFinishedCallback = base::Callback<void(PrefetchRequestStatus status, + const std::string& operation_name, const std::vector<RenderPageInfo>& pages)>; // Holds information about a new URL to be prefetched.
diff --git a/components/safe_browsing/common/safebrowsing_constants.cc b/components/safe_browsing/common/safebrowsing_constants.cc index 22e6de0..65c2b54 100644 --- a/components/safe_browsing/common/safebrowsing_constants.cc +++ b/components/safe_browsing/common/safebrowsing_constants.cc
@@ -13,4 +13,23 @@ const base::FilePath::CharType kChannelIDFile[] = FILE_PATH_LITERAL(" Channel IDs"); +// The default URL prefix where browser fetches chunk updates, hashes, +// and reports safe browsing hits and malware details. +const char kSbDefaultURLPrefix[] = + "https://safebrowsing.google.com/safebrowsing"; + +// The backup URL prefix used when there are issues establishing a connection +// with the server at the primary URL. +const char kSbBackupConnectErrorURLPrefix[] = + "https://alt1-safebrowsing.google.com/safebrowsing"; + +// The backup URL prefix used when there are HTTP-specific issues with the +// server at the primary URL. +const char kSbBackupHttpErrorURLPrefix[] = + "https://alt2-safebrowsing.google.com/safebrowsing"; + +// The backup URL prefix used when there are local network specific issues. +const char kSbBackupNetworkErrorURLPrefix[] = + "https://alt3-safebrowsing.google.com/safebrowsing"; + } // namespace safe_browsing
diff --git a/components/safe_browsing/common/safebrowsing_constants.h b/components/safe_browsing/common/safebrowsing_constants.h index e6776b5..598352e3 100644 --- a/components/safe_browsing/common/safebrowsing_constants.h +++ b/components/safe_browsing/common/safebrowsing_constants.h
@@ -14,6 +14,21 @@ // Filename suffix for the cookie database. extern const base::FilePath::CharType kCookiesFile[]; extern const base::FilePath::CharType kChannelIDFile[]; + +// The default URL prefix where browser fetches chunk updates, hashes, +// and reports safe browsing hits and malware details. +extern const char kSbDefaultURLPrefix[]; + +// The backup URL prefix used when there are issues establishing a connection +// with the server at the primary URL. +extern const char kSbBackupConnectErrorURLPrefix[]; + +// The backup URL prefix used when there are HTTP-specific issues with the +// server at the primary URL. +extern const char kSbBackupHttpErrorURLPrefix[]; + +// The backup URL prefix used when there are local network specific issues. +extern const char kSbBackupNetworkErrorURLPrefix[]; } #endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_CONSTANTS_H_
diff --git a/components/security_state/content/content_utils.cc b/components/security_state/content/content_utils.cc index 27986e0..f1dc115 100644 --- a/components/security_state/content/content_utils.cc +++ b/components/security_state/content/content_utils.cc
@@ -182,16 +182,23 @@ const blink::WebSecurityStyle security_style = SecurityLevelToSecurityStyle(security_info.security_level); - // The HTTP_SHOW_WARNING state may occur if the page is served as a data: URI - // or if it is served non-securely AND contains a sensitive form field. - if (security_info.security_level == security_state::HTTP_SHOW_WARNING && - (security_info.displayed_password_field_on_http || - security_info.displayed_credit_card_field_on_http)) { - security_style_explanations->neutral_explanations.push_back( - content::SecurityStyleExplanation( - l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), - l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION))); + if (security_info.security_level == security_state::HTTP_SHOW_WARNING) { + if (security_info.displayed_password_field_on_http || + security_info.displayed_credit_card_field_on_http) { + security_style_explanations->neutral_explanations.push_back( + content::SecurityStyleExplanation( + l10n_util::GetStringUTF8(IDS_PRIVATE_USER_DATA_INPUT), + l10n_util::GetStringUTF8( + IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION))); + } + if (security_info.incognito_downgraded_security_level) { + security_style_explanations->neutral_explanations.push_back( + content::SecurityStyleExplanation( + l10n_util::GetStringUTF8(IDS_INCOGNITO_NONSECURE), + l10n_util::GetStringUTF8(IDS_INCOGNITO_NONSECURE_DESCRIPTION))); + } } + security_style_explanations->ran_insecure_content_style = SecurityLevelToSecurityStyle(security_state::kRanInsecureContentLevel); security_style_explanations->displayed_insecure_content_style =
diff --git a/components/security_state/content/content_utils_unittest.cc b/components/security_state/content/content_utils_unittest.cc index e0e37e0..090a835 100644 --- a/components/security_state/content/content_utils_unittest.cc +++ b/components/security_state/content/content_utils_unittest.cc
@@ -4,6 +4,8 @@ #include "components/security_state/content/content_utils.h" +#include <vector> + #include "base/command_line.h" #include "base/test/histogram_tester.h" #include "components/security_state/core/security_state.h" @@ -253,6 +255,15 @@ EXPECT_EQ(blink::kWebSecurityStyleNeutral, security_style); // Verify only one explanation was shown when Form Not Secure is triggered. EXPECT_EQ(1u, explanations.neutral_explanations.size()); + + // Verify that two explanations are shown when the Incognito and + // FormNotSecure flags are both set. + explanations.neutral_explanations.clear(); + security_info.displayed_credit_card_field_on_http = true; + security_info.incognito_downgraded_security_level = true; + security_style = GetSecurityStyle(security_info, &explanations); + EXPECT_EQ(blink::kWebSecurityStyleNeutral, security_style); + EXPECT_EQ(2u, explanations.neutral_explanations.size()); } // Tests that an explanation is provided if a certificate is missing a
diff --git a/components/security_state/core/security_state.cc b/components/security_state/core/security_state.cc index a958bf3..1456374 100644 --- a/components/security_state/core/security_state.cc +++ b/components/security_state/core/security_state.cc
@@ -5,6 +5,7 @@ #include "components/security_state/core/security_state.h" #include <stdint.h> +#include <string> #include "base/command_line.h" #include "base/metrics/field_trial.h" @@ -30,22 +31,42 @@ }; // If |switch_or_field_trial_group| corresponds to a valid -// MarkHttpAs group, sets |*level| and |*histogram_status| to the +// MarkHttpAs setting, sets |*level| and |*histogram_status| to the // appropriate values and returns true. Otherwise, returns false. bool GetSecurityLevelAndHistogramValueForNonSecureFieldTrial( std::string switch_or_field_trial_group, bool displayed_sensitive_input_on_http, + bool is_incognito, SecurityLevel* level, MarkHttpStatus* histogram_status) { - if (switch_or_field_trial_group != switches::kMarkHttpAsDangerous) - return false; - *level = DANGEROUS; - *histogram_status = NON_SECURE; - return true; + if (switch_or_field_trial_group == + switches::kMarkHttpAsNonSecureWhileIncognito) { + *histogram_status = NON_SECURE_WHILE_INCOGNITO; + *level = (is_incognito || displayed_sensitive_input_on_http) + ? security_state::HTTP_SHOW_WARNING + : NONE; + return true; + } + if (switch_or_field_trial_group == + switches::kMarkHttpAsNonSecureWhileIncognitoOrEditing) { + *histogram_status = NON_SECURE_WHILE_INCOGNITO_OR_EDITING; + *level = (is_incognito || displayed_sensitive_input_on_http) + ? security_state::HTTP_SHOW_WARNING + : NONE; + return true; + } + if (switch_or_field_trial_group == switches::kMarkHttpAsDangerous) { + *histogram_status = NON_SECURE; + *level = DANGEROUS; + return true; + } + + return false; } SecurityLevel GetSecurityLevelForNonSecureFieldTrial( - bool displayed_sensitive_input_on_http) { + bool displayed_sensitive_input_on_http, + bool is_incognito) { std::string choice = base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kMarkHttpAs); @@ -59,9 +80,11 @@ // If the command-line switch is set, then it takes precedence over // the field trial group. if (!GetSecurityLevelAndHistogramValueForNonSecureFieldTrial( - choice, displayed_sensitive_input_on_http, &level, &status)) { + choice, displayed_sensitive_input_on_http, is_incognito, &level, + &status)) { if (!GetSecurityLevelAndHistogramValueForNonSecureFieldTrial( - group, displayed_sensitive_input_on_http, &level, &status)) { + group, displayed_sensitive_input_on_http, is_incognito, &level, + &status)) { status = HTTP_SHOW_WARNING_ON_SENSITIVE_FIELDS; level = displayed_sensitive_input_on_http ? security_state::HTTP_SHOW_WARNING @@ -128,7 +151,8 @@ (url.IsStandard() || url.SchemeIs(url::kBlobScheme))) { return GetSecurityLevelForNonSecureFieldTrial( visible_security_state.displayed_password_field_on_http || - visible_security_state.displayed_credit_card_field_on_http); + visible_security_state.displayed_credit_card_field_on_http, + visible_security_state.is_incognito); } return NONE; } @@ -238,10 +262,37 @@ is_origin_secure_callback, security_info->sha1_in_chain, security_info->mixed_content_status, security_info->content_with_cert_errors_status); + + security_info->incognito_downgraded_security_level = + (visible_security_state.is_incognito && + security_info->security_level == HTTP_SHOW_WARNING && + security_state::IsHttpWarningForIncognitoEnabled()); } } // namespace +bool IsHttpWarningForIncognitoEnabled() { + std::string choice = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + switches::kMarkHttpAs); + std::string group = base::FieldTrialList::FindFullName("MarkNonSecureAs"); + SecurityLevel level = NONE; + MarkHttpStatus status; + + // If the command-line switch is set, then it takes precedence over + // the field trial group. + if (!GetSecurityLevelAndHistogramValueForNonSecureFieldTrial( + choice, false, true, &level, &status)) { + if (!GetSecurityLevelAndHistogramValueForNonSecureFieldTrial( + group, false, true, &level, &status)) { + return false; + } + } + + return (status == NON_SECURE_WHILE_INCOGNITO || + status == NON_SECURE_WHILE_INCOGNITO_OR_EDITING); +} + const base::Feature kHttpFormWarningFeature{"HttpFormWarning", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -261,7 +312,8 @@ displayed_password_field_on_http(false), displayed_credit_card_field_on_http(false), contained_mixed_form(false), - cert_missing_subject_alt_name(false) {} + cert_missing_subject_alt_name(false), + incognito_downgraded_security_level(false) {} SecurityInfo::~SecurityInfo() {} @@ -293,7 +345,8 @@ ran_content_with_cert_errors(false), pkp_bypassed(false), displayed_password_field_on_http(false), - displayed_credit_card_field_on_http(false) {} + displayed_credit_card_field_on_http(false), + is_incognito(false) {} VisibleSecurityState::~VisibleSecurityState() {} @@ -315,7 +368,8 @@ other.displayed_password_field_on_http && displayed_credit_card_field_on_http == other.displayed_credit_card_field_on_http && - contained_mixed_form == other.contained_mixed_form); + contained_mixed_form == other.contained_mixed_form && + is_incognito == other.is_incognito); } } // namespace security_state
diff --git a/components/security_state/core/security_state.h b/components/security_state/core/security_state.h index 4d1ec3f9..0e737f9 100644 --- a/components/security_state/core/security_state.h +++ b/components/security_state/core/security_state.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_SECURITY_STATE_SECURITY_STATE_H_ -#define COMPONENTS_SECURITY_STATE_SECURITY_STATE_H_ +#ifndef COMPONENTS_SECURITY_STATE_CORE_SECURITY_STATE_H_ +#define COMPONENTS_SECURITY_STATE_CORE_SECURITY_STATE_H_ #include <stdint.h> #include <memory> @@ -141,6 +141,9 @@ // True if the server's certificate does not contain a // subjectAltName extension with a domain name or IP address. bool cert_missing_subject_alt_name; + // True if the |security_level| was downgraded to HTTP_SHOW_WARNING because + // the page was loaded while Incognito. + bool incognito_downgraded_security_level; }; // Contains the security state relevant to computing the SecurityInfo @@ -181,6 +184,8 @@ bool displayed_password_field_on_http; // True if the page was an HTTP page that displayed a credit card field. bool displayed_credit_card_field_on_http; + // True if the page was displayed in an Incognito context. + bool is_incognito; }; // These security levels describe the treatment given to pages that @@ -209,6 +214,10 @@ // |kHttpFormWarningFeature| feature. bool IsHttpWarningInFormEnabled(); +// Returns true if the MarkHttpAs setting indicates that a warning +// should be shown for HTTP pages loaded while in Incognito mode. +bool IsHttpWarningForIncognitoEnabled(); + } // namespace security_state -#endif // COMPONENTS_SECURITY_STATE_SECURITY_STATE_H_ +#endif // COMPONENTS_SECURITY_STATE_CORE_SECURITY_STATE_H_
diff --git a/components/security_state/core/security_state_unittest.cc b/components/security_state/core/security_state_unittest.cc index 201a91d0..85df06e 100644 --- a/components/security_state/core/security_state_unittest.cc +++ b/components/security_state/core/security_state_unittest.cc
@@ -5,11 +5,14 @@ #include "components/security_state/core/security_state.h" #include <stdint.h> +#include <utility> #include "base/bind.h" #include "base/command_line.h" #include "base/memory/ptr_util.h" #include "base/test/histogram_tester.h" +#include "base/test/scoped_command_line.h" +#include "components/security_state/core/switches.h" #include "net/cert/x509_certificate.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_connection_status_flags.h" @@ -49,7 +52,8 @@ ran_mixed_content_(false), malicious_content_status_(MALICIOUS_CONTENT_STATUS_NONE), displayed_password_field_on_http_(false), - displayed_credit_card_field_on_http_(false) {} + displayed_credit_card_field_on_http_(false), + is_incognito_(false) {} virtual ~TestSecurityStateHelper() {} void SetCertificate(scoped_refptr<net::X509Certificate> cert) { @@ -85,6 +89,7 @@ bool displayed_credit_card_field_on_http) { displayed_credit_card_field_on_http_ = displayed_credit_card_field_on_http; } + void set_is_incognito(bool is_incognito) { is_incognito_ = is_incognito; } void SetUrl(const GURL& url) { url_ = url; } @@ -103,6 +108,7 @@ state->displayed_password_field_on_http = displayed_password_field_on_http_; state->displayed_credit_card_field_on_http = displayed_credit_card_field_on_http_; + state->is_incognito = is_incognito_; return state; } @@ -124,6 +130,7 @@ MaliciousContentStatus malicious_content_status_; bool displayed_password_field_on_http_; bool displayed_credit_card_field_on_http_; + bool is_incognito_; }; } // namespace @@ -353,6 +360,30 @@ } } +// Tests that |incognito_downgraded_security_level| is set only when the +// corresponding VisibleSecurityState flag is set and the HTTPBad Phase 2 +// experiment is enabled. +TEST(SecurityStateTest, IncognitoFlagPropagates) { + TestSecurityStateHelper helper; + helper.SetUrl(GURL(kHttpUrl)); + SecurityInfo security_info; + helper.GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + + helper.set_is_incognito(true); + helper.GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + { + // Enable the "non-secure-while-incognito" configuration. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + helper.GetSecurityInfo(&security_info); + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + } +} + // Tests that SSL.MarkHttpAsStatus histogram is updated when security state is // computed for a page. TEST(SecurityStateTest, MarkHttpAsStatusHistogram) { @@ -367,12 +398,70 @@ SecurityInfo security_info; histograms.ExpectTotalCount(kHistogramName, 0); helper.GetSecurityInfo(&security_info); - histograms.ExpectUniqueSample(kHistogramName, 2 /* HTTP_SHOW_WARNING */, 1); + histograms.ExpectUniqueSample( + kHistogramName, 2 /* HTTP_SHOW_WARNING_ON_SENSITIVE_FIELDS */, 1); // Ensure histogram recorded correctly even without a password input. helper.set_displayed_password_field_on_http(false); helper.GetSecurityInfo(&security_info); - histograms.ExpectUniqueSample(kHistogramName, 2 /* HTTP_SHOW_WARNING */, 2); + histograms.ExpectUniqueSample( + kHistogramName, 2 /* HTTP_SHOW_WARNING_ON_SENSITIVE_FIELDS */, 2); + + { + // Test the "non-secure-while-incognito" configuration. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognito); + + base::HistogramTester histograms; + TestSecurityStateHelper helper; + helper.SetUrl(GURL(kHttpUrl)); + + // Ensure histogram recorded correctly when the Incognito flag is present. + helper.set_is_incognito(true); + SecurityInfo security_info; + histograms.ExpectTotalCount(kHistogramName, 0); + helper.GetSecurityInfo(&security_info); + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + histograms.ExpectUniqueSample(kHistogramName, + 4 /* NON_SECURE_WHILE_INCOGNITO */, 1); + + // Ensure histogram recorded correctly even without the Incognito flag. + helper.set_is_incognito(false); + helper.GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + histograms.ExpectUniqueSample(kHistogramName, + 4 /* NON_SECURE_WHILE_INCOGNITO */, 2); + } + + { + // Test the "non-secure-while-incognito-or-editing" configuration. + base::test::ScopedCommandLine scoped_command_line; + scoped_command_line.GetProcessCommandLine()->AppendSwitchASCII( + security_state::switches::kMarkHttpAs, + security_state::switches::kMarkHttpAsNonSecureWhileIncognitoOrEditing); + + base::HistogramTester histograms; + TestSecurityStateHelper helper; + helper.SetUrl(GURL(kHttpUrl)); + + // Ensure histogram recorded correctly when the Incognito flag is present. + helper.set_is_incognito(true); + SecurityInfo security_info; + histograms.ExpectTotalCount(kHistogramName, 0); + helper.GetSecurityInfo(&security_info); + EXPECT_TRUE(security_info.incognito_downgraded_security_level); + histograms.ExpectUniqueSample( + kHistogramName, 5 /* NON_SECURE_WHILE_INCOGNITO_OR_EDITING */, 1); + + // Ensure histogram recorded correctly even without the Incognito flag. + helper.set_is_incognito(false); + helper.GetSecurityInfo(&security_info); + EXPECT_FALSE(security_info.incognito_downgraded_security_level); + histograms.ExpectUniqueSample( + kHistogramName, 5 /* NON_SECURE_WHILE_INCOGNITO_OR_EDITING */, 2); + } } TEST(SecurityStateTest, DetectSubjectAltName) {
diff --git a/components/security_state_strings.grdp b/components/security_state_strings.grdp index 1982f91..482b6c9 100644 --- a/components/security_state_strings.grdp +++ b/components/security_state_strings.grdp
@@ -7,6 +7,12 @@ <message name="IDS_PRIVATE_USER_DATA_INPUT_DESCRIPTION" desc="Description of a security problem where the site collects private user data on an insecure page, which results in an omnibox warning." translateable="false"> This page includes a password or credit card input over HTTP. A warning has been added to the URL bar. </message> + <message name="IDS_INCOGNITO_NONSECURE" desc="Summary phrase for a security problem where the site is non-secure (HTTP) and the user is browsing Incognito." translateable="false"> + Non-secure page loaded in incognito mode + </message> + <message name="IDS_INCOGNITO_NONSECURE_DESCRIPTION" desc="Description of a security problem where the site is non-secure (HTTP) and the user is browsing Incognito, which results in an omnibox warning." translateable="false"> + This page was loaded non-securely in an incognito window. A warning has been added to the URL bar. + </message> <message name="IDS_SAFEBROWSING_WARNING" desc="Summary phrase for a security problem where the site is deemed unsafe by the SafeBrowsing service." translateable="false"> This page is dangerous (flagged by Google Safe Browsing). </message>
diff --git a/components/sync/base/pref_names.cc b/components/sync/base/pref_names.cc index 940e3f89..4ebb41c6 100644 --- a/components/sync/base/pref_names.cc +++ b/components/sync/base/pref_names.cc
@@ -71,7 +71,7 @@ const char kSyncManaged[] = "sync.managed"; // Boolean to prevent sync from automatically starting up. This is -// used when sync is disabled by the user via the privacy dashboard. +// used when sync is disabled by the user in sync settings. const char kSyncSuppressStart[] = "sync.suppress_start"; // A string that can be used to restore sync encryption infrastructure on
diff --git a/components/typemaps.gni b/components/typemaps.gni index 94d94bac..f19028a 100644 --- a/components/typemaps.gni +++ b/components/typemaps.gni
@@ -4,6 +4,7 @@ typemaps = [ "//components/autofill/content/common/autofill_types.typemap", + "//components/chrome_cleaner/public/typemaps/chrome_prompt.typemap", "//components/content_settings/core/common/content_settings.typemap", "//components/nacl/common/nacl.typemap", "//components/password_manager/content/common/credential_manager.typemap",
diff --git a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc index d1e1448..743b061 100644 --- a/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc +++ b/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -146,6 +146,7 @@ const char* metric_name) { const ukm::TestUkmRecorder* ukm_recoder = test_browser_client_.GetTestUkmRecorder(); + size_t actual_event_count = 0; for (size_t i = 0; i < ukm_recoder->entries_count(); ++i) { const ukm::mojom::UkmEntry* entry = ukm_recoder->GetEntry(i); @@ -226,6 +227,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestWheelToFirstScrollHistograms) { const GURL url(kUrl); + size_t total_ukm_entry_count = 0; contents()->NavigateAndCommit(url); for (bool rendering_on_main : {false, true}) { ResetHistograms(); @@ -250,6 +252,10 @@ INPUT_EVENT_ACK_STATE_NOT_CONSUMED); tracker()->OnGpuSwapBuffersCompleted(wheel_latency); + // UKM metrics. + total_ukm_entry_count++; + EXPECT_TRUE(AssertUkmReported("Event.ScrollBegin.Wheel", + "TimeToScrollUpdateSwapBegin")); // Rappor metrics. EXPECT_TRUE( RapporSampleAssert("Event.Latency.ScrollUpdate.Touch." @@ -316,8 +322,8 @@ ukm::TestUkmRecorder* test_ukm_recorder = test_browser_client_.GetTestUkmRecorder(); - EXPECT_EQ(0U, test_ukm_recorder->sources_count()); - EXPECT_EQ(0U, test_ukm_recorder->entries_count()); + EXPECT_EQ(1U, test_ukm_recorder->sources_count()); + EXPECT_EQ(total_ukm_entry_count, test_ukm_recorder->entries_count()); } } } @@ -398,6 +404,7 @@ TEST_F(RenderWidgetHostLatencyTrackerTest, TestTouchToFirstScrollHistograms) { const GURL url(kUrl); contents()->NavigateAndCommit(url); + size_t total_ukm_entry_count = 0; for (bool rendering_on_main : {false, true}) { ResetHistograms(); { @@ -443,6 +450,10 @@ tracker()->OnGpuSwapBuffersCompleted(touch_latency); } + // UKM metrics. + total_ukm_entry_count++; + EXPECT_TRUE(AssertUkmReported("Event.ScrollBegin.Touch", + "TimeToScrollUpdateSwapBegin")); // Rappor metrics. EXPECT_TRUE( RapporSampleAssert("Event.Latency.ScrollUpdate.Touch." @@ -511,8 +522,8 @@ ukm::TestUkmRecorder* test_ukm_recorder = test_browser_client_.GetTestUkmRecorder(); - EXPECT_EQ(0U, test_ukm_recorder->sources_count()); - EXPECT_EQ(0U, test_ukm_recorder->entries_count()); + EXPECT_EQ(1U, test_ukm_recorder->sources_count()); + EXPECT_EQ(total_ukm_entry_count, test_ukm_recorder->entries_count()); } }
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index 9e91869..2c4c7000 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -151,6 +151,10 @@ return empty; } +base::FilePath ContentBrowserClient::GetLoggingFileName() { + return base::FilePath(); +} + bool ContentBrowserClient::AllowAppCache(const GURL& manifest_url, const GURL& first_party, ResourceContext* context) {
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index b39cd98..e2b1af4 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -320,6 +320,10 @@ // Returns the default favicon. The callee doesn't own the given bitmap. virtual const gfx::ImageSkia* GetDefaultFavicon(); + // Returns the fully qualified path to the log file name, or an empty path. + // This function is used by the sandbox to allow write access to the log. + virtual base::FilePath GetLoggingFileName(); + // Allow the embedder to control if an AppCache can be used for the given url. // This is called on the IO thread. virtual bool AllowAppCache(const GURL& manifest_url,
diff --git a/ios/chrome/browser/chrome_switches.cc b/ios/chrome/browser/chrome_switches.cc index 624df12..1c7fede 100644 --- a/ios/chrome/browser/chrome_switches.cc +++ b/ios/chrome/browser/chrome_switches.cc
@@ -98,13 +98,6 @@ // prefixed with the character "t" will be treated as Trigger Variation Ids. const char kIOSForceVariationIds[] = "force-variation-ids"; -// Enables the recording of metrics reports but disables reporting. In contrast -// to kDisableMetrics, this executes all the code that a normal client would -// use for reporting, except the report is dropped rather than sent to the -// server. This is useful for finding issues in the metrics code during UI and -// performance tests. -const char kIOSMetricsRecordingOnly[] = "metrics-recording-only"; - // A string used to override the default user agent with a custom one. const char kUserAgent[] = "user-agent";
diff --git a/ios/chrome/browser/chrome_switches.h b/ios/chrome/browser/chrome_switches.h index ae7b4fa..a862788 100644 --- a/ios/chrome/browser/chrome_switches.h +++ b/ios/chrome/browser/chrome_switches.h
@@ -38,7 +38,6 @@ extern const char kEnableSuggestionsUI[]; extern const char kIOSForceVariationIds[]; -extern const char kIOSMetricsRecordingOnly[]; extern const char kUserAgent[]; extern const char kIOSHostResolverRules[];
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h index 73478f5c..7aa390d 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.h
@@ -44,7 +44,6 @@ net::URLRequestContextGetter* GetURLRequestContext() override; bool IsMetricsReportingEnabled() override; - bool OnlyDoMetricsRecording() override; // Gets the MetricsStateManager, creating it if it has not already been // created.
diff --git a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm index 7c7340b..d45a42d0 100644 --- a/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm +++ b/ios/chrome/browser/metrics/ios_chrome_metrics_services_manager_client.mm
@@ -98,11 +98,6 @@ return enabled_state_provider_->IsReportingEnabled(); } -bool IOSChromeMetricsServicesManagerClient::OnlyDoMetricsRecording() { - const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - return cmdline->HasSwitch(switches::kIOSMetricsRecordingOnly); -} - metrics::MetricsStateManager* IOSChromeMetricsServicesManagerClient::GetMetricsStateManager() { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm b/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm index c4634660..4d79542 100644 --- a/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm +++ b/ios/chrome/browser/ssl/ios_security_state_tab_helper.mm
@@ -10,6 +10,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" #include "components/security_state/core/security_state.h" +#include "ios/web/public/browser_state.h" #include "ios/web/public/navigation_item.h" #import "ios/web/public/navigation_manager.h" #import "ios/web/public/origin_util.h" @@ -62,5 +63,7 @@ (ssl.content_status & web::SSLStatus::DISPLAYED_CREDIT_CARD_FIELD_ON_HTTP) ? true : false; + state->is_incognito = web_state_->GetBrowserState()->IsOffTheRecord(); + return state; }
diff --git a/ios/chrome/test/ocmock/BUILD.gn b/ios/chrome/test/ocmock/BUILD.gn index 6c079a2..cc3ebdf3 100644 --- a/ios/chrome/test/ocmock/BUILD.gn +++ b/ios/chrome/test/ocmock/BUILD.gn
@@ -3,6 +3,7 @@ # found in the LICENSE file. source_set("ocmock") { + configs += [ "//build/config/compiler:enable_arc" ] testonly = true sources = [ "OCMockObject+BreakpadControllerTesting.h",
diff --git a/ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.mm b/ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.mm index df3cc83..ba86516 100644 --- a/ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.mm +++ b/ios/chrome/test/ocmock/OCMockObject+BreakpadControllerTesting.mm
@@ -8,11 +8,15 @@ #include "testing/gtest/include/gtest/gtest.h" #import "third_party/ocmock/OCMock/OCMock.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + @implementation OCMockObject (BreakpadControllerTesting) - (void)cr_expectGetCrashReportCount:(int)crashReportCount { id invocationBlock = ^(NSInvocation* invocation) { - void (^block)(int); + __unsafe_unretained void (^block)(int); [invocation getArgument:&block atIndex:2]; if (!block) { ADD_FAILURE();
diff --git a/ios/testing/BUILD.gn b/ios/testing/BUILD.gn index e4b8ef8..ea12102 100644 --- a/ios/testing/BUILD.gn +++ b/ios/testing/BUILD.gn
@@ -46,6 +46,7 @@ } test("ocmock_support_unittest") { + configs += [ "//build/config/compiler:enable_arc" ] deps = [ ":ocmock_support", "//base/test:run_all_unittests",
diff --git a/ios/testing/ocmock_complex_type_helper_unittest.mm b/ios/testing/ocmock_complex_type_helper_unittest.mm index 709c7b9..ab859ca 100644 --- a/ios/testing/ocmock_complex_type_helper_unittest.mm +++ b/ios/testing/ocmock_complex_type_helper_unittest.mm
@@ -5,11 +5,14 @@ #import "ios/testing/ocmock_complex_type_helper.h" #include "base/logging.h" -#import "base/mac/scoped_nsobject.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #include "third_party/ocmock/gtest_support.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + // A complex type to test with.. struct SampleComplexType { int number; @@ -49,9 +52,9 @@ protected: void SetUp() override { PlatformTest::SetUp(); - helped_mock_.reset([[MockClass alloc] - initWithRepresentedObject: - [OCMockObject mockForProtocol:@protocol(TestedProtocol)]]); + OCMockObject* protocol_mock = + [OCMockObject mockForProtocol:@protocol(TestedProtocol)]; + helped_mock_ = [[MockClass alloc] initWithRepresentedObject:protocol_mock]; } void TearDown() override { @@ -59,7 +62,7 @@ PlatformTest::TearDown(); } - base::scoped_nsobject<id> helped_mock_; + id helped_mock_; }; TEST_F(OCMockComplexTypeHelperTest, nilObjectStillWorks) { @@ -68,7 +71,7 @@ } TEST_F(OCMockComplexTypeHelperTest, anyObjectStillWorks) { - base::scoped_nsobject<id> someObject([[NSObject alloc] init]); + id someObject = [[NSObject alloc] init]; [[helped_mock_ expect] passObject:OCMOCK_ANY]; [helped_mock_ passObject:someObject]; }
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 7ac322a..8e3eaff 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -23,6 +23,16 @@ namespace media { +namespace { + +// Helper to privide gfx::Rect::Intersect() as an expression. +gfx::Rect Intersection(gfx::Rect a, const gfx::Rect& b) { + a.Intersect(b); + return a; +} + +} // namespace + // Static POD class for generating unique identifiers for each VideoFrame. static base::StaticAtomicSequenceNumber g_unique_id_generator; @@ -923,13 +933,16 @@ : format_(format), storage_type_(storage_type), coded_size_(coded_size), - visible_rect_(visible_rect), + visible_rect_(Intersection(visible_rect, gfx::Rect(coded_size))), natural_size_(natural_size), shared_memory_offset_(0), timestamp_(timestamp), unique_id_(g_unique_id_generator.GetNext()) { DCHECK(IsValidConfig(format_, storage_type, coded_size_, visible_rect_, natural_size_)); + DCHECK(visible_rect_ == visible_rect) + << "visible_rect " << visible_rect.ToString() << " exceeds coded_size " + << coded_size.ToString(); memset(&mailbox_holders_, 0, sizeof(mailbox_holders_)); memset(&strides_, 0, sizeof(strides_)); memset(&data_, 0, sizeof(data_));
diff --git a/media/mojo/common/media_type_converters.cc b/media/mojo/common/media_type_converters.cc index 0a415d9..5571a8b 100644 --- a/media/mojo/common/media_type_converters.cc +++ b/media/mojo/common/media_type_converters.cc
@@ -18,8 +18,6 @@ #include "media/base/encryption_scheme.h" #include "media/base/subsample_entry.h" #include "media/base/video_decoder_config.h" -#include "media/base/video_frame.h" -#include "media/mojo/common/mojo_shared_buffer_video_frame.h" #include "mojo/public/cpp/system/buffer.h" namespace mojo { @@ -342,69 +340,4 @@ input->timestamp); } -// static -media::mojom::VideoFramePtr -TypeConverter<media::mojom::VideoFramePtr, scoped_refptr<media::VideoFrame>>:: - Convert(const scoped_refptr<media::VideoFrame>& input) { - media::mojom::VideoFramePtr frame(media::mojom::VideoFrame::New()); - frame->end_of_stream = - input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM); - if (frame->end_of_stream) - return frame; - - // Handle non EOS frame. It must be a MojoSharedBufferVideoFrame. - // TODO(jrummell): Support other types of VideoFrame. - CHECK_EQ(media::VideoFrame::STORAGE_MOJO_SHARED_BUFFER, - input->storage_type()); - media::MojoSharedBufferVideoFrame* input_frame = - static_cast<media::MojoSharedBufferVideoFrame*>(input.get()); - mojo::ScopedSharedBufferHandle duplicated_handle = - input_frame->Handle().Clone(); - CHECK(duplicated_handle.is_valid()); - - frame->format = input->format(); - frame->coded_size = input->coded_size(); - frame->visible_rect = input->visible_rect(); - frame->natural_size = input->natural_size(); - frame->timestamp = input->timestamp(); - - media::mojom::SharedBufferVideoFrameDataPtr data = - media::mojom::SharedBufferVideoFrameData::New(); - data->frame_data = std::move(duplicated_handle); - data->frame_data_size = input_frame->MappedSize(); - data->y_stride = input_frame->stride(media::VideoFrame::kYPlane); - data->u_stride = input_frame->stride(media::VideoFrame::kUPlane); - data->v_stride = input_frame->stride(media::VideoFrame::kVPlane); - data->y_offset = input_frame->PlaneOffset(media::VideoFrame::kYPlane); - data->u_offset = input_frame->PlaneOffset(media::VideoFrame::kUPlane); - data->v_offset = input_frame->PlaneOffset(media::VideoFrame::kVPlane); - - frame->data = media::mojom::VideoFrameData::New(); - frame->data->set_shared_buffer_data(std::move(data)); - return frame; -} - -// static -scoped_refptr<media::VideoFrame> -TypeConverter<scoped_refptr<media::VideoFrame>, media::mojom::VideoFramePtr>:: - Convert(const media::mojom::VideoFramePtr& input) { - if (input->end_of_stream) - return media::VideoFrame::CreateEOSFrame(); - - // Handle non EOS frame. It must be a MojoSharedBufferVideoFrame. - // TODO(jrummell): Support other types of VideoFrame. - DCHECK(input->data->is_shared_buffer_data()); - const media::mojom::SharedBufferVideoFrameDataPtr& data = - input->data->get_shared_buffer_data(); - - return media::MojoSharedBufferVideoFrame::Create( - input->format, input->coded_size, input->visible_rect, - input->natural_size, std::move(data->frame_data), - base::saturated_cast<size_t>(data->frame_data_size), - base::saturated_cast<size_t>(data->y_offset), - base::saturated_cast<size_t>(data->u_offset), - base::saturated_cast<size_t>(data->v_offset), data->y_stride, - data->u_stride, data->v_stride, input->timestamp); -} - } // namespace mojo
diff --git a/media/mojo/common/media_type_converters.h b/media/mojo/common/media_type_converters.h index d0afe70..c10c277 100644 --- a/media/mojo/common/media_type_converters.h +++ b/media/mojo/common/media_type_converters.h
@@ -19,7 +19,6 @@ class DecryptConfig; class EncryptionScheme; class VideoDecoderConfig; -class VideoFrame; struct CdmConfig; struct CdmKeyInformation; } @@ -127,19 +126,6 @@ const media::mojom::AudioBufferPtr& input); }; -template <> -struct TypeConverter<media::mojom::VideoFramePtr, - scoped_refptr<media::VideoFrame>> { - static media::mojom::VideoFramePtr Convert( - const scoped_refptr<media::VideoFrame>& input); -}; -template <> -struct TypeConverter<scoped_refptr<media::VideoFrame>, - media::mojom::VideoFramePtr> { - static scoped_refptr<media::VideoFrame> Convert( - const media::mojom::VideoFramePtr& input); -}; - } // namespace mojo #endif // MEDIA_MOJO_COMMON_MEDIA_TYPE_CONVERTERS_H_
diff --git a/media/mojo/interfaces/media_types.mojom b/media/mojo/interfaces/media_types.mojom index e206edb..5448756c 100644 --- a/media/mojo/interfaces/media_types.mojom +++ b/media/mojo/interfaces/media_types.mojom
@@ -213,22 +213,24 @@ // Natural size of the frame. gfx.mojom.Size natural_size; - // True if end of stream. - bool end_of_stream; - // Timestamp in microseconds of the associated frame. mojo.common.mojom.TimeDelta timestamp; - // Contents of the video frame. Will be null for end of stream frames. - VideoFrameData? data; + // Contents of the video frame (or EOS marker). + VideoFrameData data; }; // Possible choices for storing VideoFrame data. union VideoFrameData { + EosVideoFrameData eos_data; SharedBufferVideoFrameData shared_buffer_data; MailboxVideoFrameData mailbox_data; }; +// A marker for EOS frames. +struct EosVideoFrameData { +}; + // This defines video frame data stored in a Mojo shared buffer. struct SharedBufferVideoFrameData { // Reference to the shared memory containing the frame's data.
diff --git a/media/mojo/interfaces/video_frame_struct_traits.cc b/media/mojo/interfaces/video_frame_struct_traits.cc index 4d6aebf4..c68fed42 100644 --- a/media/mojo/interfaces/video_frame_struct_traits.cc +++ b/media/mojo/interfaces/video_frame_struct_traits.cc
@@ -16,9 +16,10 @@ media::mojom::VideoFrameDataPtr MakeVideoFrameData( const scoped_refptr<media::VideoFrame>& input) { - // EOS frames contain no data. - if (input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)) - return nullptr; + if (input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM)) { + return media::mojom::VideoFrameData::NewEosData( + media::mojom::EosVideoFrameData::New()); + } if (input->storage_type() == media::VideoFrame::STORAGE_MOJO_SHARED_BUFFER) { media::MojoSharedBufferVideoFrame* mojo_frame = @@ -86,8 +87,7 @@ media::mojom::VideoFrameDataDataView data; input.GetDataDataView(&data); - DCHECK_EQ(input.end_of_stream(), data.is_null()); - if (input.end_of_stream()) { + if (data.is_eos_data()) { *output = media::VideoFrame::CreateEOSFrame(); return !!*output; } @@ -104,11 +104,8 @@ if (!input.ReadVisibleRect(&visible_rect)) return false; - // Coded size must contain the visible rect. - if (visible_rect.right() > coded_size.width() || - visible_rect.bottom() > coded_size.height()) { + if (!gfx::Rect(coded_size).Contains(visible_rect)) return false; - } gfx::Size natural_size; if (!input.ReadNaturalSize(&natural_size))
diff --git a/media/mojo/interfaces/video_frame_struct_traits.h b/media/mojo/interfaces/video_frame_struct_traits.h index d674b162..3324b09 100644 --- a/media/mojo/interfaces/video_frame_struct_traits.h +++ b/media/mojo/interfaces/video_frame_struct_traits.h
@@ -52,10 +52,6 @@ return input->natural_size(); } - static bool end_of_stream(const scoped_refptr<media::VideoFrame>& input) { - return input->metadata()->IsTrue(media::VideoFrameMetadata::END_OF_STREAM); - } - static base::TimeDelta timestamp( const scoped_refptr<media::VideoFrame>& input) { return input->timestamp();
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc index 54b2a1b..650c7a4 100644 --- a/net/http/http_proxy_client_socket_pool.cc +++ b/net/http/http_proxy_client_socket_pool.cc
@@ -5,11 +5,17 @@ #include "net/http/http_proxy_client_socket_pool.h" #include <algorithm> +#include <map> +#include <string> #include <utility> #include "base/compiler_specific.h" #include "base/memory/ptr_util.h" -#include "base/time/time.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" +#include "base/optional.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/values.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" @@ -18,6 +24,7 @@ #include "net/http/http_proxy_client_socket_wrapper.h" #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" +#include "net/nqe/network_quality_provider.h" #include "net/socket/client_socket_factory.h" #include "net/socket/client_socket_handle.h" #include "net/socket/client_socket_pool_base.h" @@ -45,6 +52,28 @@ static const int kHttpProxyConnectJobTimeoutInSeconds = 30; #endif +static const char kNetAdaptiveProxyConnectionTimeout[] = + "NetAdaptiveProxyConnectionTimeout"; + +bool IsInNetAdaptiveProxyConnectionTimeoutFieldTrial() { + // Field trial is enabled if the group name starts with "Enabled". + return base::FieldTrialList::FindFullName(kNetAdaptiveProxyConnectionTimeout) + .find("Enabled") == 0; +} + +// Return the value of the parameter |param_name| for the field trial +// |kNetAdaptiveProxyConnectionTimeout|. If the value of the parameter is +// unavailable, then |default_value| is available. +int32_t GetInt32Param(const std::string& param_name, int32_t default_value) { + int32_t param; + if (!base::StringToInt(base::GetFieldTrialParamValue( + kNetAdaptiveProxyConnectionTimeout, param_name), + ¶m)) { + return default_value; + } + return param; +} + } // namespace HttpProxySocketParams::HttpProxySocketParams( @@ -162,7 +191,17 @@ : transport_pool_(transport_pool), ssl_pool_(ssl_pool), network_quality_provider_(network_quality_provider), - net_log_(net_log) {} + transport_rtt_multiplier_(GetInt32Param("transport_rtt_multiplier", 5)), + min_proxy_connection_timeout_(base::TimeDelta::FromSeconds( + GetInt32Param("min_proxy_connection_timeout_seconds", 8))), + max_proxy_connection_timeout_(base::TimeDelta::FromSeconds( + GetInt32Param("max_proxy_connection_timeout_seconds", 60))), + net_log_(net_log) { + DCHECK_LT(0, transport_rtt_multiplier_); + DCHECK_LE(base::TimeDelta(), min_proxy_connection_timeout_); + DCHECK_LE(base::TimeDelta(), max_proxy_connection_timeout_); + DCHECK_LE(min_proxy_connection_timeout_, max_proxy_connection_timeout_); +} std::unique_ptr<ConnectJob> HttpProxyClientSocketPool::HttpProxyConnectJobFactory::NewConnectJob( @@ -176,11 +215,25 @@ } base::TimeDelta -HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout( - ) const { - // TODO(tbansal): https://crbug.com/704339. Use |network_quality_provider_| - // and field trial to determine the connection timeout. - ALLOW_UNUSED_LOCAL(network_quality_provider_); +HttpProxyClientSocketPool::HttpProxyConnectJobFactory::ConnectionTimeout() + const { + if (IsInNetAdaptiveProxyConnectionTimeoutFieldTrial() && + network_quality_provider_) { + base::Optional<base::TimeDelta> transport_rtt_estimate = + network_quality_provider_->GetTransportRTT(); + if (transport_rtt_estimate) { + base::TimeDelta timeout = base::TimeDelta::FromMilliseconds( + transport_rtt_multiplier_ * + transport_rtt_estimate.value().InMilliseconds()); + // Ensure that connection timeout is between + // |min_proxy_connection_timeout_| and |max_proxy_connection_timeout_|. + if (timeout < min_proxy_connection_timeout_) + return min_proxy_connection_timeout_; + if (timeout > max_proxy_connection_timeout_) + return max_proxy_connection_timeout_; + return timeout; + } + } // Return the default proxy connection timeout. base::TimeDelta max_pool_timeout = base::TimeDelta();
diff --git a/net/http/http_proxy_client_socket_pool.h b/net/http/http_proxy_client_socket_pool.h index bf6dede8..24c4517 100644 --- a/net/http/http_proxy_client_socket_pool.h +++ b/net/http/http_proxy_client_socket_pool.h
@@ -5,6 +5,8 @@ #ifndef NET_HTTP_HTTP_PROXY_CLIENT_SOCKET_POOL_H_ #define NET_HTTP_HTTP_PROXY_CLIENT_SOCKET_POOL_H_ +#include <stdint.h> + #include <memory> #include <string> @@ -226,6 +228,9 @@ TransportClientSocketPool* const transport_pool_; SSLClientSocketPool* const ssl_pool_; NetworkQualityProvider* network_quality_provider_; + const int32_t transport_rtt_multiplier_; + const base::TimeDelta min_proxy_connection_timeout_; + const base::TimeDelta max_proxy_connection_timeout_; NetLog* net_log_; DISALLOW_COPY_AND_ASSIGN(HttpProxyConnectJobFactory);
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc index e05b203..9f3703d0 100644 --- a/net/http/http_proxy_client_socket_pool_unittest.cc +++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -4,10 +4,16 @@ #include "net/http/http_proxy_client_socket_pool.h" +#include <map> +#include <string> #include <utility> #include "base/callback.h" #include "base/compiler_specific.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_param_associator.h" +#include "base/metrics/field_trial_params.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/histogram_tester.h" @@ -75,17 +81,50 @@ NULL, session_deps_.ssl_config_service.get(), NetLogWithSource().net_log()), - pool_(kMaxSockets, - kMaxSocketsPerGroup, - &transport_socket_pool_, - &ssl_socket_pool_, - &estimator_, - NULL) { + field_trial_list_(nullptr), + pool_( + base::MakeUnique<HttpProxyClientSocketPool>(kMaxSockets, + kMaxSocketsPerGroup, + &transport_socket_pool_, + &ssl_socket_pool_, + &estimator_, + nullptr)) { session_ = CreateNetworkSession(); } virtual ~HttpProxyClientSocketPoolTest() {} + // Initializes the field trial paramters for the field trial that determines + // connection timeout based on the network quality. + void InitAdaptiveTimeoutFieldTrialWithParams( + bool use_default_params, + int transport_rtt_multiplier, + base::TimeDelta min_proxy_connection_timeout, + base::TimeDelta max_proxy_connection_timeout) { + std::string trial_name = "NetAdaptiveProxyConnectionTimeout"; + std::string group_name = "Enabled"; + + std::map<std::string, std::string> params; + if (!use_default_params) { + params["transport_rtt_multiplier"] = + base::IntToString(transport_rtt_multiplier); + params["min_proxy_connection_timeout_seconds"] = + base::IntToString(min_proxy_connection_timeout.InSeconds()); + params["max_proxy_connection_timeout_seconds"] = + base::IntToString(max_proxy_connection_timeout.InSeconds()); + } + base::FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting(); + EXPECT_TRUE( + base::AssociateFieldTrialParams(trial_name, group_name, params)); + EXPECT_TRUE(base::FieldTrialList::CreateFieldTrial(trial_name, group_name)); + + // Reset |pool_| so that the field trial parameters are read by the + // |pool_|. + pool_ = base::MakeUnique<HttpProxyClientSocketPool>( + kMaxSockets, kMaxSocketsPerGroup, &transport_socket_pool_, + &ssl_socket_pool_, &estimator_, NetLogWithSource().net_log()); + } + void AddAuthToCache() { const base::string16 kFoo(base::ASCIIToUTF16("foo")); const base::string16 kBar(base::ASCIIToUTF16("bar")); @@ -196,6 +235,8 @@ const base::HistogramTester& histogram_tester() { return histogram_tester_; } + TestNetworkQualityEstimator* estimator() { return &estimator_; } + private: SpdySessionDependencies session_deps_; @@ -210,11 +251,13 @@ base::HistogramTester histogram_tester_; + base::FieldTrialList field_trial_list_; + protected: SpdyTestUtil spdy_util_; std::unique_ptr<SSLSocketDataProvider> ssl_data_; std::unique_ptr<SequencedSocketData> data_; - HttpProxyClientSocketPool pool_; + std::unique_ptr<HttpProxyClientSocketPool> pool_; ClientSocketHandle handle_; TestCompletionCallback callback_; }; @@ -231,7 +274,7 @@ std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate()); int rv = handle_.Init("a", CreateNoTunnelParams(proxy_delegate.get()), LOW, ClientSocketPool::RespectLimits::ENABLED, - CompletionCallback(), &pool_, NetLogWithSource()); + CompletionCallback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsOk()); EXPECT_TRUE(handle_.is_initialized()); ASSERT_TRUE(handle_.socket()); @@ -251,9 +294,10 @@ // (non-SSL) socket request on Init. TEST_P(HttpProxyClientSocketPoolTest, SetSocketRequestPriorityOnInit) { Initialize(NULL, 0, NULL, 0, NULL, 0, NULL, 0); - EXPECT_EQ(OK, handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST, - ClientSocketPool::RespectLimits::ENABLED, - CompletionCallback(), &pool_, NetLogWithSource())); + EXPECT_EQ( + OK, handle_.Init("a", CreateNoTunnelParams(NULL), HIGHEST, + ClientSocketPool::RespectLimits::ENABLED, + CompletionCallback(), pool_.get(), NetLogWithSource())); EXPECT_EQ(HIGHEST, GetLastTransportRequestPriority()); } @@ -293,7 +337,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -342,7 +386,7 @@ std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate()); int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsOk()); EXPECT_TRUE(handle_.is_initialized()); ASSERT_TRUE(handle_.socket()); @@ -393,7 +437,7 @@ std::unique_ptr<TestProxyDelegate> proxy_delegate(new TestProxyDelegate()); int rv = handle_.Init("a", CreateTunnelParams(proxy_delegate.get()), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -427,10 +471,11 @@ spdy_writes, arraysize(spdy_writes)); AddAuthToCache(); - EXPECT_EQ(ERR_IO_PENDING, - handle_.Init("a", CreateTunnelParams(NULL), MEDIUM, - ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource())); + EXPECT_EQ( + ERR_IO_PENDING, + handle_.Init("a", CreateTunnelParams(NULL), MEDIUM, + ClientSocketPool::RespectLimits::ENABLED, + callback_.callback(), pool_.get(), NetLogWithSource())); EXPECT_EQ(MEDIUM, GetLastTransportRequestPriority()); EXPECT_THAT(callback_.WaitForResult(), IsOk()); @@ -446,7 +491,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -479,7 +524,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -511,7 +556,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -554,7 +599,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -594,7 +639,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -633,7 +678,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -690,7 +735,7 @@ int rv = handle_.Init("a", CreateTunnelParams(NULL), LOW, ClientSocketPool::RespectLimits::ENABLED, - callback_.callback(), &pool_, NetLogWithSource()); + callback_.callback(), pool_.get(), NetLogWithSource()); EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); EXPECT_FALSE(handle_.is_initialized()); EXPECT_FALSE(handle_.socket()); @@ -727,17 +772,118 @@ } TEST_P(HttpProxyClientSocketPoolTest, ProxyPoolTimeout) { - ASSERT_LE(base::TimeDelta(), pool_.ConnectionTimeout()); + EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout()); // Test against a large value. - ASSERT_GE(base::TimeDelta::FromMinutes(10), pool_.ConnectionTimeout()); + EXPECT_GE(base::TimeDelta::FromMinutes(10), pool_->ConnectionTimeout()); #if (defined(OS_ANDROID) || defined(OS_IOS)) // On Android and iOS, the timeout is fixed to 10 seconds. - ASSERT_EQ(base::TimeDelta::FromSeconds(10), pool_.ConnectionTimeout()); + EXPECT_EQ(base::TimeDelta::FromSeconds(10), pool_->ConnectionTimeout()); #endif } +// Tests the connection timeout values when the field trial parameters are +// specified. +TEST_P(HttpProxyClientSocketPoolTest, ProxyPoolTimeoutWithExperiment) { + int transport_rtt_multiplier = 2; + base::TimeDelta min_timeout = base::TimeDelta::FromSeconds(8); + base::TimeDelta max_timeout = base::TimeDelta::FromSeconds(20); + + InitAdaptiveTimeoutFieldTrialWithParams(false, transport_rtt_multiplier, + min_timeout, max_timeout); + EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout()); + + // Timeout should be |transport_rtt_multiplier| times the transport RTT + // estimate. + base::TimeDelta rtt_estimate = base::TimeDelta::FromSeconds(7); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(rtt_estimate + rtt_estimate, pool_->ConnectionTimeout()); + + // A change in RTT estimate should also change the connection timeout. + rtt_estimate = base::TimeDelta::FromSeconds(8); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(rtt_estimate + rtt_estimate, pool_->ConnectionTimeout()); + + // Connection timeout should not exceed |max_timeout|. + rtt_estimate = base::TimeDelta::FromSeconds(25); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(max_timeout, pool_->ConnectionTimeout()); + + // Connection timeout should not be less than |min_timeout|. + rtt_estimate = base::TimeDelta::FromSeconds(0); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(min_timeout, pool_->ConnectionTimeout()); +} + +// Tests the connection timeout values when the field trial parameters are +// specified. +TEST_P(HttpProxyClientSocketPoolTest, + ProxyPoolTimeoutWithExperimentDifferentParams) { + int transport_rtt_multiplier = 3; + base::TimeDelta min_timeout = base::TimeDelta::FromSeconds(2); + base::TimeDelta max_timeout = base::TimeDelta::FromSeconds(30); + + InitAdaptiveTimeoutFieldTrialWithParams(false, transport_rtt_multiplier, + min_timeout, max_timeout); + EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout()); + + // Timeout should be |transport_rtt_multiplier| times the transport RTT + // estimate. + base::TimeDelta rtt_estimate = base::TimeDelta::FromSeconds(2); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(rtt_estimate + rtt_estimate + rtt_estimate, + pool_->ConnectionTimeout()); + + // A change in RTT estimate should also change the connection timeout. + rtt_estimate = base::TimeDelta::FromSeconds(7); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(rtt_estimate + rtt_estimate + rtt_estimate, + pool_->ConnectionTimeout()); + + // Connection timeout should not exceed |max_timeout|. + rtt_estimate = base::TimeDelta::FromSeconds(35); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(max_timeout, pool_->ConnectionTimeout()); + + // Connection timeout should not be less than |min_timeout|. + rtt_estimate = base::TimeDelta::FromSeconds(0); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_EQ(min_timeout, pool_->ConnectionTimeout()); +} + +// Tests the connection timeout values when the field trial parameters are not +// specified. +TEST_P(HttpProxyClientSocketPoolTest, + ProxyPoolTimeoutWithExperimentDefaultParams) { + InitAdaptiveTimeoutFieldTrialWithParams(true, 0, base::TimeDelta(), + base::TimeDelta()); + EXPECT_LE(base::TimeDelta(), pool_->ConnectionTimeout()); + + // Timeout should be |transport_rtt_multiplier| times the transport RTT + // estimate. + base::TimeDelta rtt_estimate = base::TimeDelta::FromMilliseconds(10); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + // Connection timeout should not be less than the transport RTT estimate. + EXPECT_LE(rtt_estimate, pool_->ConnectionTimeout()); + + // A change in RTT estimate should also change the connection timeout. + rtt_estimate = base::TimeDelta::FromSeconds(10); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + // Connection timeout should not be less than the transport RTT estimate. + EXPECT_LE(rtt_estimate, pool_->ConnectionTimeout()); + + // Set RTT to a very large value. + rtt_estimate = base::TimeDelta::FromMinutes(60); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_GT(rtt_estimate, pool_->ConnectionTimeout()); + + // Set RTT to a very small value. + rtt_estimate = base::TimeDelta::FromSeconds(0); + estimator()->set_start_time_null_transport_rtt(rtt_estimate); + EXPECT_LT(rtt_estimate, pool_->ConnectionTimeout()); +} + // It would be nice to also test the timeouts in HttpProxyClientSocketPool. } // namespace net
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc index c97829f..99ad8291 100644 --- a/net/http/http_stream_factory_impl_job.cc +++ b/net/http/http_stream_factory_impl_job.cc
@@ -125,7 +125,8 @@ const NetLogSource& source, const GURL* original_url, const GURL* url, - const AlternativeService* alternative_service, + bool expect_spdy, + bool using_quic, RequestPriority priority, NetLogCaptureMode /* capture_mode */) { auto dict = base::MakeUnique<base::DictionaryValue>(); @@ -133,7 +134,8 @@ source.AddToEventParameters(dict.get()); dict->SetString("original_url", original_url->GetOrigin().spec()); dict->SetString("url", url->GetOrigin().spec()); - dict->SetString("alternative_service", alternative_service->ToString()); + dict->SetString("expect_spdy", expect_spdy ? "true" : "false"); + dict->SetString("using_quic", using_quic ? "true" : "false"); dict->SetString("priority", RequestPriorityToString(priority)); return std::move(dict); } @@ -159,34 +161,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - bool enable_ip_based_pooling, - NetLog* net_log) - : Job(delegate, - job_type, - session, - request_info, - priority, - proxy_info, - server_ssl_config, - proxy_ssl_config, - destination, - origin_url, - AlternativeService(), - ProxyServer(), - enable_ip_based_pooling, - net_log) {} - -HttpStreamFactoryImpl::Job::Job(Delegate* delegate, - JobType job_type, - HttpNetworkSession* session, - const HttpRequestInfo& request_info, - RequestPriority priority, - const ProxyInfo& proxy_info, - const SSLConfig& server_ssl_config, - const SSLConfig& proxy_ssl_config, - HostPortPair destination, - GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, const ProxyServer& alternative_proxy_server, bool enable_ip_based_pooling, NetLog* net_log) @@ -204,15 +179,17 @@ next_state_(STATE_NONE), destination_(destination), origin_url_(origin_url), - alternative_service_(alternative_service), alternative_proxy_server_(alternative_proxy_server), enable_ip_based_pooling_(enable_ip_based_pooling), delegate_(delegate), job_type_(job_type), using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) || origin_url_.SchemeIs(url::kWssScheme)), + using_quic_( + alternative_protocol == kProtoQUIC || + ShouldForceQuic(session, destination, origin_url, proxy_info)), + expect_spdy_(alternative_protocol == kProtoHTTP2 && !using_quic_), using_spdy_(false), - using_quic_(false), should_reconsider_proxy_(false), quic_request_(session_->quic_stream_factory()), using_existing_quic_session_(false), @@ -222,34 +199,34 @@ num_streams_(0), spdy_session_direct_( !(proxy_info.is_https() && origin_url_.SchemeIs(url::kHttpScheme))), - spdy_session_key_(GetSpdySessionKey()), + spdy_session_key_(GetSpdySessionKey(spdy_session_direct_, + proxy_info_.proxy_server(), + origin_url_, + request_info_.privacy_mode)), stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM), ptr_factory_(this) { DCHECK(session); - // The job can't have alternative service and alternative proxy server set at - // the same time since alternative services are used for requests that are - // fetched directly, while the alternative proxy server is used for requests - // that should be fetched using proxy. - DCHECK(alternative_service_.protocol == kProtoUnknown || - !alternative_proxy_server_.is_valid()); - DCHECK(!alternative_proxy_server_.is_valid() || - !(IsSpdyAlternative() || IsQuicAlternative())); - // If either the alternative service protocol is specified or if the - // alternative proxy server is valid, then the job type must be set to - // either ALTERNATIVE or PRECONNECT. - DCHECK((alternative_service_.protocol == kProtoUnknown && - !alternative_proxy_server_.is_valid()) || - (job_type_ == ALTERNATIVE || job_type_ == PRECONNECT)); - // If the alternative proxy server is valid, then the job type must be - // set to ALTERNATIVE. - DCHECK(!alternative_proxy_server_.is_valid() || job_type_ == ALTERNATIVE); + if (alternative_protocol != kProtoUnknown) { + // The job cannot have protocol requirements dictated by alternative service + // and have an alternative proxy server set at the same time, since + // alternative services are used for requests that are fetched directly, + // while the alternative proxy server is used for requests that should be + // fetched using proxy. + DCHECK(!alternative_proxy_server_.is_valid()); + // If the alternative service protocol is specified, then the job type must + // be either ALTERNATIVE or PRECONNECT. + DCHECK(job_type_ == ALTERNATIVE || job_type_ == PRECONNECT); + } + // If the alternative proxy server is set, then the job must be ALTERNATIVE. + if (alternative_proxy_server_.is_valid()) { + DCHECK(job_type_ == ALTERNATIVE); + } - if (IsSpdyAlternative()) { + if (expect_spdy_) { DCHECK(origin_url_.SchemeIs(url::kHttpsScheme)); } - if (IsQuicAlternative()) { + if (using_quic_) { DCHECK(session_->IsQuicEnabled()); - using_quic_ = true; } } @@ -396,16 +373,38 @@ ssl_socket->GetSSLInfo(ssl_info); } -SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey() const { +// static +bool HttpStreamFactoryImpl::Job::ShouldForceQuic( + HttpNetworkSession* session, + const HostPortPair& destination, + const GURL& origin_url, + const ProxyInfo& proxy_info) { + if (!session->IsQuicEnabled()) + return false; + if (proxy_info.is_quic()) + return true; + return (base::ContainsKey(session->params().origins_to_force_quic_on, + HostPortPair()) || + base::ContainsKey(session->params().origins_to_force_quic_on, + destination)) && + proxy_info.is_direct() && origin_url.SchemeIs(url::kHttpsScheme); +} + +// static +SpdySessionKey HttpStreamFactoryImpl::Job::GetSpdySessionKey( + bool spdy_session_direct, + const ProxyServer& proxy_server, + const GURL& origin_url, + PrivacyMode privacy_mode) { // In the case that we're using an HTTPS proxy for an HTTP url, // we look for a SPDY session *to* the proxy, instead of to the // origin server. - if (!spdy_session_direct_) { - return SpdySessionKey(proxy_info_.proxy_server().host_port_pair(), - ProxyServer::Direct(), PRIVACY_MODE_DISABLED); + if (!spdy_session_direct) { + return SpdySessionKey(proxy_server.host_port_pair(), ProxyServer::Direct(), + PRIVACY_MODE_DISABLED); } - return SpdySessionKey(HostPortPair::FromURL(origin_url_), - proxy_info_.proxy_server(), request_info_.privacy_mode); + return SpdySessionKey(HostPortPair::FromURL(origin_url), proxy_server, + privacy_mode); } bool HttpStreamFactoryImpl::Job::CanUseExistingSpdySession() const { @@ -459,7 +458,7 @@ void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() { DCHECK(stream_.get() || bidirectional_stream_impl_.get()); DCHECK_NE(job_type_, PRECONNECT); - DCHECK(using_spdy()); + DCHECK(using_spdy_); // Note: an event loop iteration has passed, so |new_spdy_session_| may be // NULL at this point if the SpdySession closed immediately after creation. base::WeakPtr<SpdySession> spdy_session = new_spdy_session_; @@ -733,7 +732,7 @@ net_log_.BeginEvent( NetLogEventType::HTTP_STREAM_JOB, base::Bind(&NetLogHttpStreamJobCallback, net_log->source(), - &request_info_.url, &origin_url_, &alternative_service_, + &request_info_.url, &origin_url_, expect_spdy_, using_quic_, priority_)); net_log->AddEvent(NetLogEventType::HTTP_STREAM_REQUEST_STARTED_JOB, net_log_.source().ToEventParametersCallback()); @@ -749,15 +748,6 @@ return OK; } -bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const { - return session_->IsQuicEnabled() && - (base::ContainsKey(session_->params().origins_to_force_quic_on, - HostPortPair()) || - base::ContainsKey(session_->params().origins_to_force_quic_on, - destination_)) && - proxy_info_.is_direct() && origin_url_.SchemeIs(url::kHttpsScheme); -} - int HttpStreamFactoryImpl::Job::DoWait() { next_state_ = STATE_WAIT_COMPLETE; bool should_wait = delegate_->ShouldWait(this); @@ -806,18 +796,6 @@ return OK; } - using_spdy_ = false; - - if (ShouldForceQuic()) - using_quic_ = true; - - DCHECK(!using_quic_ || session_->IsQuicEnabled()); - - if (proxy_info_.is_quic()) { - using_quic_ = true; - DCHECK(session_->IsQuicEnabled()); - } - if (proxy_info_.is_https() || proxy_info_.is_quic()) { InitSSLConfig(&proxy_ssl_config_, /*is_proxy=*/true); // Disable revocation checking for HTTPS proxies since the revocation @@ -904,8 +882,6 @@ if (proxy_info_.is_http() || proxy_info_.is_https()) establishing_tunnel_ = using_ssl_; - const bool expect_spdy = IsSpdyAlternative(); - HttpServerProperties* http_server_properties = session_->http_server_properties(); if (http_server_properties) { @@ -920,9 +896,9 @@ DCHECK(!delegate_->for_websockets()); return PreconnectSocketsForHttpRequest( GetSocketGroup(), destination_, request_info_.extra_headers, - request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, - server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode, - net_log_, num_streams_); + request_info_.load_flags, priority_, session_, proxy_info_, + expect_spdy_, server_ssl_config_, proxy_ssl_config_, + request_info_.privacy_mode, net_log_, num_streams_); } // If we can't use a SPDY session, don't bother checking for one after @@ -937,15 +913,15 @@ websocket_server_ssl_config.alpn_protos.clear(); return InitSocketHandleForWebSocketRequest( GetSocketGroup(), destination_, request_info_.extra_headers, - request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, - websocket_server_ssl_config, proxy_ssl_config_, + request_info_.load_flags, priority_, session_, proxy_info_, + expect_spdy_, websocket_server_ssl_config, proxy_ssl_config_, request_info_.privacy_mode, net_log_, connection_.get(), resolution_callback, io_callback_); } return InitSocketHandleForHttpRequest( GetSocketGroup(), destination_, request_info_.extra_headers, - request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy, + request_info_.load_flags, priority_, session_, proxy_info_, expect_spdy_, server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode, net_log_, connection_.get(), resolution_callback, io_callback_); } @@ -1030,16 +1006,13 @@ return result; } - if (proxy_info_.is_quic() && using_quic_ && result < 0) { - using_quic_ = false; + if (proxy_info_.is_quic() && using_quic_ && result < 0) return ReconsiderProxyAfterError(result); - } - if (IsSpdyAlternative() && !using_spdy_) + if (expect_spdy_ && !using_spdy_) return ERR_ALPN_NEGOTIATION_FAILED; - if (!ssl_started && result < 0 && - (IsSpdyAlternative() || IsQuicAlternative())) + if (!ssl_started && result < 0 && (expect_spdy_ || using_quic_)) return result; if (using_quic_) { @@ -1126,7 +1099,7 @@ FROM_HERE_WITH_EXPLICIT_FUNCTION( "462811 HttpStreamFactoryImpl::Job::DoCreateStream")); DCHECK(connection_->socket() || existing_spdy_session_.get() || using_quic_); - DCHECK(!IsQuicAlternative()); + DCHECK(!using_quic_); next_state_ = STATE_CREATE_STREAM_COMPLETE; @@ -1144,7 +1117,7 @@ SetSocketMotivation(); if (!using_spdy_) { - DCHECK(!IsSpdyAlternative()); + DCHECK(!expect_spdy_); // We may get ftp scheme when fetching ftp resources through proxy. bool using_proxy = (proxy_info_.is_http() || proxy_info_.is_https()) && (request_info_.url.SchemeIs(url::kHttpScheme) || @@ -1272,14 +1245,6 @@ // TODO(mbelshe): Add other motivations (like EARLY_LOAD_MOTIVATED). } -bool HttpStreamFactoryImpl::Job::IsSpdyAlternative() const { - return alternative_service_.protocol == kProtoHTTP2; -} - -bool HttpStreamFactoryImpl::Job::IsQuicAlternative() const { - return alternative_service_.protocol == kProtoQUIC; -} - void HttpStreamFactoryImpl::Job::InitSSLConfig(SSLConfig* ssl_config, bool is_proxy) const { if (!is_proxy) { @@ -1446,7 +1411,7 @@ return base::MakeUnique<HttpStreamFactoryImpl::Job>( delegate, job_type, session, request_info, priority, proxy_info, server_ssl_config, proxy_ssl_config, destination, origin_url, - enable_ip_based_pooling, net_log); + kProtoUnknown, ProxyServer(), enable_ip_based_pooling, net_log); } std::unique_ptr<HttpStreamFactoryImpl::Job> @@ -1461,13 +1426,13 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, bool enable_ip_based_pooling, NetLog* net_log) { return base::MakeUnique<HttpStreamFactoryImpl::Job>( delegate, job_type, session, request_info, priority, proxy_info, server_ssl_config, proxy_ssl_config, destination, origin_url, - alternative_service, ProxyServer(), enable_ip_based_pooling, net_log); + alternative_protocol, ProxyServer(), enable_ip_based_pooling, net_log); } std::unique_ptr<HttpStreamFactoryImpl::Job> @@ -1488,7 +1453,7 @@ return base::MakeUnique<HttpStreamFactoryImpl::Job>( delegate, job_type, session, request_info, priority, proxy_info, server_ssl_config, proxy_ssl_config, destination, origin_url, - AlternativeService(), alternative_proxy_server, enable_ip_based_pooling, + kProtoUnknown, alternative_proxy_server, enable_ip_based_pooling, net_log); }
diff --git a/net/http/http_stream_factory_impl_job.h b/net/http/http_stream_factory_impl_job.h index 91c3def5..80b9e52 100644 --- a/net/http/http_stream_factory_impl_job.h +++ b/net/http/http_stream_factory_impl_job.h
@@ -145,9 +145,29 @@ virtual bool for_websockets() = 0; }; - // Constructor for non-alternative Job. - // Job is owned by |delegate|, hence |delegate| is valid for the - // lifetime of the Job. + // Job is owned by |delegate|, hence |delegate| is valid for the lifetime of + // the Job. + // + // |alternative_protocol| is the protocol required by Alternative Service, if + // any: + // * |alternative_protocol == kProtoUnknown| means that the Job can pool to an + // existing SpdySession, or bind to a idle TCP socket that might use either + // HTTP/1.1 or HTTP/2. + // * |alternative_protocol == kProtoHTTP2| means that the Job can pool to an + // existing SpdySession, or bind to a idle TCP socket. In the latter case, + // if the socket does not use HTTP/2, then the Job fails. + // * |alternative_protocol == kProtoQUIC| means that the Job can pool to an + // existing QUIC connection or open a new one. + // Note that this can be overwritten by specifying a QUIC proxy in + // |proxy_info|, or by setting + // HttpNetworkSession::Params::origins_to_force_quic_on. + // + // If |alternative_proxy_server| is a valid proxy server, then the Job will + // use that instead of using ProxyService for proxy resolution. Further, if + // |alternative_proxy_server| is a valid but bad proxy, then fallback proxies + // are not used. It is illegal to call this constructor with a valid + // |alternative_proxy_server| and an |alternate_protocol| different from + // kProtoUnknown. Job(Delegate* delegate, JobType job_type, HttpNetworkSession* session, @@ -158,28 +178,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - bool enable_ip_based_pooling, - NetLog* net_log); - - // Constructor for the alternative Job. The Job is owned by |delegate|, hence - // |delegate| is valid for the lifetime of the Job. If |alternative_service| - // is initialized, then the Job will use the alternative service. On the - // other hand, if |alternative_proxy_server| is a valid proxy server, then the - // job will use that instead of using ProxyService for proxy resolution. - // Further, if |alternative_proxy_server| is a valid but bad proxy, then - // fallback proxies are not used. It is illegal to call this with an - // initialized |alternative_service|, and a valid |alternative_proxy_server|. - Job(Delegate* delegate, - JobType job_type, - HttpNetworkSession* session, - const HttpRequestInfo& request_info, - RequestPriority priority, - const ProxyInfo& proxy_info, - const SSLConfig& server_ssl_config, - const SSLConfig& proxy_ssl_config, - HostPortPair destination, - GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, const ProxyServer& alternative_proxy_server, bool enable_ip_based_pooling, NetLog* net_log); @@ -231,10 +230,6 @@ JobType job_type() const { return job_type_; } - const AlternativeService alternative_service() const { - return alternative_service_; - } - const ProxyServer alternative_proxy_server() const { return alternative_proxy_server_; } @@ -334,10 +329,6 @@ // Set the motivation for this request onto the underlying socket. void SetSocketMotivation(); - // Is this a SPDY or QUIC alternative Job? - bool IsSpdyAlternative() const; - bool IsQuicAlternative() const; - // Sets several fields of |ssl_config| based on the proxy info and other // factors. void InitSSLConfig(SSLConfig* ssl_config, bool is_proxy) const; @@ -346,8 +337,17 @@ // This must only be called when we are using an SSLSocket. void GetSSLInfo(SSLInfo* ssl_info); + // Called in Job constructor: should Job be forced to use QUIC. + static bool ShouldForceQuic(HttpNetworkSession* session, + const HostPortPair& destination, + const GURL& origin_url, + const ProxyInfo& proxy_info); + // Called in Job constructor. Use |spdy_session_key_| after construction. - SpdySessionKey GetSpdySessionKey() const; + static SpdySessionKey GetSpdySessionKey(bool spdy_session_direct, + const ProxyServer& proxy_server, + const GURL& origin_url, + PrivacyMode privacy_mode); // Returns true if the current request can use an existing spdy session. bool CanUseExistingSpdySession() const; @@ -368,9 +368,6 @@ // Called to handle a client certificate request. int HandleCertificateRequest(int error); - // Should we force QUIC for this stream request. - bool ShouldForceQuic() const; - ClientSocketPoolManager::SocketGroupType GetSocketGroup() const; void MaybeCopyConnectionAttemptsFromSocketOrHandle(); @@ -413,9 +410,6 @@ // original request when host mapping rules are set-up. const GURL origin_url_; - // AlternativeService for this Job if this is an alternative Job. - const AlternativeService alternative_service_; - // Alternative proxy server that should be used by |this| to fetch the // request. const ProxyServer alternative_proxy_server_; @@ -432,11 +426,16 @@ // True if handling a HTTPS request. const bool using_ssl_; - // True if this network transaction is using SPDY instead of HTTP. - bool using_spdy_; + // True if Job uses QUIC. + const bool using_quic_; - // True if this network transaction is using QUIC instead of HTTP. - bool using_quic_; + // True if Alternative Service protocol field requires that HTTP/2 is used. + // In this case, Job fails if it cannot pool to an existing SpdySession and + // the server does not negotiate HTTP/2 on a new socket. + const bool expect_spdy_; + + // True if Job actually uses HTTP/2. + bool using_spdy_; // True if this job might succeed with a different proxy config. bool should_reconsider_proxy_; @@ -517,7 +516,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, bool enable_ip_based_pooling, NetLog* net_log);
diff --git a/net/http/http_stream_factory_impl_job_controller.cc b/net/http/http_stream_factory_impl_job_controller.cc index 69209d4..a3134b8 100644 --- a/net/http/http_stream_factory_impl_job_controller.cc +++ b/net/http/http_stream_factory_impl_job_controller.cc
@@ -769,7 +769,7 @@ GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination); // Create an alternative job if alternative service is set up for this domain. - const AlternativeService alternative_service = + alternative_service_ = GetAlternativeServiceInfoFor(request_info_, delegate_, stream_type_) .alternative_service(); @@ -778,15 +778,15 @@ // priority currently makes sense for preconnects. The priority for // preconnects is currently ignored (see RequestSocketsForPool()), but could // be used at some point for proxy resolution or something. - if (alternative_service.protocol != kProtoUnknown) { + if (alternative_service_.protocol != kProtoUnknown) { HostPortPair alternative_destination( - alternative_service.host_port_pair()); + alternative_service_.host_port_pair()); ignore_result( ApplyHostMappingRules(request_info_.url, &alternative_destination)); main_job_ = job_factory_->CreateAltSvcJob( this, PRECONNECT, session_, request_info_, IDLE, proxy_info_, server_ssl_config_, proxy_ssl_config_, alternative_destination, - origin_url, alternative_service, enable_ip_based_pooling_, + origin_url, alternative_service_.protocol, enable_ip_based_pooling_, session_->net_log()); } else { main_job_ = job_factory_->CreateMainJob( @@ -803,21 +803,22 @@ enable_ip_based_pooling_, net_log_.net_log()); // Alternative Service can only be set for HTTPS requests while Alternative // Proxy is set for HTTP requests. - if (alternative_service.protocol != kProtoUnknown) { + if (alternative_service_.protocol != kProtoUnknown) { // Never share connection with other jobs for FTP requests. DVLOG(1) << "Selected alternative service (host: " - << alternative_service.host_port_pair().host() - << " port: " << alternative_service.host_port_pair().port() << ")"; + << alternative_service_.host_port_pair().host() + << " port: " << alternative_service_.host_port_pair().port() + << ")"; DCHECK(!request_info_.url.SchemeIs(url::kFtpScheme)); - HostPortPair alternative_destination(alternative_service.host_port_pair()); + HostPortPair alternative_destination(alternative_service_.host_port_pair()); ignore_result( ApplyHostMappingRules(request_info_.url, &alternative_destination)); alternative_job_ = job_factory_->CreateAltSvcJob( this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_, server_ssl_config_, proxy_ssl_config_, alternative_destination, - origin_url, alternative_service, enable_ip_based_pooling_, + origin_url, alternative_service_.protocol, enable_ip_based_pooling_, net_log_.net_log()); main_job_is_blocked_ = true; @@ -945,10 +946,9 @@ int net_error) { DCHECK_EQ(alternative_job_->job_type(), ALTERNATIVE); DCHECK_NE(OK, net_error); - DCHECK_NE(kProtoUnknown, alternative_job_->alternative_service().protocol); + DCHECK_NE(kProtoUnknown, alternative_service_.protocol); alternative_job_net_error_ = net_error; - failed_alternative_service_ = alternative_job_->alternative_service(); if (IsJobOrphaned(alternative_job_.get())) { // If |request_| is gone then it must have been successfully served by @@ -974,7 +974,7 @@ } void HttpStreamFactoryImpl::JobController::ReportBrokenAlternativeService() { - DCHECK(failed_alternative_service_.protocol != kProtoUnknown); + DCHECK(alternative_service_.protocol != kProtoUnknown); DCHECK_NE(OK, alternative_job_net_error_); int error_to_report = alternative_job_net_error_; @@ -990,7 +990,7 @@ HistogramBrokenAlternateProtocolLocation( BROKEN_ALTERNATE_PROTOCOL_LOCATION_HTTP_STREAM_FACTORY_IMPL_JOB_ALT); session_->http_server_properties()->MarkAlternativeServiceBroken( - failed_alternative_service_); + alternative_service_); } void HttpStreamFactoryImpl::JobController::MaybeNotifyFactoryOfCompletion() {
diff --git a/net/http/http_stream_factory_impl_job_controller.h b/net/http/http_stream_factory_impl_job_controller.h index a5ccf46..9b29742 100644 --- a/net/http/http_stream_factory_impl_job_controller.h +++ b/net/http/http_stream_factory_impl_job_controller.h
@@ -11,6 +11,7 @@ #include "net/base/privacy_mode.h" #include "net/http/http_stream_factory_impl_job.h" #include "net/http/http_stream_factory_impl_request.h" +#include "net/socket/next_proto.h" namespace net { @@ -312,11 +313,12 @@ // |main_job_| to proceed and then race the two jobs. std::unique_ptr<Job> main_job_; std::unique_ptr<Job> alternative_job_; + // The alternative service used by |alternative_job_| + // (or by |main_job_| if |is_preconnect_|.) + AlternativeService alternative_service_; // Net error code of the failed alternative job. Set to OK by default. int alternative_job_net_error_; - // The alternative service server that |alternative_job_| uses failed. - AlternativeService failed_alternative_service_; // True if a Job has ever been bound to the |request_|. bool job_bound_;
diff --git a/net/http/http_stream_factory_test_util.cc b/net/http/http_stream_factory_test_util.cc index 2c8fc625..0f5371d 100644 --- a/net/http/http_stream_factory_test_util.cc +++ b/net/http/http_stream_factory_test_util.cc
@@ -26,35 +26,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - bool enable_ip_based_pooling, - NetLog* net_log) - : HttpStreamFactoryImpl::Job(delegate, - job_type, - session, - request_info, - priority, - proxy_info, - server_ssl_config, - proxy_ssl_config, - destination, - origin_url, - enable_ip_based_pooling, - net_log) { - DCHECK(!is_waiting()); -} - -MockHttpStreamFactoryImplJob::MockHttpStreamFactoryImplJob( - HttpStreamFactoryImpl::Job::Delegate* delegate, - HttpStreamFactoryImpl::JobType job_type, - HttpNetworkSession* session, - const HttpRequestInfo& request_info, - RequestPriority priority, - ProxyInfo proxy_info, - const SSLConfig& server_ssl_config, - const SSLConfig& proxy_ssl_config, - HostPortPair destination, - GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, const ProxyServer& alternative_proxy_server, bool enable_ip_based_pooling, NetLog* net_log) @@ -68,10 +40,12 @@ proxy_ssl_config, destination, origin_url, - alternative_service, + alternative_protocol, alternative_proxy_server, enable_ip_based_pooling, - net_log) {} + net_log) { + DCHECK(!is_waiting()); +} MockHttpStreamFactoryImplJob::~MockHttpStreamFactoryImplJob() {} @@ -100,8 +74,8 @@ auto main_job = base::MakeUnique<MockHttpStreamFactoryImplJob>( delegate, job_type, session, request_info, priority, proxy_info, - SSLConfig(), SSLConfig(), destination, origin_url, - enable_ip_based_pooling, nullptr); + SSLConfig(), SSLConfig(), destination, origin_url, kProtoUnknown, + ProxyServer(), enable_ip_based_pooling, nullptr); // Keep raw pointer to Job but pass ownership. main_job_ = main_job.get(); @@ -120,12 +94,12 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, bool enable_ip_based_pooling, NetLog* net_log) { auto alternative_job = base::MakeUnique<MockHttpStreamFactoryImplJob>( delegate, job_type, session, request_info, priority, proxy_info, - SSLConfig(), SSLConfig(), destination, origin_url, alternative_service, + SSLConfig(), SSLConfig(), destination, origin_url, alternative_protocol, ProxyServer(), enable_ip_based_pooling, nullptr); // Keep raw pointer to Job but pass ownership. @@ -150,7 +124,7 @@ NetLog* net_log) { auto alternative_job = base::MakeUnique<MockHttpStreamFactoryImplJob>( delegate, job_type, session, request_info, priority, proxy_info, - SSLConfig(), SSLConfig(), destination, origin_url, AlternativeService(), + SSLConfig(), SSLConfig(), destination, origin_url, kProtoUnknown, alternative_proxy_server, enable_ip_based_pooling, nullptr); // Keep raw pointer to Job but pass ownership.
diff --git a/net/http/http_stream_factory_test_util.h b/net/http/http_stream_factory_test_util.h index 461ee2b5..49a3d96 100644 --- a/net/http/http_stream_factory_test_util.h +++ b/net/http/http_stream_factory_test_util.h
@@ -15,6 +15,7 @@ #include "net/http/http_stream_factory_impl_job_controller.h" #include "net/proxy/proxy_info.h" #include "net/proxy/proxy_server.h" +#include "net/socket/next_proto.h" #include "testing/gmock/include/gmock/gmock.h" using testing::_; @@ -114,20 +115,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - bool enable_ip_based_pooling, - NetLog* net_log); - - MockHttpStreamFactoryImplJob(HttpStreamFactoryImpl::Job::Delegate* delegate, - HttpStreamFactoryImpl::JobType job_type, - HttpNetworkSession* session, - const HttpRequestInfo& request_info, - RequestPriority priority, - ProxyInfo proxy_info, - const SSLConfig& server_ssl_config, - const SSLConfig& proxy_ssl_config, - HostPortPair destination, - GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, const ProxyServer& alternative_proxy_server, bool enable_ip_based_pooling, NetLog* net_log); @@ -170,7 +158,7 @@ const SSLConfig& proxy_ssl_config, HostPortPair destination, GURL origin_url, - AlternativeService alternative_service, + NextProto alternative_protocol, bool enable_ip_based_pooling, NetLog* net_log) override;
diff --git a/net/nqe/network_quality_estimator_test_util.cc b/net/nqe/network_quality_estimator_test_util.cc index 81372b4..84cc856 100644 --- a/net/nqe/network_quality_estimator_test_util.cc +++ b/net/nqe/network_quality_estimator_test_util.cc
@@ -183,6 +183,13 @@ return NetworkQualityEstimator::GetRecentTransportRTT(start_time, rtt); } +base::Optional<base::TimeDelta> TestNetworkQualityEstimator::GetTransportRTT() + const { + if (start_time_null_transport_rtt_) + return start_time_null_transport_rtt_; + return NetworkQualityEstimator::GetTransportRTT(); +} + bool TestNetworkQualityEstimator::GetRecentDownlinkThroughputKbps( const base::TimeTicks& start_time, int32_t* kbps) const {
diff --git a/net/nqe/network_quality_estimator_test_util.h b/net/nqe/network_quality_estimator_test_util.h index 4b12fce..4549c92 100644 --- a/net/nqe/network_quality_estimator_test_util.h +++ b/net/nqe/network_quality_estimator_test_util.h
@@ -8,6 +8,7 @@ #include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "base/files/file_path.h" @@ -155,6 +156,9 @@ DCHECK(!effective_connection_type_ && !recent_effective_connection_type_); recent_transport_rtt_ = recent_transport_rtt; } + + base::Optional<base::TimeDelta> GetTransportRTT() const override; + // Returns the recent transport RTT that was set using // |set_recent_transport_rtt|. If the recent transport RTT has not been set, // then the base implementation is called.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2b362ec..a9141a1 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1375,7 +1375,10 @@ ], "experiments": [ { - "name": "Enabled", + "name": "EnableAppNap", + "params": { + "app_nap": "true" + }, "enable_features": [ "MacAllowBackgroundingProcesses" ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG index 1651fe30..92302c0c 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-features=LayoutNG
@@ -17582,20 +17582,20 @@ crbug.com/591099 inspector/elements/styles/url-multiple-collapsing.html [ Crash ] crbug.com/591099 inspector/elements/user-properties.html [ Crash ] crbug.com/591099 inspector/evaluate-in-page.html [ Failure ] -crbug.com/591099 inspector/extensions/extensions-api.html [ Failure ] -crbug.com/591099 inspector/extensions/extensions-audits-api.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-audits-content-script.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-audits.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-eval-content-script.html [ Failure ] -crbug.com/591099 inspector/extensions/extensions-eval.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-events.html [ Crash ] -crbug.com/591099 inspector/extensions/extensions-network.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-panel.html [ Crash ] -crbug.com/591099 inspector/extensions/extensions-reload.html [ Failure ] -crbug.com/591099 inspector/extensions/extensions-resources.html [ Crash Failure ] -crbug.com/591099 inspector/extensions/extensions-sidebar.html [ Crash ] -crbug.com/591099 inspector/extensions/extensions-timeline-api.html [ Crash ] -crbug.com/591099 inspector/extensions/multiple-extensions.html [ Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-api.html [ Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-audits-api.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-audits-content-script.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-audits.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-eval-content-script.html [ Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-eval.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-events.html [ Crash ] +crbug.com/591099 http/tests/inspector/extensions/extensions-network.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-panel.html [ Crash ] +crbug.com/591099 http/tests/inspector/extensions/extensions-reload.html [ Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-resources.html [ Crash Failure ] +crbug.com/591099 http/tests/inspector/extensions/extensions-sidebar.html [ Crash ] +crbug.com/591099 http/tests/inspector/extensions/extensions-timeline-api.html [ Crash ] +crbug.com/591099 http/tests/inspector/extensions/multiple-extensions.html [ Failure ] crbug.com/591099 inspector/file-reader-with-network-panel.html [ Failure ] crbug.com/591099 inspector/file-system-mapping.html [ Failure ] crbug.com/591099 inspector/file-system-project.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service index ccb1b75..5b8a7ce 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-network-service
@@ -281,7 +281,7 @@ Bug(none) external/wpt/cssom-view/scrollingElement.html [ Failure Timeout ] Bug(none) external/wpt/custom-elements/custom-element-registry/per-global.html [ Failure Timeout ] Bug(none) external/wpt/dom/nodes/Document-URL.sub.html [ Failure Timeout ] -Bug(none) external/wpt/dom/nodes/Document-characterSet-normalization.html [ Failure Timeout ] +Bug(none) external/wpt/dom/nodes/Document-characterSet-normalization.html [ Crash Failure Timeout ] Bug(none) external/wpt/dom/nodes/Document-createElement-namespace.html [ Failure Timeout ] Bug(none) external/wpt/dom/nodes/Element-remove.html [ Failure Timeout ] Bug(none) external/wpt/domxpath/xml_xpath_runner.html [ Failure Timeout ] @@ -1048,39 +1048,119 @@ Bug(none) external/wpt/referrer-policy/origin/meta-referrer/same-origin/http-https/xhr-request/generic.keep-origin-redirect.http.html [ Failure Timeout ] Bug(none) external/wpt/referrer-policy/origin/meta-referrer/same-origin/http-https/xhr-request/generic.no-redirect.http.html [ Failure Timeout ] Bug(none) external/wpt/referrer-policy/origin/meta-referrer/same-origin/http-https/xhr-request/generic.swap-origin-redirect.http.html [ Failure Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/iframe-tag/cross-origin.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/img-tag/cross-origin.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/cross-origin/http-https/img-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/same-origin/http-https/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/attr-referrer/same-origin/http-https/img-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/fetch-request/cross-origin.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/fetch-request/cross-origin.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/img-tag/cross-origin.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/img-tag/cross-origin.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/script-tag/cross-origin.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/script-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/cross-origin/http-https/xhr-request/cross-origin.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/http-rp/same-origin/http-https/fetch-request/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/same-origin/http-https/img-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/http-rp/same-origin/http-https/script-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/fetch-request/cross-origin.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/iframe-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/img-tag/cross-origin.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/img-tag/cross-origin.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/script-tag/cross-origin.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/cross-origin/http-https/script-tag/cross-origin.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/same-origin/http-https/fetch-request/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/same-origin/http-https/iframe-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/same-origin/meta-referrer/same-origin/http-https/img-tag/same-origin-insecure.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/cross-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/attr-referrer/same-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin-when-cross-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/cross-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/attr-referrer/same-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/http-rp/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/fetch-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/iframe-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/img-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/cross-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/iframe-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/img-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/img-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.no-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/script-tag/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.keep-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.no-redirect.http.html [ Timeout ] +Bug(none) external/wpt/referrer-policy/strict-origin/meta-referrer/same-origin/http-https/xhr-request/upgrade-protocol.swap-origin-redirect.http.html [ Timeout ] Bug(none) external/wpt/referrer-policy/unsafe-url/attr-referrer/cross-origin/http-https/iframe-tag/generic.keep-origin-redirect.http.html [ Failure Timeout ] Bug(none) external/wpt/referrer-policy/unsafe-url/attr-referrer/cross-origin/http-https/iframe-tag/generic.no-redirect.http.html [ Failure Timeout ] Bug(none) external/wpt/referrer-policy/unsafe-url/attr-referrer/cross-origin/http-https/iframe-tag/generic.swap-origin-redirect.http.html [ Failure Timeout ] @@ -1586,7 +1666,7 @@ Bug(none) http/tests/appcache/offline-access.html [ Timeout ] Bug(none) http/tests/appcache/online-fallback-layering.html [ Timeout ] Bug(none) http/tests/appcache/online-whitelist.html [ Failure ] -Bug(none) http/tests/appcache/reload.html [ Failure ] +Bug(none) http/tests/appcache/reload.html [ Failure Timeout ] Bug(none) http/tests/appcache/remove-cache.html [ Timeout ] Bug(none) http/tests/appcache/simple.html [ Timeout ] Bug(none) http/tests/appcache/top-frame-1.html [ Timeout ] @@ -1663,7 +1743,7 @@ Bug(none) http/tests/csspaint/registerPaint.html [ Timeout ] Bug(none) http/tests/csspaint/registered-properties-in-custom-paint.html [ Timeout ] Bug(none) http/tests/csspaint/style-background-image.html [ Timeout ] -Bug(none) http/tests/csspaint/style-before-pseudo.html [ Timeout ] +Bug(none) http/tests/csspaint/style-before-pseudo.html [ Crash Pass Timeout ] Bug(none) http/tests/csspaint/style-first-letter-pseudo.html [ Timeout ] Bug(none) http/tests/dom/create-contextual-fragment-from-bodyless-svg-document-range.html [ Timeout ] Bug(none) http/tests/download/basic-ascii.html [ Crash ] @@ -1934,6 +2014,16 @@ Bug(none) http/tests/inspector [ Crash Failure Timeout ] Bug(none) http/tests/inspector-enabled [ Failure Timeout ] Bug(none) http/tests/inspector-protocol [ Failure Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-api.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-audits-api.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-audits-content-script.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-audits.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-events.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-network.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-reload.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-resources.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/extensions-timeline-api.html [ Timeout ] +Bug(none) http/tests/inspector/extensions/multiple-extensions.html [ Timeout ] Bug(none) http/tests/linkHeader/link-preconnect-schemeless.https.php [ Timeout ] Bug(none) http/tests/loading/307-after-303-after-post.html [ Failure ] Bug(none) http/tests/loading/bad-scheme-subframe.html [ Failure ] @@ -2489,16 +2579,6 @@ Bug(none) inspector/elements/styles/cancel-upon-invalid-property.html [ Timeout ] Bug(none) inspector/elements/styles/original-content-provider.html [ Timeout ] Bug(none) inspector/elements/styles/url-multiple-collapsing.html [ Timeout ] -Bug(none) inspector/extensions/extensions-api.html [ Timeout ] -Bug(none) inspector/extensions/extensions-audits-api.html [ Timeout ] -Bug(none) inspector/extensions/extensions-audits-content-script.html [ Timeout ] -Bug(none) inspector/extensions/extensions-audits.html [ Timeout ] -Bug(none) inspector/extensions/extensions-events.html [ Timeout ] -Bug(none) inspector/extensions/extensions-network.html [ Timeout ] -Bug(none) inspector/extensions/extensions-reload.html [ Timeout ] -Bug(none) inspector/extensions/extensions-resources.html [ Timeout ] -Bug(none) inspector/extensions/extensions-timeline-api.html [ Timeout ] -Bug(none) inspector/extensions/multiple-extensions.html [ Timeout ] Bug(none) inspector/file-system-mapping.html [ Timeout ] Bug(none) inspector/file-system-project.html [ Failure ] Bug(none) inspector/geolocation-emulation-tests.html [ Timeout ]
diff --git a/third_party/WebKit/LayoutTests/SlowTests b/third_party/WebKit/LayoutTests/SlowTests index 0f02144..99808d1 100644 --- a/third_party/WebKit/LayoutTests/SlowTests +++ b/third_party/WebKit/LayoutTests/SlowTests
@@ -98,9 +98,9 @@ crbug.com/451577 [ Debug ] fast/dom/gc-treescope.html [ Slow ] crbug.com/451577 [ Debug ] fast/frames/calculate-round.html [ Slow ] crbug.com/451577 external/wpt/IndexedDB/idbindex-multientry-big.htm [ Slow ] -crbug.com/451577 [ Mac ] inspector/extensions/extensions-reload.html [ Slow ] -crbug.com/451577 [ Mac ] inspector/extensions/extensions-resources.html [ Slow ] -crbug.com/451577 [ Win10 ] inspector/extensions/extensions-sidebar.html [ Slow ] +crbug.com/451577 [ Mac ] http/tests/inspector/extensions/extensions-reload.html [ Slow ] +crbug.com/451577 [ Mac ] http/tests/inspector/extensions/extensions-resources.html [ Slow ] +crbug.com/451577 [ Win10 ] http/tests/inspector/extensions/extensions-sidebar.html [ Slow ] crbug.com/451577 [ Mac ] inspector/layers/layer-canvas-log.html [ Slow ] crbug.com/451577 [ Mac ] inspector/network/network-domain-filter.html [ Slow ] @@ -129,8 +129,8 @@ crbug.com/420008 virtual/threaded/inspector/tracing/ [ Slow ] crbug.com/246190 [ Release ] http/tests/inspector/indexeddb/ [ Slow ] crbug.com/246190 [ Release ] virtual/mojo-loading/http/tests/inspector/indexeddb/ [ Slow ] -crbug.com/451577 [ Mac ] inspector/extensions/extensions-sidebar.html [ Slow ] -crbug.com/451577 [ Mac ] inspector/extensions/extensions-events.html [ Slow ] +crbug.com/451577 [ Mac ] http/tests/inspector/extensions/extensions-sidebar.html [ Slow ] +crbug.com/451577 [ Mac ] http/tests/inspector/extensions/extensions-events.html [ Slow ] # Random slow tests webkit.org/b/90488 [ Release ] http/tests/inspector/compiler-source-mapping-debug.html [ Slow ] @@ -221,7 +221,7 @@ crbug.com/241576 [ Win ] virtual/mojo-loading/http/tests/appcache/404-manifest.html [ Slow ] crbug.com/241869 [ Debug ] css3/flexbox/multiline-justify-content.html [ Slow ] crbug.com/245154 editing/selection/modify_move/move-by-character-brute-force.html [ Slow ] -crbug.com/246749 inspector/extensions/extensions-panel.html [ Slow ] +crbug.com/246749 http/tests/inspector/extensions/extensions-panel.html [ Slow ] # This test takes 5+ seconds as intended because it tests connection throttling. crbug.com/459377 http/tests/websocket/multiple-connections-throttled.html [ Slow ]
diff --git a/third_party/WebKit/LayoutTests/SmokeTests b/third_party/WebKit/LayoutTests/SmokeTests index 4f186b9..7aa6bb2 100644 --- a/third_party/WebKit/LayoutTests/SmokeTests +++ b/third_party/WebKit/LayoutTests/SmokeTests
@@ -974,7 +974,6 @@ transforms/3d/hit-testing/composited-hit-test.html transforms/3d/hit-testing/rotated-hit-test-with-child.html transforms/container-transform-crash.html -transforms/cssmatrix-crash.html transforms/focus-on-transformed-node.html transforms/no_transform_hit_testing.html transforms/topmost-becomes-bottomost-for-scrolling.html
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 0c961d2..8cc8f3b 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1560,22 +1560,20 @@ crbug.com/501659 virtual/mojo-loading/http/tests/security/xss-DENIED-xml-external-entity.xhtml [ Failure ] crbug.com/501659 fast/css/stylesheet-candidate-nodes-crash.xhtml [ Failure ] - # Change to higher precision for exotic blend modes -crbug.com/732829 css3/blending/background-blend-mode-crossfade-image-gradient.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/background-blend-mode-gif-color-2.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/background-blend-mode-gif-color.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/background-blend-mode-svg-color.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-1.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-2.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-3.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/mix-blend-mode-simple-text.html [ NeedsManualRebaseline ] -crbug.com/732829 svg/filters/feBlend-all-modes.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/svg-blend-color.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/svg-blend-hue.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/svg-blend-luminosity.html [ NeedsManualRebaseline ] -crbug.com/732829 css3/blending/svg-blend-saturation.html [ NeedsManualRebaseline ] - +crbug.com/732829 css3/blending/background-blend-mode-crossfade-image-gradient.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/background-blend-mode-gif-color-2.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/background-blend-mode-gif-color.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/background-blend-mode-svg-color.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-1.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-2.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/mix-blend-mode-isolated-group-3.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/mix-blend-mode-simple-text.html [ NeedsRebaseline ] +crbug.com/732829 svg/filters/feBlend-all-modes.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/svg-blend-color.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/svg-blend-hue.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/svg-blend-luminosity.html [ NeedsRebaseline ] +crbug.com/732829 css3/blending/svg-blend-saturation.html [ NeedsRebaseline ] # Mac10.10-specific failures that still need triaging. # Form controls need rebaseline because of the default font change. @@ -2871,3 +2869,6 @@ crbug.com/732103 [ Mac ] virtual/mojo-loading/http/tests/shapedetection/shapedetection-cross-origin.html [ Failure Pass Timeout ] # Sheriff failures 2017-06-10 crbug.com/732839 [ Win ] external/wpt/payment-request/payment-request-constructor-crash.https.html [ Pass Timeout ] + +# Sheriff failures 2017-06-14 +crbug.com/733357 [ Win Mac ] inspector/elements/styles-4/styles-history.html [ Failure Pass ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index a609fab..152ce22c 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -96304,6 +96304,11 @@ {} ] ], + "payment-request/payment-request-update-event-updatewith-method.https-expected.txt": [ + [ + {} + ] + ], "performance-timeline/performanceobservers.js": [ [ {} @@ -238025,6 +238030,10 @@ "6b546870fd384a5bf2106d25fd3159a72f8537b2", "testharness" ], + "payment-request/payment-request-update-event-updatewith-method.https-expected.txt": [ + "6f7d4ed0c005b4a8af0644148b174c7911531688", + "support" + ], "payment-request/payment-request-update-event-updatewith-method.https.html": [ "d85bca2ccb865c11c550a9d9c1d8770b2c68d6bd", "testharness"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt deleted file mode 100644 index 22ad39c5..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/DOMMatrix-stringifier-expected.txt +++ /dev/null
@@ -1,82 +0,0 @@ -This is a testharness.js-based test. -Found 78 tests; 54 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS DOMMatrix stringifier: identity (2d) -PASS DOMMatrix stringifier: identity (3d) -PASS DOMMatrix stringifier: NaN (2d) -PASS DOMMatrix stringifier: NaN (3d) -PASS DOMMatrix stringifier: Infinity (2d) -PASS DOMMatrix stringifier: Infinity (3d) -PASS DOMMatrix stringifier: -Infinity (2d) -PASS DOMMatrix stringifier: -Infinity (3d) -PASS DOMMatrix stringifier: 1/3 (2d) -PASS DOMMatrix stringifier: 1/3 (3d) -PASS DOMMatrix stringifier: 1/300000 (2d) -PASS DOMMatrix stringifier: 1/300000 (3d) -PASS DOMMatrix stringifier: 1/300000000 (2d) -PASS DOMMatrix stringifier: 1/300000000 (3d) -PASS DOMMatrix stringifier: 100000 + (1/3) (2d) -PASS DOMMatrix stringifier: 100000 + (1/3) (3d) -PASS DOMMatrix stringifier: Math.pow(2, 53) + 1 (2d) -PASS DOMMatrix stringifier: Math.pow(2, 53) + 1 (3d) -PASS DOMMatrix stringifier: Math.pow(2, 53) + 2 (2d) -PASS DOMMatrix stringifier: Math.pow(2, 53) + 2 (3d) -PASS DOMMatrix stringifier: Number.MAX_VALUE (2d) -PASS DOMMatrix stringifier: Number.MAX_VALUE (3d) -PASS DOMMatrix stringifier: Number.MIN_VALUE (2d) -PASS DOMMatrix stringifier: Number.MIN_VALUE (3d) -PASS DOMMatrix stringifier: throwing getters (2d) -PASS DOMMatrix stringifier: throwing getters (3d) -PASS DOMMatrixReadOnly stringifier: identity (2d) -PASS DOMMatrixReadOnly stringifier: identity (3d) -PASS DOMMatrixReadOnly stringifier: NaN (2d) -PASS DOMMatrixReadOnly stringifier: NaN (3d) -PASS DOMMatrixReadOnly stringifier: Infinity (2d) -PASS DOMMatrixReadOnly stringifier: Infinity (3d) -PASS DOMMatrixReadOnly stringifier: -Infinity (2d) -PASS DOMMatrixReadOnly stringifier: -Infinity (3d) -PASS DOMMatrixReadOnly stringifier: 1/3 (2d) -PASS DOMMatrixReadOnly stringifier: 1/3 (3d) -PASS DOMMatrixReadOnly stringifier: 1/300000 (2d) -PASS DOMMatrixReadOnly stringifier: 1/300000 (3d) -PASS DOMMatrixReadOnly stringifier: 1/300000000 (2d) -PASS DOMMatrixReadOnly stringifier: 1/300000000 (3d) -PASS DOMMatrixReadOnly stringifier: 100000 + (1/3) (2d) -PASS DOMMatrixReadOnly stringifier: 100000 + (1/3) (3d) -PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 1 (2d) -PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 1 (3d) -PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 2 (2d) -PASS DOMMatrixReadOnly stringifier: Math.pow(2, 53) + 2 (3d) -PASS DOMMatrixReadOnly stringifier: Number.MAX_VALUE (2d) -PASS DOMMatrixReadOnly stringifier: Number.MAX_VALUE (3d) -PASS DOMMatrixReadOnly stringifier: Number.MIN_VALUE (2d) -PASS DOMMatrixReadOnly stringifier: Number.MIN_VALUE (3d) -PASS DOMMatrixReadOnly stringifier: throwing getters (2d) -PASS DOMMatrixReadOnly stringifier: throwing getters (3d) -PASS WebKitCSSMatrix stringifier: identity (2d) -FAIL WebKitCSSMatrix stringifier: identity (3d) self[constr].fromMatrix is not a function -FAIL WebKitCSSMatrix stringifier: NaN (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,NaN'. -FAIL WebKitCSSMatrix stringifier: NaN (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,NaN,0,1'. -FAIL WebKitCSSMatrix stringifier: Infinity (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,Infinity'. -FAIL WebKitCSSMatrix stringifier: Infinity (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,Infinity,0,1'. -FAIL WebKitCSSMatrix stringifier: -Infinity (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,-Infinity'. -FAIL WebKitCSSMatrix stringifier: -Infinity (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,-Infinity,0,1'. -FAIL WebKitCSSMatrix stringifier: 1/3 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,0.3333333333333333'. -FAIL WebKitCSSMatrix stringifier: 1/3 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,0.3333333333333333,0,1'. -FAIL WebKitCSSMatrix stringifier: 1/300000 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,0.0000033333333333333333'. -FAIL WebKitCSSMatrix stringifier: 1/300000 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,0.0000033333333333333333,0,1'. -FAIL WebKitCSSMatrix stringifier: 1/300000000 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,3.3333333333333334e-9'. -FAIL WebKitCSSMatrix stringifier: 1/300000000 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,3.3333333333333334e-9,0,1'. -FAIL WebKitCSSMatrix stringifier: 100000 + (1/3) (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,100000.33333333333'. -FAIL WebKitCSSMatrix stringifier: 100000 + (1/3) (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,100000.33333333333,0,1'. -FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,9007199254740992'. -FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 1 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,9007199254740992,0,1'. -FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,9007199254740994'. -FAIL WebKitCSSMatrix stringifier: Math.pow(2, 53) + 2 (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,9007199254740994,0,1'. -FAIL WebKitCSSMatrix stringifier: Number.MAX_VALUE (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,1.7976931348623157e+308'. -FAIL WebKitCSSMatrix stringifier: Number.MAX_VALUE (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,1.7976931348623157e+308,0,1'. -FAIL WebKitCSSMatrix stringifier: Number.MIN_VALUE (2d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,1,0,5e-324'. -FAIL WebKitCSSMatrix stringifier: Number.MIN_VALUE (3d) Failed to construct 'WebKitCSSMatrix': Failed to parse '1,0,0,0,0,1,0,0,0,0,1,0,0,5e-324,0,1'. -PASS WebKitCSSMatrix stringifier: throwing getters (2d) -FAIL WebKitCSSMatrix stringifier: throwing getters (3d) self[constr].fromMatrix is not a function -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt deleted file mode 100644 index dd0272a..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/geometry-1/WebKitCSSMatrix-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL Equivalence test assert_equals: interface object expected function "function DOMMatrix() { [native code] }" but got function "function WebKitCSSMatrix() { [native code] }" -PASS Property descriptor for WebKitCSSMatrix -PASS Property descriptor for DOMMatrix -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_null.tentative.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_null.tentative.html new file mode 100644 index 0000000..314a7035 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_null.tentative.html
@@ -0,0 +1,82 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<!-- SEKRITS! --> +<input id="sekrit" value="omg!"> + +<script> + function postMessageToFrame(frame, message) { + return new Promise(resolve => { + var c = new MessageChannel(); + c.port1.onmessage = e => { + resolve({ data: e.data, frame: frame }) + }; + frame.contentWindow.postMessage(message, '*', [c.port2]); + }); + } + + function createFrame() { + return new Promise(resolve => { + var i = document.createElement('iframe'); + i.src = "./support/document_domain_frame.html"; + window.addEventListener('message', m => { + if (m.source == i.contentWindow) + resolve(i); + }); + document.body.appendChild(i); + }); + } + + promise_test(t => { + return createFrame() + .then(f => postMessageToFrame(f, 'poke-at-parent')) + .then(result => { + assert_equals(result.data, document.querySelector('#sekrit').value); + result.frame.remove(); + }); + }, "Access allowed with no 'document.domain' modification. (Sanity check)"); + + promise_test(t => { + return createFrame() + .then(f => postMessageToFrame(f, { domain: null })) + .then(result => { + assert_equals(result.data, 'Done'); + return postMessageToFrame(result.frame, 'poke-at-parent') + .then(result => { + assert_equals(result.data, 'SecurityError'); + result.frame.remove(); + }); + }); + }, "No access when frame sets a `null` 'document.domain'."); + + promise_test(t => { + return createFrame() + .then(f => { + document.domain = null; + assert_equals(document.domain, "null"); + return postMessageToFrame(f, 'poke-at-parent'); + }) + .then(result => { + assert_equals(result.data, 'SecurityError'); + result.frame.remove(); + }); + }, "No access when parent sets a `null` 'document.domain'."); + + promise_test(t => { + return createFrame() + .then(f => { + document.domain = null; + assert_equals(document.domain, "null"); + return postMessageToFrame(f, { domain: null }); + }) + .then(result => { + assert_equals(result.data, 'Done'); + return postMessageToFrame(result.frame, 'poke-at-parent') + .then(result => { + assert_equals(result.data, 'SecurityError'); + result.frame.remove(); + }); + }); + }, "No access when both sides set a `null` 'document.domain'."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_srcdoc.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_srcdoc.html new file mode 100644 index 0000000..42d2d97 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/document_domain_setter_srcdoc.html
@@ -0,0 +1,84 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<body> +<!-- SEKRITS! --> +<input id="sekrit" value="omg!"> + +<script> + function postMessageToFrame(frame, message) { + return new Promise(resolve => { + var c = new MessageChannel(); + c.port1.onmessage = e => { + resolve({ data: e.data, frame: frame }) + }; + frame.contentWindow.postMessage(message, '*', [c.port2]); + }); + } + + function createFrame() { + return new Promise(resolve => { + var i = document.createElement('iframe'); + i.srcdoc = ` + <script> + window.addEventListener('message', e => { + if (e.data.domain !== undefined) { + try { + document.domain = e.data.domain; + e.ports[0].postMessage('Done'); + } catch(error) { + e.ports[0].postMessage(error.name); + } + } else if (e.data == 'poke-at-parent') { + try { + var sekrit = window.parent.document.body.querySelector('#sekrit').value; + e.ports[0].postMessage(sekrit); + } catch(error) { + e.ports[0].postMessage(error.name); + } + } + }); + window.parent.postMessage('Hi!', '*'); + </scr` + `ipt>`; + window.addEventListener('message', m => { + if (m.source == i.contentWindow) + resolve(i); + }); + document.body.appendChild(i); + }); + } + + promise_test(t => { + return createFrame() + .then(f => postMessageToFrame(f, 'poke-at-parent')) + .then(result => { + assert_equals(result.data, document.querySelector('#sekrit').value); + result.frame.remove(); + }); + }, "srcdoc can access with no 'document.domain' modification."); + + promise_test(t => { + return createFrame() + .then(f => postMessageToFrame(f, { domain: window.location.hostname })) + .then(result => { + assert_equals(result.data, 'Done'); + return postMessageToFrame(result.frame, 'poke-at-parent') + .then(result => { + assert_equals(result.data, document.querySelector('#sekrit').value); + result.frame.remove(); + }); + }); + }, "srcdoc can access with valid 'document.domain'."); + + promise_test(t => { + return createFrame() + .then(f => { + document.domain = window.location.hostname; + return postMessageToFrame(f, 'poke-at-parent'); + }) + .then(result => { + assert_equals(result.data, document.querySelector('#sekrit').value); + result.frame.remove(); + }); + }, "srcdoc can access when parent modifies 'document.domain'."); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/support/document_domain_frame.html b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/support/document_domain_frame.html new file mode 100644 index 0000000..42e8137 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/origin/relaxing-the-same-origin-restriction/support/document_domain_frame.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<script> + window.addEventListener('message', e => { + if (e.data.domain !== undefined) { + try { + document.domain = e.data.domain; + e.ports[0].postMessage('Done'); + } catch(error) { + e.ports[0].postMessage(error.name); + } + } else if (e.data == 'poke-at-parent') { + try { + var sekrit = window.parent.document.body.querySelector('#sekrit').value; + e.ports[0].postMessage(sekrit); + } catch(error) { + e.ports[0].postMessage(error.name); + } + } + }); + window.parent.postMessage('Hi!', '*'); +</script>
diff --git a/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt index 7d0014c..294eef2 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/Window/custom-constructors-expected.txt
@@ -7,7 +7,7 @@ PASS Option.prototype.toString.call(new Option) is '[object HTMLOptionElement]' PASS WebKitCSSMatrix.prototype.toString.call(new WebKitCSSMatrix) is 'matrix(1, 0, 0, 1, 0, 0)' PASS WebKitCSSMatrix.prototype.toString.call(new WebKitCSSMatrix()) is 'matrix(1, 0, 0, 1, 0, 0)' -PASS new WebKitCSSMatrix(null) threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'null'.. +PASS new WebKitCSSMatrix(null) threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'null'.. FAIL new WebKitCSSMatrix(undefined) should throw an exception. Was matrix(1, 0, 0, 1, 0, 0). PASS XMLHttpRequest.prototype.toString.call(new XMLHttpRequest) is '[object XMLHttpRequest]' PASS XSLTProcessor.prototype.toString.call(new XSLTProcessor) is '[object XSLTProcessor]'
diff --git a/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt b/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt index bcd6af3..d91c597 100644 --- a/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/dom/call-a-constructor-as-a-function-expected.txt
@@ -22,7 +22,7 @@ PASS Uint16Array() threw exception TypeError: Constructor Uint16Array requires 'new'. PASS Uint32Array() threw exception TypeError: Constructor Uint32Array requires 'new'. PASS Uint8Array() threw exception TypeError: Constructor Uint8Array requires 'new'. -PASS WebKitCSSMatrix() threw exception TypeError: Failed to construct 'WebKitCSSMatrix': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. +PASS WebKitCSSMatrix() threw exception TypeError: Failed to construct 'DOMMatrix': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS WebSocket() threw exception TypeError: Failed to construct 'WebSocket': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS Worker() threw exception TypeError: Failed to construct 'Worker': Please use the 'new' operator, this DOM object constructor cannot be called as a function.. PASS XMLHttpRequest() threw exception TypeError: Failed to construct 'XMLHttpRequest': Please use the 'new' operator, this DOM object constructor cannot be called as a function..
diff --git a/third_party/WebKit/LayoutTests/inspector/audits/audits-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/audits-test.js similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/audits/audits-test.js rename to third_party/WebKit/LayoutTests/http/tests/inspector/audits-test.js
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js index a5dc23d..44b66a99 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-network-test.js
@@ -11,6 +11,8 @@ } } } + output("no item found"); + callback(null); } webInspector.network.getHAR(onHAR); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js index 9e744db..b49489f 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions-test.js
@@ -9,8 +9,14 @@ return functions; } +var extensionsOrigin = "http://devtools-extensions.test:8000"; + var initialize_ExtensionsTest = function() { + +var extensionsHost = "devtools-extensions.test"; +var extensionsOrigin = `http://${extensionsHost}:8000`; + Extensions.extensionServer._registerHandler("evaluateForTestInFrontEnd", onEvaluate); Extensions.extensionServer._extensionAPITestHook = function(extensionServerClient, coreAPI) @@ -56,7 +62,8 @@ var extensionURL = (/^https?:/.test(pageURL) ? pageURL.replace(/^(https?:\/\/[^/]*\/).*$/,"$1") : pageURL.replace(/\/inspector\/extensions\/[^/]*$/, "/http/tests")) + - "/inspector/resources/extension-main.html"; + "inspector/resources/extension-main.html"; + extensionURL = extensionURL.replace("127.0.0.1", extensionsHost); InspectorFrontendAPI.addExtensions([{ startPage: extensionURL, name: "test extension", exposeWebInspectorNamespace: true }]); Extensions.extensionServer.initializeExtensions(); }
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-api-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-api-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-api-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-api.html similarity index 64% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-api.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-api.html index 629c74db..b4789e4 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-api.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-api.html
@@ -1,15 +1,13 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> - function extension_testAPI(nextTest) { dumpObject(webInspector); nextTest(); } - </script> </head> <body onload="runTest()">
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-api-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-api-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-api-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-api-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-api.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-api.html similarity index 83% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-api.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-api.html index 0e4cb03..074f35d 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-api.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-api.html
@@ -1,8 +1,8 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../audits/audits-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../audits-test.js"></script> <script src="extensions-audits-tests.js"></script> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-content-script-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-content-script-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-content-script-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-content-script-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-content-script.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-content-script.html similarity index 86% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-content-script.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-content-script.html index 9e03190..16925c9 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-content-script.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-content-script.html
@@ -1,15 +1,15 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../audits/audits-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../audits-test.js"></script> <script src="extensions-audits-tests.js"></script> <script type="text/javascript"> window.whereAmI = "main world"; -testRunner.setIsolatedWorldSecurityOrigin(632, "file:///"); +testRunner.setIsolatedWorldSecurityOrigin(632, extensionsOrigin); testRunner.evaluateScriptInIsolatedWorld(632, "window.whereAmI = 'brave new world'"); function extension_testAudits(nextTest)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-tests.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-tests.js similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits-tests.js rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits-tests.js
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits.html similarity index 93% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits.html index 7c5dada..997586100 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-audits.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-audits.html
@@ -1,8 +1,8 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../audits/audits-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../audits-test.js"></script> <script src="extensions-audits-tests.js"></script> <script type="text/javascript">
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-content-script-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-content-script-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-content-script-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-content-script-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-content-script.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-content-script.html similarity index 82% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-content-script.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-content-script.html index ac0404f0..8c4c0ef 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-content-script.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-content-script.html
@@ -1,12 +1,12 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> window.whereAmI = "main world"; -testRunner.setIsolatedWorldSecurityOrigin(632, "file:///"); +testRunner.setIsolatedWorldSecurityOrigin(632, extensionsOrigin); testRunner.evaluateScriptInIsolatedWorld(632, "window.whereAmI = 'brave new world'"); function extension_testEvalInMainWorldImplicit(nextTest)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval.html similarity index 93% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval.html index ebb7db4..15e74a57 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-eval.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-eval.html
@@ -1,7 +1,7 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> window.inspectedValue = { str: "foo", num: 42 };
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-events-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-events-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-events-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-events-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-events.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-events.html similarity index 92% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-events.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-events.html index 8a09ce0..004f32d 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-events.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-events.html
@@ -1,9 +1,9 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../../http/tests/inspector/debugger-test.js"></script> -<script src="../sources/debugger/resources/edit-me.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../debugger-test.js"></script> +<script src="../../../inspector/sources/debugger/resources/edit-me.js"></script> <script type="text/javascript"> function initialize_extensionsSidebarTest() @@ -49,7 +49,7 @@ nextTest(); } webInspector.network.onRequestFinished.addListener(onRequestFinished); - webInspector.inspectedWindow.eval("var xhr = new XMLHttpRequest(); xhr.open('GET', '" + location.href + "', false); xhr.send(null);"); + webInspector.inspectedWindow.eval("var xhr = new XMLHttpRequest(); xhr.open('GET', location.href, false); xhr.send(null);"); } function extension_testOnNavigated(nextTest)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-network-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network-expected.txt similarity index 96% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-network-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network-expected.txt index 1036a2c..074fe12 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-network-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network-expected.txt
@@ -5,15 +5,15 @@ Started extension. Running tests... RUNNING TEST: extension_testGetHAR -resource: .../tests/inspector/extensions-network-test.js -resource: .../tests/inspector/extensions-test.js -resource: .../tests/inspector/inspector-test.js -resource: .../inspector/extensions/extensions-network.html -resource: .../inspector/extensions/extensions-network.html -resource: .../extensions/resources/abe.png -resource: .../extensions/resources/audits-style1.css -resource: .../extensions/resources/missing-image.png -resource: .../LayoutTests/resources/Ahem.ttf +resource: http://127.0.0.1:8000/inspector/extensions-network-test.js +resource: http://127.0.0.1:8000/inspector/extensions-test.js +resource: http://127.0.0.1:8000/inspector/extensions/extensions-network.html +resource: http://127.0.0.1:8000/inspector/extensions/extensions-network.html +resource: http://127.0.0.1:8000/inspector/extensions/resources/abe.png +resource: http://127.0.0.1:8000/inspector/extensions/resources/audits-style1.css +resource: http://127.0.0.1:8000/inspector/extensions/resources/missing-image.png +resource: http://127.0.0.1:8000/inspector/inspector-test.js +resource: http://127.0.0.1:8000/resources/Ahem.ttf RUNNING TEST: extension_testGetRequestContent { 0 : ".some-style {
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-network.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network.html similarity index 77% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-network.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network.html index 7a78707..b16e954f 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-network.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-network.html
@@ -1,6 +1,5 @@ <html> <head> -<link rel="stylesheet" href="resources/audits-style1.css" type="text/css"> <style> @font-face { font-family: 'test'; @@ -10,9 +9,10 @@ p { font-family: 'test'; } </style> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../../http/tests/inspector/extensions-network-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../extensions-network-test.js"></script> +<link rel="stylesheet" href="resources/audits-style1.css" type="text/css"> <script type="text/javascript"> function extension_testGetHAR(nextTest) @@ -27,7 +27,7 @@ result.entries.sort(compareEntries); for (var i = 0; i < result.entries.length; ++i) - output("resource: " + result.entries[i].request.url.replace(/.*((\/[^/]*){3}$)/,"...$1")); + output("resource: " + result.entries[i].request.url); } extension_doXHR(function() { webInspector.network.getHAR(callbackAndNextTest(onHAR, nextTest)); @@ -36,14 +36,20 @@ function doXHR() { - var xhr = new XMLHttpRequest(); - xhr.open("GET", "", false); - xhr.send(null); + return new Promise((fulfill) => { + var xhr = new XMLHttpRequest(); + xhr.open("GET", "", true); + xhr.send(null); + xhr.onreadystatechange = () => { + if (xhr.readyState == 4 && xhr.status == 200) + fulfill(); + }; + }); } function extension_doXHR(callback) { - webInspector.inspectedWindow.eval("doXHR()", callback); + invokePageFunctionAsync("doXHR", callback); } function extension_testRequestNotification(nextTest)
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-panel-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-panel-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-panel.html similarity index 96% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-panel.html index 45532d9..0dc5b48 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-panel.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-panel.html
@@ -1,11 +1,11 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/console-test.js"></script> -<script src="../../http/tests/inspector/network-test.js"></script> -<script src="../../http/tests/inspector/sources-test.js"></script> -<script src="../../http/tests/inspector/resources-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../console-test.js"></script> +<script src="../network-test.js"></script> +<script src="../sources-test.js"></script> +<script src="../resources-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> function logMessage() { @@ -225,7 +225,7 @@ function performSearch(query) { - UI.inspectorView.panel("file://TestPanelforsearch").then(panel => { + UI.inspectorView.panel(extensionsOrigin + "TestPanelforsearch").then(panel => { panel.searchableView().showSearchField(); panel.searchableView()._searchInputElement.value = query; panel.searchableView()._performSearch(true, true);
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-reload-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-reload-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-reload-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-reload-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-reload.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-reload.html similarity index 91% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-reload.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-reload.html index dfb3528..1c27c0d 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-reload.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-reload.html
@@ -1,9 +1,9 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/debugger-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../../http/tests/inspector/console-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../debugger-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../console-test.js"></script> <script type="text/javascript"> window.bar = "foo = " + window.foo;
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-resources-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-resources-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-resources.html similarity index 96% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-resources.html index c03206b..63f69c6 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-resources.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-resources.html
@@ -1,9 +1,9 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/console-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../../http/tests/inspector/debugger-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../console-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../debugger-test.js"></script> <script type="text/javascript"> function loadFrame() {
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-sidebar-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-sidebar-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-sidebar-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-sidebar-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-sidebar.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-sidebar.html similarity index 98% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-sidebar.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-sidebar.html index 2a70803..1dd3c51 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-sidebar.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-sidebar.html
@@ -1,7 +1,7 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> function initialize_extensionsSidebarTest()
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-timeline-api-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-timeline-api-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-timeline-api.html similarity index 93% rename from third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-timeline-api.html index c216f2a..b4ed623 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/extensions-timeline-api.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/extensions-timeline-api.html
@@ -1,8 +1,8 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> -<script src="../../http/tests/inspector/timeline-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> +<script src="../timeline-test.js"></script> <script type="text/javascript"> function initialize_timelineExtensionTest()
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/multiple-extensions-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/multiple-extensions-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/multiple-extensions-expected.txt rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/multiple-extensions-expected.txt
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/multiple-extensions.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/multiple-extensions.html similarity index 86% rename from third_party/WebKit/LayoutTests/inspector/extensions/multiple-extensions.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/multiple-extensions.html index fdfae56c..861d3589 100644 --- a/third_party/WebKit/LayoutTests/inspector/extensions/multiple-extensions.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/multiple-extensions.html
@@ -1,7 +1,7 @@ <html> <head> -<script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="../../http/tests/inspector/extensions-test.js"></script> +<script src="../inspector-test.js"></script> +<script src="../extensions-test.js"></script> <script type="text/javascript"> function initialize_multipleExtensionsTest() {
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/resources/abe.png b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/abe.png similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/resources/abe.png rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/abe.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/resources/audits-style1.css b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/audits-style1.css similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/resources/audits-style1.css rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/audits-style1.css
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/resources/subframe.html b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/subframe.html similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/resources/subframe.html rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/subframe.html
diff --git a/third_party/WebKit/LayoutTests/inspector/extensions/resources/test-script.js b/third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/test-script.js similarity index 100% rename from third_party/WebKit/LayoutTests/inspector/extensions/resources/test-script.js rename to third_party/WebKit/LayoutTests/http/tests/inspector/extensions/resources/test-script.js
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/resources/extension-main.js b/third_party/WebKit/LayoutTests/http/tests/inspector/resources/extension-main.js index 63c40089..5416cdf 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/resources/extension-main.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/resources/extension-main.js
@@ -63,7 +63,7 @@ function onError(event) { window.removeEventListener("error", onError); - output("Uncaught exception in extension context: " + event.message + " [" + event.filename + ":" + event.lineno + "]"); + output("Uncaught exception in extension context: " + event.message + " [" + event.filename + ":" + event.lineno + "]\n"); evaluateOnFrontend("InspectorTest.completeTest();"); }
diff --git a/third_party/WebKit/LayoutTests/http/tests/security/document-domain-invalid.html b/third_party/WebKit/LayoutTests/http/tests/security/document-domain-invalid.html index 91fd118..893dd017 100644 --- a/third_party/WebKit/LayoutTests/http/tests/security/document-domain-invalid.html +++ b/third_party/WebKit/LayoutTests/http/tests/security/document-domain-invalid.html
@@ -9,15 +9,6 @@ assert_equals(document.domain, '127.0.0.1'); assert_throws('SecurityError', function () { - document.domain = null; - }); - assert_equals(document.domain, '127.0.0.1'); - }, 'Setting `document.domain` to null fails.'); - - test(function () { - assert_equals(document.domain, '127.0.0.1'); - assert_throws('SecurityError', - function () { document.domain = ''; }); assert_equals(document.domain, '127.0.0.1');
diff --git a/third_party/WebKit/LayoutTests/inspector/audits/audits-empty-stylesheet.html b/third_party/WebKit/LayoutTests/inspector/audits/audits-empty-stylesheet.html index 2a11d0e..56c7ecf7 100644 --- a/third_party/WebKit/LayoutTests/inspector/audits/audits-empty-stylesheet.html +++ b/third_party/WebKit/LayoutTests/inspector/audits/audits-empty-stylesheet.html
@@ -5,7 +5,7 @@ /* Empty stylesheet */ </style> <script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="audits-test.js"></script> +<script src="../../http/tests/inspector/audits-test.js"></script> <script> function test()
diff --git a/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-functional.html b/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-functional.html index ce53f03..6cf35f417 100644 --- a/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-functional.html +++ b/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-functional.html
@@ -42,7 +42,7 @@ JSON = {}; </script> <script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="audits-test.js"></script> +<script src="../../http/tests/inspector/audits-test.js"></script> <!-- These scripts are needed to result in a violation of the max JS resource count from the same domain --> <script src="resources/audits-script1.js"></script>
diff --git a/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-noimages-functional.html b/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-noimages-functional.html index edfdb02..b738592 100644 --- a/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-noimages-functional.html +++ b/third_party/WebKit/LayoutTests/inspector/audits/audits-panel-noimages-functional.html
@@ -13,7 +13,7 @@ JSON = {}; </script> <script src="../../http/tests/inspector/inspector-test.js"></script> -<script src="audits-test.js"></script> +<script src="../../http/tests/inspector/audits-test.js"></script> <!-- These scripts are needed to result in a violation of the max JS resource count from the same domain --> <script src="resources/audits-script1.js"></script>
diff --git a/third_party/WebKit/LayoutTests/inspector/user-metrics.html b/third_party/WebKit/LayoutTests/inspector/user-metrics.html index ca156a6..8867bea 100644 --- a/third_party/WebKit/LayoutTests/inspector/user-metrics.html +++ b/third_party/WebKit/LayoutTests/inspector/user-metrics.html
@@ -3,7 +3,7 @@ <script src="../http/tests/inspector/inspector-test.js"></script> <script src="../http/tests/inspector/timeline-test.js"></script> <script src="profiler/profiler-test.js"></script> -<script src="audits/audits-test.js"></script> +<script src="../http/tests/inspector/audits-test.js"></script> <script> function test()
diff --git a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt index b743349..4289e61 100644 --- a/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/mac/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7369,63 +7369,9 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix +interface WebKitCSSMatrix : DOMMatrixReadOnly attribute @@toStringTag - getter a - getter b - getter c - getter d - getter e - getter f - getter m11 - getter m12 - getter m13 - getter m14 - getter m21 - getter m22 - getter m23 - getter m24 - getter m31 - getter m32 - getter m33 - getter m34 - getter m41 - getter m42 - getter m43 - getter m44 method constructor - method inverse - method multiply - method rotate - method rotateAxisAngle - method scale - method setMatrixValue - method skewX - method skewY - method toString - method translate - setter a - setter b - setter c - setter d - setter e - setter f - setter m11 - setter m12 - setter m13 - setter m14 - setter m21 - setter m22 - setter m23 - setter m24 - setter m31 - setter m32 - setter m33 - setter m34 - setter m41 - setter m42 - setter m43 - setter m44 interface WebKitMutationObserver attribute @@toStringTag method constructor
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt index ff81a8a..f88813a 100644 --- a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -7298,63 +7298,9 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix +interface WebKitCSSMatrix : DOMMatrixReadOnly attribute @@toStringTag - getter a - getter b - getter c - getter d - getter e - getter f - getter m11 - getter m12 - getter m13 - getter m14 - getter m21 - getter m22 - getter m23 - getter m24 - getter m31 - getter m32 - getter m33 - getter m34 - getter m41 - getter m42 - getter m43 - getter m44 method constructor - method inverse - method multiply - method rotate - method rotateAxisAngle - method scale - method setMatrixValue - method skewX - method skewY - method toString - method translate - setter a - setter b - setter c - setter d - setter e - setter f - setter m11 - setter m12 - setter m13 - setter m14 - setter m21 - setter m22 - setter m23 - setter m24 - setter m31 - setter m32 - setter m33 - setter m34 - setter m41 - setter m42 - setter m43 - setter m44 interface WebKitMutationObserver attribute @@toStringTag method constructor
diff --git a/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png b/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png index cdd5578c..ba6d122 100644 --- a/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png +++ b/third_party/WebKit/LayoutTests/transforms/3d/general/cssmatrix-3d-zoom-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt index fb5cb01..66b3e49c 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface-expected.txt
@@ -23,7 +23,7 @@ PASS a3[1] is "" Test bad input to string constructor -PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'banana'.. +PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. Test attributes on default matrix PASS m.a is 1 @@ -58,9 +58,9 @@ PASS m.f is 20 Test throwing exception from setMatrixValue -PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'banana'.. -PASS m.setMatrixValue("translate(10em, 20%)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': The transformation depends on the box size, which is not supported.. -PASS m.setMatrixValue("translate(10px, 20px) scale()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate(10px, 20px) scale()'.. +PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. +PASS m.setMatrixValue("translate(10em, 20%)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Lengths must be absolute, not relative. +PASS m.setMatrixValue("translate(10px, 20px) scale()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate(10px, 20px) scale()'.. Test attributes on translate() and accumulation PASS m2.a is 1 @@ -189,7 +189,12 @@ PASS sx.f is 0 Test multiply with missing argument -PASS m2 is null +PASS m2.a is 1 +PASS m2.b is 2 +PASS m2.c is 3 +PASS m2.d is 4 +PASS m2.e is 5 +PASS m2.f is 6 Test inverse PASS parseFloat(m2.a) is 0.5 @@ -207,8 +212,21 @@ PASS parseFloat(m.e) is 10 PASS parseFloat(m.f) is 20 -Test throwing exception from inverse -PASS m.inverse() threw exception NotSupportedError: Failed to execute 'inverse' on 'WebKitCSSMatrix': The matrix is not invertable.. +Test not invertible matrix +PASS m2.a is NaN +PASS m2.b is NaN +PASS m2.c is NaN +PASS m2.d is NaN +PASS m2.e is NaN +PASS m2.f is NaN + +Test immutability of inverse +PASS m.a is 0 +PASS m.b is 0 +PASS m.c is 0 +PASS m.d is 0 +PASS m.e is 0 +PASS m.f is 0 PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml index cc85536..ed7b00c 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-2d-interface.xhtml
@@ -255,7 +255,12 @@ debug("Test multiply with missing argument"); m = new WebKitCSSMatrix("matrix(1, 2, 3, 4, 5, 6)"); m2 = m.multiply(); -shouldBe('m2', 'null'); +shouldBe('m2.a', '1'); +shouldBe('m2.b', '2'); +shouldBe('m2.c', '3'); +shouldBe('m2.d', '4'); +shouldBe('m2.e', '5'); +shouldBe('m2.f', '6'); debug(""); debug("Test inverse"); @@ -279,9 +284,25 @@ shouldBe('parseFloat(m.f)', '20'); debug(""); -debug("Test throwing exception from inverse"); +debug("Test not invertible matrix"); m = new WebKitCSSMatrix("matrix(0, 0, 0, 0, 0, 0)"); // not invertible -shouldThrow('m.inverse()'); +m2 = m.inverse(); + +shouldBeNaN('m2.a'); +shouldBeNaN('m2.b'); +shouldBeNaN('m2.c'); +shouldBeNaN('m2.d'); +shouldBeNaN('m2.e'); +shouldBeNaN('m2.f'); + +debug(""); +debug("Test immutability of inverse"); +shouldBe('m.a', '0'); +shouldBe('m.b', '0'); +shouldBe('m.c', '0'); +shouldBe('m.d', '0'); +shouldBe('m.e', '0'); +shouldBe('m.f', '0'); debug("");
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt index 247a66d..3563c33 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface-expected.txt
@@ -29,7 +29,7 @@ PASS a3[1] is "" Test bad input to string constructor -PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'WebKitCSSMatrix': Failed to parse 'banana'.. +PASS new WebKitCSSMatrix("banana") threw exception SyntaxError: Failed to construct 'DOMMatrix': Failed to parse 'banana'.. Test attributes on default matrix PASS m.m11 is 1 @@ -104,9 +104,9 @@ PASS m.m44 is 1 Test throwing exception from setMatrixValue -PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'banana'.. -PASS m.setMatrixValue("translate3d(10em, 20%, 40)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate3d(10em, 20%, 40)'.. -PASS m.setMatrixValue("translate3d(10px, 20px, 30px) scale3d()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'WebKitCSSMatrix': Failed to parse 'translate3d(10px, 20px, 30px) scale3d()'.. +PASS m.setMatrixValue("banana") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'banana'.. +PASS m.setMatrixValue("translate3d(10em, 20%, 40)") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10em, 20%, 40)'.. +PASS m.setMatrixValue("translate3d(10px, 20px, 30px) scale3d()") threw exception SyntaxError: Failed to execute 'setMatrixValue' on 'DOMMatrix': Failed to parse 'translate3d(10px, 20px, 30px) scale3d()'.. Test multiply PASS parseFloat(m3.m11) is 538 @@ -216,8 +216,41 @@ PASS parseFloat(m.m43) is 30 PASS parseFloat(m.m44) is 1 -Test throwing exception from inverse -PASS m.inverse() threw exception NotSupportedError: Failed to execute 'inverse' on 'WebKitCSSMatrix': The matrix is not invertable.. +Test not invertible 3d matrix +PASS m2.m11 is NaN +PASS m2.m12 is NaN +PASS m2.m13 is NaN +PASS m2.m14 is NaN +PASS m2.m21 is NaN +PASS m2.m22 is NaN +PASS m2.m23 is NaN +PASS m2.m24 is NaN +PASS m2.m31 is NaN +PASS m2.m32 is NaN +PASS m2.m33 is NaN +PASS m2.m34 is NaN +PASS m2.m41 is NaN +PASS m2.m42 is NaN +PASS m2.m43 is NaN +PASS m2.m44 is NaN + +Test immutability of inverse +PASS m.m11 is 0 +PASS m.m12 is 0 +PASS m.m13 is 0 +PASS m.m14 is 0 +PASS m.m21 is 0 +PASS m.m22 is 0 +PASS m.m23 is 0 +PASS m.m24 is 0 +PASS m.m31 is 0 +PASS m.m32 is 0 +PASS m.m33 is 0 +PASS m.m34 is 0 +PASS m.m41 is 0 +PASS m.m42 is 0 +PASS m.m43 is 0 +PASS m.m44 is 0 Test translate PASS m2.m11 is 1
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml index 392949f..2ea85b43 100644 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml +++ b/third_party/WebKit/LayoutTests/transforms/cssmatrix-3d-interface.xhtml
@@ -277,9 +277,45 @@ shouldBe('parseFloat(m.m44)', '1'); debug(""); -debug("Test throwing exception from inverse"); +debug("Test not invertible 3d matrix"); m = new WebKitCSSMatrix("matrix3d(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)"); // not invertible -shouldThrow('m.inverse()'); +m2 = m.inverse(); + +shouldBeNaN('m2.m11'); +shouldBeNaN('m2.m12'); +shouldBeNaN('m2.m13'); +shouldBeNaN('m2.m14'); +shouldBeNaN('m2.m21'); +shouldBeNaN('m2.m22'); +shouldBeNaN('m2.m23'); +shouldBeNaN('m2.m24'); +shouldBeNaN('m2.m31'); +shouldBeNaN('m2.m32'); +shouldBeNaN('m2.m33'); +shouldBeNaN('m2.m34'); +shouldBeNaN('m2.m41'); +shouldBeNaN('m2.m42'); +shouldBeNaN('m2.m43'); +shouldBeNaN('m2.m44'); + +debug(""); +debug("Test immutability of inverse"); +shouldBe('m.m11', '0'); +shouldBe('m.m12', '0'); +shouldBe('m.m13', '0'); +shouldBe('m.m14', '0'); +shouldBe('m.m21', '0'); +shouldBe('m.m22', '0'); +shouldBe('m.m23', '0'); +shouldBe('m.m24', '0'); +shouldBe('m.m31', '0'); +shouldBe('m.m32', '0'); +shouldBe('m.m33', '0'); +shouldBe('m.m34', '0'); +shouldBe('m.m41', '0'); +shouldBe('m.m42', '0'); +shouldBe('m.m43', '0'); +shouldBe('m.m44', '0'); debug(""); debug("Test translate");
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt deleted file mode 100644 index ddad5eaf..0000000 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -PASS if no crash
diff --git a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html b/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html deleted file mode 100644 index ad928d2..0000000 --- a/third_party/WebKit/LayoutTests/transforms/cssmatrix-crash.html +++ /dev/null
@@ -1,9 +0,0 @@ -<!DOCTYPE html> -<script> -if (window.testRunner) - testRunner.dumpAsText(); - -new WebKitCSSMatrix("translateX(1ex)"); -new WebKitCSSMatrix("translateX(1ch)"); -</script> -<p>PASS if no crash</p>
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt index 22f8ae8..c9903255 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload-disabled/webexposed/global-interface-listing-expected.txt
@@ -8495,7 +8495,7 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix +interface WebKitCSSMatrix : DOMMatrixReadOnly attribute @@toStringTag getter a getter b @@ -8520,16 +8520,18 @@ getter m43 getter m44 method constructor - method inverse - method multiply - method rotate - method rotateAxisAngle - method scale + method invertSelf + method multiplySelf + method preMultiplySelf + method rotateAxisAngleSelf + method rotateFromVectorSelf + method rotateSelf + method scale3dSelf + method scaleSelf method setMatrixValue - method skewX - method skewY - method toString - method translate + method skewXSelf + method skewYSelf + method translateSelf setter a setter b setter c
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index a0f6f0de..eca5b15 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -8503,7 +8503,7 @@ getter animationName getter elapsedTime method constructor -interface WebKitCSSMatrix +interface WebKitCSSMatrix : DOMMatrixReadOnly attribute @@toStringTag getter a getter b @@ -8528,16 +8528,18 @@ getter m43 getter m44 method constructor - method inverse - method multiply - method rotate - method rotateAxisAngle - method scale + method invertSelf + method multiplySelf + method preMultiplySelf + method rotateAxisAngleSelf + method rotateFromVectorSelf + method rotateSelf + method scale3dSelf + method scaleSelf method setMatrixValue - method skewX - method skewY - method toString - method translate + method skewXSelf + method skewYSelf + method translateSelf setter a setter b setter c
diff --git a/third_party/WebKit/Source/core/core_idl_files.gni b/third_party/WebKit/Source/core/core_idl_files.gni index 63aa5c8..36809bdc 100644 --- a/third_party/WebKit/Source/core/core_idl_files.gni +++ b/third_party/WebKit/Source/core/core_idl_files.gni
@@ -62,7 +62,6 @@ "css/StyleMedia.idl", "css/StyleSheet.idl", "css/StyleSheetList.idl", - "css/WebKitCSSMatrix.idl", "css/cssom/CSSImageValue.idl", "css/cssom/CSSKeywordValue.idl", "css/cssom/CSSMatrixComponent.idl",
diff --git a/third_party/WebKit/Source/core/css/BUILD.gn b/third_party/WebKit/Source/core/css/BUILD.gn index 827bc67f..32af1bf 100644 --- a/third_party/WebKit/Source/core/css/BUILD.gn +++ b/third_party/WebKit/Source/core/css/BUILD.gn
@@ -94,8 +94,6 @@ "CSSKeyframesRule.h", "CSSMarkup.cpp", "CSSMarkup.h", - "CSSMatrix.cpp", - "CSSMatrix.h", "CSSMediaRule.cpp", "CSSMediaRule.h", "CSSNamespaceRule.cpp",
diff --git a/third_party/WebKit/Source/core/css/CSSMatrix.cpp b/third_party/WebKit/Source/core/css/CSSMatrix.cpp deleted file mode 100644 index c123e4b..0000000 --- a/third_party/WebKit/Source/core/css/CSSMatrix.cpp +++ /dev/null
@@ -1,208 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "core/css/CSSMatrix.h" - -#include "bindings/core/v8/ExceptionState.h" -#include "core/CSSPropertyNames.h" -#include "core/CSSValueKeywords.h" -#include "core/css/CSSIdentifierValue.h" -#include "core/css/CSSToLengthConversionData.h" -#include "core/css/StylePropertySet.h" -#include "core/css/parser/CSSParser.h" -#include "core/css/resolver/TransformBuilder.h" -#include "core/dom/ExceptionCode.h" -#include "core/frame/UseCounter.h" -#include "core/layout/api/LayoutViewItem.h" -#include "core/style/ComputedStyle.h" -#include "platform/wtf/MathExtras.h" - -namespace blink { - -CSSMatrix* CSSMatrix::Create(ExecutionContext* execution_context, - const String& s, - ExceptionState& exception_state) { - UseCounter::Count(execution_context, WebFeature::kWebKitCSSMatrix); - if (!s.IsEmpty()) { - UseCounter::Count(execution_context, - WebFeature::kWebkitCSSMatrixConstructFromString); - } - return new CSSMatrix(s, exception_state); -} - -CSSMatrix::CSSMatrix(const TransformationMatrix& m) - : matrix_(TransformationMatrix::Create(m)) {} - -CSSMatrix::CSSMatrix(const String& s, ExceptionState& exception_state) - : matrix_(TransformationMatrix::Create()) { - setMatrixValue(s, exception_state); -} - -static inline PassRefPtr<ComputedStyle> CreateInitialStyle() { - RefPtr<ComputedStyle> initial_style = ComputedStyle::Create(); - initial_style->GetFont().Update(nullptr); - return initial_style; -} - -void CSSMatrix::setMatrixValue(const String& string, - ExceptionState& exception_state) { - if (string.IsEmpty()) - return; - - if (const CSSValue* value = - CSSParser::ParseSingleValue(CSSPropertyTransform, string)) { - // Check for a "none" transform. In these cases we can use the default - // identity matrix. - if (value->IsIdentifierValue() && - (ToCSSIdentifierValue(value))->GetValueID() == CSSValueNone) - return; - - DEFINE_STATIC_REF(ComputedStyle, initial_style, CreateInitialStyle()); - TransformOperations operations = - TransformBuilder::CreateTransformOperations( - *value, CSSToLengthConversionData(initial_style, initial_style, - LayoutViewItem(nullptr), 1.0f)); - - // Convert transform operations to a TransformationMatrix. This can fail - // if a param has a percentage ('%') - if (operations.DependsOnBoxSize()) - exception_state.ThrowDOMException(kSyntaxError, - "The transformation depends on the box " - "size, which is not supported."); - matrix_ = TransformationMatrix::Create(); - operations.Apply(FloatSize(0, 0), *matrix_); - } else { // There is something there but parsing failed. - exception_state.ThrowDOMException(kSyntaxError, - "Failed to parse '" + string + "'."); - } -} - -// Perform a concatenation of the matrices (this * secondMatrix) -CSSMatrix* CSSMatrix::multiply(CSSMatrix* second_matrix) const { - if (!second_matrix) - return nullptr; - - return CSSMatrix::Create( - TransformationMatrix(*matrix_).Multiply(*second_matrix->matrix_)); -} - -CSSMatrix* CSSMatrix::inverse(ExceptionState& exception_state) const { - if (!matrix_->IsInvertible()) { - exception_state.ThrowDOMException(kNotSupportedError, - "The matrix is not invertable."); - return nullptr; - } - - return CSSMatrix::Create(matrix_->Inverse()); -} - -CSSMatrix* CSSMatrix::translate(double x, double y, double z) const { - if (std::isnan(x)) - x = 0; - if (std::isnan(y)) - y = 0; - if (std::isnan(z)) - z = 0; - return CSSMatrix::Create(TransformationMatrix(*matrix_).Translate3d(x, y, z)); -} - -CSSMatrix* CSSMatrix::scale(double scale_x, - double scale_y, - double scale_z) const { - if (std::isnan(scale_x)) - scale_x = 1; - if (std::isnan(scale_y)) - scale_y = scale_x; - if (std::isnan(scale_z)) - scale_z = 1; - return CSSMatrix::Create( - TransformationMatrix(*matrix_).Scale3d(scale_x, scale_y, scale_z)); -} - -CSSMatrix* CSSMatrix::rotate(double rot_x, double rot_y, double rot_z) const { - if (std::isnan(rot_x)) - rot_x = 0; - - if (std::isnan(rot_y) && std::isnan(rot_z)) { - rot_z = rot_x; - rot_x = 0; - rot_y = 0; - } - - if (std::isnan(rot_y)) - rot_y = 0; - if (std::isnan(rot_z)) - rot_z = 0; - return CSSMatrix::Create( - TransformationMatrix(*matrix_).Rotate3d(rot_x, rot_y, rot_z)); -} - -CSSMatrix* CSSMatrix::rotateAxisAngle(double x, - double y, - double z, - double angle) const { - if (std::isnan(x)) - x = 0; - if (std::isnan(y)) - y = 0; - if (std::isnan(z)) - z = 0; - if (std::isnan(angle)) - angle = 0; - if (!x && !y && !z) - z = 1; - return CSSMatrix::Create( - TransformationMatrix(*matrix_).Rotate3d(x, y, z, angle)); -} - -CSSMatrix* CSSMatrix::skewX(double angle) const { - if (std::isnan(angle)) - angle = 0; - return CSSMatrix::Create(TransformationMatrix(*matrix_).SkewX(angle)); -} - -CSSMatrix* CSSMatrix::skewY(double angle) const { - if (std::isnan(angle)) - angle = 0; - return CSSMatrix::Create(TransformationMatrix(*matrix_).SkewY(angle)); -} - -String CSSMatrix::toString() const { - // FIXME - Need to ensure valid CSS floating point values - // (https://bugs.webkit.org/show_bug.cgi?id=20674) - if (matrix_->IsAffine()) - return String::Format("matrix(%g, %g, %g, %g, %g, %g)", matrix_->A(), - matrix_->B(), matrix_->C(), matrix_->D(), - matrix_->E(), matrix_->F()); - return String::Format( - "matrix3d(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, " - "%g)", - matrix_->M11(), matrix_->M12(), matrix_->M13(), matrix_->M14(), - matrix_->M21(), matrix_->M22(), matrix_->M23(), matrix_->M24(), - matrix_->M31(), matrix_->M32(), matrix_->M33(), matrix_->M34(), - matrix_->M41(), matrix_->M42(), matrix_->M43(), matrix_->M44()); -} - -} // namespace blink
diff --git a/third_party/WebKit/Source/core/css/CSSMatrix.h b/third_party/WebKit/Source/core/css/CSSMatrix.h deleted file mode 100644 index 1c25efb2..0000000 --- a/third_party/WebKit/Source/core/css/CSSMatrix.h +++ /dev/null
@@ -1,171 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CSSMatrix_h -#define CSSMatrix_h - -#include <memory> -#include "platform/bindings/ScriptWrappable.h" -#include "platform/transforms/TransformationMatrix.h" -#include "platform/wtf/text/WTFString.h" - -namespace blink { - -class ExceptionState; -class ExecutionContext; - -class CSSMatrix final : public GarbageCollectedFinalized<CSSMatrix>, - public ScriptWrappable { - DEFINE_WRAPPERTYPEINFO(); - - public: - static CSSMatrix* Create(const TransformationMatrix& m) { - return new CSSMatrix(m); - } - static CSSMatrix* Create(ExecutionContext*, const String&, ExceptionState&); - - double a() const { return matrix_->A(); } - double b() const { return matrix_->B(); } - double c() const { return matrix_->C(); } - double d() const { return matrix_->D(); } - double e() const { return matrix_->E(); } - double f() const { return matrix_->F(); } - - void setA(double f) { matrix_->SetA(f); } - void setB(double f) { matrix_->SetB(f); } - void setC(double f) { matrix_->SetC(f); } - void setD(double f) { matrix_->SetD(f); } - void setE(double f) { matrix_->SetE(f); } - void setF(double f) { matrix_->SetF(f); } - - double m11() const { return matrix_->M11(); } - double m12() const { return matrix_->M12(); } - double m13() const { return matrix_->M13(); } - double m14() const { return matrix_->M14(); } - double m21() const { return matrix_->M21(); } - double m22() const { return matrix_->M22(); } - double m23() const { return matrix_->M23(); } - double m24() const { return matrix_->M24(); } - double m31() const { return matrix_->M31(); } - double m32() const { return matrix_->M32(); } - double m33() const { return matrix_->M33(); } - double m34() const { return matrix_->M34(); } - double m41() const { return matrix_->M41(); } - double m42() const { return matrix_->M42(); } - double m43() const { return matrix_->M43(); } - double m44() const { return matrix_->M44(); } - - void setM11(double f) { matrix_->SetM11(f); } - void setM12(double f) { matrix_->SetM12(f); } - void setM13(double f) { matrix_->SetM13(f); } - void setM14(double f) { matrix_->SetM14(f); } - void setM21(double f) { matrix_->SetM21(f); } - void setM22(double f) { matrix_->SetM22(f); } - void setM23(double f) { matrix_->SetM23(f); } - void setM24(double f) { matrix_->SetM24(f); } - void setM31(double f) { matrix_->SetM31(f); } - void setM32(double f) { matrix_->SetM32(f); } - void setM33(double f) { matrix_->SetM33(f); } - void setM34(double f) { matrix_->SetM34(f); } - void setM41(double f) { matrix_->SetM41(f); } - void setM42(double f) { matrix_->SetM42(f); } - void setM43(double f) { matrix_->SetM43(f); } - void setM44(double f) { matrix_->SetM44(f); } - - void setMatrixValue(const String&, ExceptionState&); - - // The following math function return a new matrix with the - // specified operation applied. The this value is not modified. - - // Multiply this matrix by secondMatrix, on the right - // (result = this * secondMatrix) - CSSMatrix* multiply(CSSMatrix* second_matrix) const; - - // Return the inverse of this matrix. Throw an exception if the matrix is not - // invertible. - CSSMatrix* inverse(ExceptionState&) const; - - // Return this matrix translated by the passed values. - // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D - // operations. - // Operation is performed as though the this matrix is multiplied by a matrix - // with the translation values on the left - // (result = translation(x,y,z) * this) - CSSMatrix* translate(double x, double y, double z) const; - - // Returns this matrix scaled by the passed values. - // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of - // NaN makes it the same as scaleX. This allows the 3D form to used for 2D - // operations Operation is performed as though the this matrix is multiplied - // by a matrix with the scale values on the left - // (result = scale(x,y,z) * this) - CSSMatrix* scale(double scale_x, double scale_y, double scale_z) const; - - // Returns this matrix rotated by the passed values. - // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). - // Otherwise use a rotation value of 0 for any passed NaN. - // Operation is performed as though the this matrix is multiplied by a matrix - // with the rotation values on the left (result = rotation(x,y,z) * this) - CSSMatrix* rotate(double rot_x, double rot_y, double rot_z) const; - - // Returns this matrix rotated about the passed axis by the passed angle. - // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value - // Operation is performed as though the this matrix is multiplied by a matrix - // with the rotation values on the left - // (result = rotation(x,y,z,angle) * this) - CSSMatrix* rotateAxisAngle(double x, double y, double z, double angle) const; - - // Return this matrix skewed along the X axis by the passed values. - // Passing a NaN will use a value of 0. - // Operation is performed as though the this matrix is multiplied by a matrix - // with the skew values on the left (result = skewX(angle) * this) - CSSMatrix* skewX(double angle) const; - - // Return this matrix skewed along the Y axis by the passed values. - // Passing a NaN will use a value of 0. - // Operation is performed as though the this matrix is multiplied by a matrix - // with the skew values on the left (result = skewY(angle) * this) - CSSMatrix* skewY(double angle) const; - - const TransformationMatrix& Transform() const { return *matrix_; } - - String toString() const; - - DEFINE_INLINE_TRACE() {} - - protected: - CSSMatrix(const TransformationMatrix&); - CSSMatrix(const String&, ExceptionState&); - - // TransformationMatrix needs to be 16-byte aligned. PartitionAlloc - // supports 16-byte alignment but Oilpan doesn't. So we use an std::unique_ptr - // to allocate TransformationMatrix on PartitionAlloc. - // TODO(oilpan): Oilpan should support 16-byte aligned allocations. - std::unique_ptr<TransformationMatrix> matrix_; -}; - -} // namespace blink - -#endif // CSSMatrix_h
diff --git a/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl b/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl deleted file mode 100644 index d9227cf0..0000000 --- a/third_party/WebKit/Source/core/css/WebKitCSSMatrix.idl +++ /dev/null
@@ -1,104 +0,0 @@ -/* - * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// Introduced in DOM Level ?: -[ - Constructor(optional DOMString cssValue = null), - ConstructorCallWith=ExecutionContext, - ImplementedAs=CSSMatrix, - RaisesException=Constructor, -] interface WebKitCSSMatrix { - - // These attributes are simple aliases for certain elements of the 4x4 matrix - attribute unrestricted double a; // alias for m11 - attribute unrestricted double b; // alias for m12 - attribute unrestricted double c; // alias for m21 - attribute unrestricted double d; // alias for m22 - attribute unrestricted double e; // alias for m41 - attribute unrestricted double f; // alias for m42 - - attribute unrestricted double m11; - attribute unrestricted double m12; - attribute unrestricted double m13; - attribute unrestricted double m14; - attribute unrestricted double m21; - attribute unrestricted double m22; - attribute unrestricted double m23; - attribute unrestricted double m24; - attribute unrestricted double m31; - attribute unrestricted double m32; - attribute unrestricted double m33; - attribute unrestricted double m34; - attribute unrestricted double m41; - attribute unrestricted double m42; - attribute unrestricted double m43; - attribute unrestricted double m44; - - [RaisesException, MeasureAs=WebkitCSSMatrixSetMatrixValue] void setMatrixValue([Default=Undefined] optional DOMString string); - - // Multiply this matrix by secondMatrix, on the right (result = this * secondMatrix) - [LegacyInterfaceTypeChecking] WebKitCSSMatrix multiply([Default=Undefined] optional WebKitCSSMatrix secondMatrix); - - // Return the inverse of this matrix. Throw an exception if the matrix is not invertible - [RaisesException] WebKitCSSMatrix inverse(); - - // Return this matrix translated by the passed values. - // Passing a NaN will use a value of 0. This allows the 3D form to used for 2D operations - WebKitCSSMatrix translate([Default=Undefined] optional unrestricted double x, - [Default=Undefined] optional unrestricted double y, - [Default=Undefined] optional unrestricted double z); - - // Returns this matrix scaled by the passed values. - // Passing scaleX or scaleZ as NaN uses a value of 1, but passing scaleY of NaN - // makes it the same as scaleX. This allows the 3D form to used for 2D operations - WebKitCSSMatrix scale([Default=Undefined] optional unrestricted double scaleX, - [Default=Undefined] optional unrestricted double scaleY, - [Default=Undefined] optional unrestricted double scaleZ); - - // Returns this matrix rotated by the passed values. - // If rotY and rotZ are NaN, rotate about Z (rotX=0, rotateY=0, rotateZ=rotX). - // Otherwise use a rotation value of 0 for any passed NaN. - WebKitCSSMatrix rotate([Default=Undefined] optional unrestricted double rotX, - [Default=Undefined] optional unrestricted double rotY, - [Default=Undefined] optional unrestricted double rotZ); - - // Returns this matrix rotated about the passed axis by the passed angle. - // Passing a NaN will use a value of 0. If the axis is (0,0,0) use a value - // of (0,0,1). - WebKitCSSMatrix rotateAxisAngle([Default=Undefined] optional unrestricted double x, - [Default=Undefined] optional unrestricted double y, - [Default=Undefined] optional unrestricted double z, - [Default=Undefined] optional unrestricted double angle); - - // Returns this matrix skewed along the X axis by the passed values. - // Passing a NaN will use a value of 0. - WebKitCSSMatrix skewX([Default=Undefined] optional unrestricted double angle); - - // Returns this matrix skewed along the Y axis by the passed values. - // Passing a NaN will use a value of 0. - WebKitCSSMatrix skewY([Default=Undefined] optional unrestricted double angle); - - [NotEnumerable] stringifier; -};
diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp index bcf1820..61e9ade 100644 --- a/third_party/WebKit/Source/core/dom/Document.cpp +++ b/third_party/WebKit/Source/core/dom/Document.cpp
@@ -4930,20 +4930,27 @@ return; } - OriginAccessEntry access_entry(GetSecurityOrigin()->Protocol(), new_domain, - OriginAccessEntry::kAllowSubdomains); - OriginAccessEntry::MatchResult result = - access_entry.MatchesOrigin(*GetSecurityOrigin()); - if (result == OriginAccessEntry::kDoesNotMatchOrigin) { - exception_state.ThrowSecurityError( - "'" + new_domain + "' is not a suffix of '" + domain() + "'."); - return; - } + // TODO(mkwst): If we decide to ship this, change the IDL file to make the + // value nullable (via `TreatNullAs=NullString`, for example). For the moment, + // just rely on JavaScript's inherent nuttiness for implicit conversion to the + // string "null". https://crbug.com/733150 + if (!RuntimeEnabledFeatures::NullableDocumentDomainEnabled() || + new_domain != "null") { + OriginAccessEntry access_entry(GetSecurityOrigin()->Protocol(), new_domain, + OriginAccessEntry::kAllowSubdomains); + OriginAccessEntry::MatchResult result = + access_entry.MatchesOrigin(*GetSecurityOrigin()); + if (result == OriginAccessEntry::kDoesNotMatchOrigin) { + exception_state.ThrowSecurityError( + "'" + new_domain + "' is not a suffix of '" + domain() + "'."); + return; + } - if (result == OriginAccessEntry::kMatchesOriginButIsPublicSuffix) { - exception_state.ThrowSecurityError("'" + new_domain + - "' is a top-level domain."); - return; + if (result == OriginAccessEntry::kMatchesOriginButIsPublicSuffix) { + exception_state.ThrowSecurityError("'" + new_domain + + "' is a top-level domain."); + return; + } } if (frame_) {
diff --git a/third_party/WebKit/Source/core/frame/LocalFrame.cpp b/third_party/WebKit/Source/core/frame/LocalFrame.cpp index 6e6ca09..214a622 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrame.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrame.cpp
@@ -458,6 +458,18 @@ // Notify ScriptController that the frame is closing, since its cleanup ends // up calling back to LocalFrameClient via WindowProxy. GetScriptController().ClearForClose(); + + // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. + // It seems to crash because Frame is detached before LocalFrameView. + // Verify here that any LocalFrameView has been detached by now. + CHECK(!view_->IsAttached()); + if (HTMLFrameOwnerElement* owner = DeprecatedLocalOwner()) { + if (EmbeddedContentView* owner_view = owner->OwnedEmbeddedContentView()) { + CHECK(!owner_view->IsAttached()); + CHECK_EQ(owner_view, view_); + } + } + SetView(nullptr); page_->GetEventHandlerRegistry().DidRemoveAllEventHandlers(*DomWindow());
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp index bdbd0a6..2da8988 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.cpp +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.cpp
@@ -241,6 +241,7 @@ DEFINE_TRACE(LocalFrameView) { visitor->Trace(frame_); + visitor->Trace(parent_); visitor->Trace(fragment_anchor_); visitor->Trace(scrollable_areas_); visitor->Trace(animating_scrollable_areas_); @@ -3884,9 +3885,17 @@ } void LocalFrameView::AttachToLayout() { - DCHECK(!is_attached_); + CHECK(!is_attached_); is_attached_ = true; - if (ParentFrameView()->IsVisible()) + parent_ = ParentFrameView(); + if (!parent_) { + Frame* parent_frame = frame_->Tree().Parent(); + CHECK(parent_frame); + CHECK(parent_frame->IsLocalFrame()); + CHECK(parent_frame->View()); + } + CHECK(parent_); + if (parent_->IsVisible()) SetParentVisible(true); UpdateParentScrollableAreaSet(); SetupRenderThrottling(); @@ -3894,9 +3903,18 @@ } void LocalFrameView::DetachFromLayout() { - DCHECK(is_attached_); + // TODO(crbug.com/729196): Trace why LocalFrameView::DetachFromLayout crashes. + CHECK(is_attached_); + LocalFrameView* parent = ParentFrameView(); + if (!parent) { + Frame* parent_frame = frame_->Tree().Parent(); + CHECK(parent_frame); + CHECK(parent_frame->IsLocalFrame()); + CHECK(parent_frame->View()); + } + CHECK(parent == parent_); if (!RuntimeEnabledFeatures::RootLayerScrollingEnabled()) - ParentFrameView()->RemoveScrollableArea(this); + parent->RemoveScrollableArea(this); SetParentVisible(false); is_attached_ = false; }
diff --git a/third_party/WebKit/Source/core/frame/LocalFrameView.h b/third_party/WebKit/Source/core/frame/LocalFrameView.h index 9265043..fbc737c 100644 --- a/third_party/WebKit/Source/core/frame/LocalFrameView.h +++ b/third_party/WebKit/Source/core/frame/LocalFrameView.h
@@ -1064,6 +1064,7 @@ EmbeddedObjectSet part_update_set_; Member<LocalFrame> frame_; + Member<LocalFrameView> parent_; IntRect frame_rect_; bool is_attached_;
diff --git a/third_party/WebKit/Source/core/frame/Window.idl b/third_party/WebKit/Source/core/frame/Window.idl index 3434eb3..f610832 100644 --- a/third_party/WebKit/Source/core/frame/Window.idl +++ b/third_party/WebKit/Source/core/frame/Window.idl
@@ -204,6 +204,8 @@ // https://w3c.github.io/webappsec/specs/powerfulfeatures/#monkey-patching-global-object readonly attribute boolean isSecureContext; + + attribute DOMMatrixConstructor WebKitCSSMatrix; }; // https://html.spec.whatwg.org/#transferable-objects
diff --git a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp index 7be507d..96ec2377 100644 --- a/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/FrameFetchContext.cpp
@@ -949,7 +949,11 @@ GetSecurityOrigin())) { CountDeprecation( WebFeature::kRequestedSubresourceWithEmbeddedCredentials); - return true; + + // TODO(mkwst): Remove the runtime check one way or the other once we're + // sure it's going to stick (or that it's not). + if (RuntimeEnabledFeatures::BlockCredentialedSubresourcesEnabled()) + return true; } } return false;
diff --git a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp index f502d93..2faf3de 100644 --- a/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp +++ b/third_party/WebKit/Source/core/loader/WorkerFetchContext.cpp
@@ -161,7 +161,11 @@ if (Url().User() != url.User() || Url().Pass() != url.Pass()) { CountDeprecation( WebFeature::kRequestedSubresourceWithEmbeddedCredentials); - return true; + + // TODO(mkwst): Remove the runtime check one way or the other once we're + // sure it's going to stick (or that it's not). + if (RuntimeEnabledFeatures::BlockCredentialedSubresourcesEnabled()) + return true; } } return false;
diff --git a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp index 7f5f3a37..df25107b 100644 --- a/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/BarcodeDetector.cpp
@@ -54,15 +54,15 @@ HeapVector<Point2D> corner_points; for (const auto& corner_point : barcode->corner_points) { Point2D point; - point.setX(corner_point->x); - point.setY(corner_point->y); + point.setX(corner_point.x); + point.setY(corner_point.y); corner_points.push_back(point); } detected_barcodes.push_back(DetectedBarcode::Create( barcode->raw_value, - DOMRect::Create(barcode->bounding_box->x, barcode->bounding_box->y, - barcode->bounding_box->width, - barcode->bounding_box->height), + DOMRect::Create(barcode->bounding_box.x, barcode->bounding_box.y, + barcode->bounding_box.width, + barcode->bounding_box.height), corner_points)); }
diff --git a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp index 2f5c485..148fed7 100644 --- a/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/FaceDetector.cpp
@@ -65,8 +65,8 @@ HeapVector<Landmark> landmarks; for (const auto& landmark : face->landmarks) { Point2D location; - location.setX(landmark->location->x); - location.setY(landmark->location->y); + location.setX(landmark->location.x); + location.setY(landmark->location.y); Landmark web_landmark; web_landmark.setLocation(location); if (landmark->type == shape_detection::mojom::blink::LandmarkType::EYE) { @@ -79,8 +79,8 @@ } detected_faces.push_back(DetectedFace::Create( - DOMRect::Create(face->bounding_box->x, face->bounding_box->y, - face->bounding_box->width, face->bounding_box->height), + DOMRect::Create(face->bounding_box.x, face->bounding_box.y, + face->bounding_box.width, face->bounding_box.height), landmarks)); }
diff --git a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp index 1d6ad27..45e49a0 100644 --- a/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp +++ b/third_party/WebKit/Source/modules/shapedetection/TextDetector.cpp
@@ -51,9 +51,8 @@ for (const auto& text : text_detection_results) { detected_text.push_back(DetectedText::Create( text->raw_value, - DOMRect::Create(text->bounding_box->x, text->bounding_box->y, - text->bounding_box->width, - text->bounding_box->height))); + DOMRect::Create(text->bounding_box.x, text->bounding_box.y, + text->bounding_box.width, text->bounding_box.height))); } resolver->Resolve(detected_text);
diff --git a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 index 820ce875..702918c 100644 --- a/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5 +++ b/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.json5
@@ -116,6 +116,10 @@ status: "test", }, { + name: "BlockCredentialedSubresources", + status: "stable", + }, + { name: "BlockLegacySubresources", status: "stable", }, @@ -725,6 +729,10 @@ status: "stable", }, { + name: "NullableDocumentDomain", + status: "experimental", + }, + { name: "OffMainThreadFetch", }, {
diff --git a/third_party/WebKit/Source/platform/mojo/Geometry.typemap b/third_party/WebKit/Source/platform/mojo/Geometry.typemap index 3e1e17d..4b35c2f 100644 --- a/third_party/WebKit/Source/platform/mojo/Geometry.typemap +++ b/third_party/WebKit/Source/platform/mojo/Geometry.typemap
@@ -3,7 +3,11 @@ # found in the LICENSE file. mojom = "//ui/gfx/geometry/mojo/geometry.mojom" -public_headers = [ "//third_party/WebKit/public/platform/WebSize.h" ] +public_headers = [ + "//third_party/WebKit/public/platform/WebFloatRect.h", + "//third_party/WebKit/public/platform/WebFloatPoint.h", + "//third_party/WebKit/public/platform/WebSize.h", +] traits_headers = [ "//third_party/WebKit/Source/platform/mojo/GeometryStructTraits.h", "//ui/gfx/geometry/mojo/geometry_struct_traits.h", @@ -17,4 +21,8 @@ # TODO(zqzhang): ideally, gfx.mojom.Size should be mapped into ::blink::IntSize. # However that introduces an link issue on Windows. See https://crbug.com/653323 -type_mappings = [ "gfx.mojom.Size=::blink::WebSize" ] +type_mappings = [ + "gfx.mojom.PointF=::blink::WebFloatPoint", + "gfx.mojom.RectF=::blink::WebFloatRect", + "gfx.mojom.Size=::blink::WebSize", +]
diff --git a/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.cpp b/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.cpp index 4ec1c2a..fbc1a81 100644 --- a/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.cpp +++ b/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.cpp
@@ -7,6 +7,28 @@ namespace mojo { // static +bool StructTraits<gfx::mojom::RectFDataView, ::blink::WebFloatRect>::Read( + gfx::mojom::RectFDataView data, + ::blink::WebFloatRect* out) { + if (data.width() < 0 || data.height() < 0) + return false; + out->x = data.x(); + out->y = data.y(); + out->width = data.width(); + out->height = data.height(); + return true; +} + +// static +bool StructTraits<gfx::mojom::PointFDataView, ::blink::WebFloatPoint>::Read( + gfx::mojom::PointFDataView data, + ::blink::WebFloatPoint* out) { + out->x = data.x(); + out->y = data.y(); + return true; +} + +// static bool StructTraits<gfx::mojom::SizeDataView, ::blink::WebSize>::Read( gfx::mojom::SizeDataView data, ::blink::WebSize* out) {
diff --git a/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.h b/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.h index b88c3b2..21d4a8f 100644 --- a/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.h +++ b/third_party/WebKit/Source/platform/mojo/GeometryStructTraits.h
@@ -5,12 +5,30 @@ #ifndef GeometryStructTraits_h #define GeometryStructTraits_h +#include "third_party/WebKit/public/platform/WebFloatPoint.h" +#include "third_party/WebKit/public/platform/WebFloatRect.h" #include "third_party/WebKit/public/platform/WebSize.h" #include "ui/gfx/geometry/mojo/geometry.mojom-shared.h" namespace mojo { template <> +struct StructTraits<gfx::mojom::PointFDataView, ::blink::WebFloatPoint> { + static float x(const ::blink::WebFloatPoint& point) { return point.x; } + static float y(const ::blink::WebFloatPoint& point) { return point.y; } + static bool Read(gfx::mojom::PointFDataView, ::blink::WebFloatPoint* out); +}; + +template <> +struct StructTraits<gfx::mojom::RectFDataView, ::blink::WebFloatRect> { + static float x(const ::blink::WebFloatRect& rect) { return rect.x; } + static float y(const ::blink::WebFloatRect& rect) { return rect.y; } + static float width(const ::blink::WebFloatRect& rect) { return rect.width; } + static float height(const ::blink::WebFloatRect& rect) { return rect.height; } + static bool Read(gfx::mojom::RectFDataView, ::blink::WebFloatRect* out); +}; + +template <> struct StructTraits<gfx::mojom::SizeDataView, ::blink::WebSize> { static int width(const ::blink::WebSize& size) { return size.width; } static int height(const ::blink::WebSize& size) { return size.height; }
diff --git a/third_party/WebKit/Source/platform/mojo/GeometryStructTraitsTest.cpp b/third_party/WebKit/Source/platform/mojo/GeometryStructTraitsTest.cpp index 9a48f27f..569c7c7 100644 --- a/third_party/WebKit/Source/platform/mojo/GeometryStructTraitsTest.cpp +++ b/third_party/WebKit/Source/platform/mojo/GeometryStructTraitsTest.cpp
@@ -33,9 +33,9 @@ NOTREACHED(); } - void EchoPointF(gfx::mojom::blink::PointFPtr, EchoPointFCallback) override { - // The type map is not specified. - NOTREACHED(); + void EchoPointF(const WebFloatPoint& p, + EchoPointFCallback callback) override { + std::move(callback).Run(p); } void EchoSize(const WebSize& s, EchoSizeCallback callback) override { @@ -52,9 +52,8 @@ NOTREACHED(); } - void EchoRectF(gfx::mojom::blink::RectFPtr, EchoRectFCallback) override { - // The type map is not specified. - NOTREACHED(); + void EchoRectF(const WebFloatRect& r, EchoRectFCallback callback) override { + std::move(callback).Run(r); } void EchoInsets(gfx::mojom::blink::InsetsPtr, EchoInsetsCallback) override { @@ -100,4 +99,26 @@ EXPECT_EQ(input, output); } +TEST_F(GeometryStructTraitsTest, PointF) { + const float kX = 1.234; + const float kY = 5.678; + WebFloatPoint input(kX, kY); + gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy(); + WebFloatPoint output; + proxy->EchoPointF(input, &output); + EXPECT_EQ(input, output); +} + +TEST_F(GeometryStructTraitsTest, RectF) { + const float kX = 1.234; + const float kY = 2.345; + const float kWidth = 3.456; + const float kHeight = 4.567; + WebFloatRect input(kX, kY, kWidth, kHeight); + gfx::mojom::blink::GeometryTraitsTestServicePtr proxy = GetTraitsTestProxy(); + WebFloatRect output; + proxy->EchoRectF(input, &output); + EXPECT_EQ(input, output); +} + } // namespace blink
diff --git a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp index 1f96326..3ff0ba0 100644 --- a/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp +++ b/third_party/WebKit/Source/platform/weborigin/SecurityOrigin.cpp
@@ -260,8 +260,12 @@ if (host_ == other->host_ && port_ == other->port_) can_access = true; } else if (domain_was_set_in_dom_ && other->domain_was_set_in_dom_) { - if (domain_ == other->domain_) + // TODO(mkwst): If/when we ship this behavior, change this to check + // IsNull() rather than relying on string comparison. + // https://crbug.com/733150 + if (domain_ == other->domain_ && domain_ != "null") { can_access = true; + } } }
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py index d6cbf3a..2260237 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common.py
@@ -16,6 +16,7 @@ WPT_GH_URL = 'https://github.com/%s/%s/' % (WPT_GH_ORG, WPT_GH_REPO_NAME) WPT_GH_SSH_URL_TEMPLATE = 'https://{}@github.com/%s/%s.git' % (WPT_GH_ORG, WPT_GH_REPO_NAME) WPT_REVISION_FOOTER = 'WPT-Export-Revision:' +DEFAULT_COMMIT_HISTORY_WINDOW = 5000 # TODO(qyearsley): This directory should be able to be constructed with # PathFinder and WPT_DEST_NAME, plus the string "external". @@ -28,7 +29,7 @@ _log = logging.getLogger(__name__) -def exportable_commits_since(chromium_commit_hash, host, local_wpt): +def _exportable_commits_since(chromium_commit_hash, host, local_wpt): """Lists exportable commits after a certain point. Args: @@ -55,7 +56,7 @@ return [commit for commit in chromium_commits if is_exportable(commit, local_wpt)] -def exportable_commits_over_last_n_commits(number, host, local_wpt): +def exportable_commits_over_last_n_commits(host, local_wpt, number=DEFAULT_COMMIT_HISTORY_WINDOW): """Lists exportable commits after a certain point. Args: @@ -70,7 +71,7 @@ A list of ChromiumCommit objects for commits that are exportable after the given commit, in chronological order. """ - return exportable_commits_since('HEAD~{}'.format(number + 1), host, local_wpt) + return _exportable_commits_since('HEAD~{}'.format(number + 1), host, local_wpt) def is_exportable(chromium_commit, local_wpt):
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py index e3bfa4e..b1fc2c0 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/common_unittest.py
@@ -7,7 +7,7 @@ from webkitpy.common.host_mock import MockHost from webkitpy.common.system.executive_mock import mock_git_commands from webkitpy.w3c.chromium_commit import ChromiumCommit -from webkitpy.w3c.common import exportable_commits_since +from webkitpy.w3c.common import _exportable_commits_since class MockLocalWPT(object): @@ -31,7 +31,7 @@ 'footers': 'cr-rev-position', }) - commits = exportable_commits_since('beefcafe', host, MockLocalWPT()) + commits = _exportable_commits_since('beefcafe', host, MockLocalWPT()) self.assertEqual(len(commits), 1) self.assertIsInstance(commits[0], ChromiumCommit) self.assertEqual(host.executive.calls, [ @@ -55,7 +55,7 @@ 'footers': 'cr-rev-position', }) - commits = exportable_commits_since('add087a97844f4b9e307d9a216940582d96db306', host, MockLocalWPT()) + commits = _exportable_commits_since('add087a97844f4b9e307d9a216940582d96db306', host, MockLocalWPT()) self.assertEqual(commits, []) self.assertEqual(host.executive.calls, [ ['git', 'rev-parse', '--show-toplevel'], @@ -77,7 +77,7 @@ 'diff-tree': '', }, strict=True) - commits = exportable_commits_since('add087a97844f4b9e307d9a216940582d96db306', host, MockLocalWPT()) + commits = _exportable_commits_since('add087a97844f4b9e307d9a216940582d96db306', host, MockLocalWPT()) self.assertEqual(len(commits), 0) self.assertEqual(host.executive.calls, [ ['git', 'rev-parse', '--show-toplevel'], @@ -98,7 +98,7 @@ 'footers': 'cr-rev-position', }) - commits = exportable_commits_since('beefcafe', host, MockLocalWPT()) + commits = _exportable_commits_since('beefcafe', host, MockLocalWPT()) self.assertEqual(commits, []) self.assertEqual(host.executive.calls, [ ['git', 'rev-parse', '--show-toplevel'],
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py index a9d84ee..3cf8b98 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_copier.py
@@ -92,9 +92,7 @@ cur_dir = root.replace(self.dir_above_repo + '/', '') + '/' _log.debug('Scanning %s...', cur_dir) - # Files in 'tools' are not for browser testing, so we skip them. - # See: http://web-platform-tests.org/writing-tests/general-guidelines.html#tools - dirs_to_skip = ('.git', 'test-plan', 'tools') + dirs_to_skip = ('.git', 'test-plan') if dirs: for name in dirs_to_skip:
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py index be0d919..03764d6e 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter.py
@@ -16,7 +16,6 @@ _log = logging.getLogger(__name__) PR_HISTORY_WINDOW = 100 -COMMIT_HISTORY_WINDOW = 5000 class TestExporter(object): @@ -39,7 +38,7 @@ open_gerrit_cls = self.gerrit.query_exportable_open_cls() self.process_gerrit_cls(open_gerrit_cls) - exportable_commits = self.get_exportable_commits(limit=COMMIT_HISTORY_WINDOW) + exportable_commits = self.get_exportable_commits() for exportable_commit in exportable_commits: pull_request = self.corresponding_pull_request_for_commit(exportable_commit) @@ -78,8 +77,8 @@ _log.info('No in-flight PR found for CL. Creating...') self.create_or_update_pull_request_from_cl(cl) - def get_exportable_commits(self, limit): - return exportable_commits_over_last_n_commits(limit, self.host, self.local_wpt) + def get_exportable_commits(self): + return exportable_commits_over_last_n_commits(self.host, self.local_wpt) def merge_pull_request(self, pull_request): _log.info('In-flight PR found: %s', pull_request.title)
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py index dbf6059..ff0a0cc 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_exporter_unittest.py
@@ -31,7 +31,7 @@ PullRequest(title='title1', number=1234, body='', state='open'), ]) test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') - test_exporter.get_exportable_commits = lambda limit: [ + test_exporter.get_exportable_commits = lambda: [ ChromiumCommit(host, position='refs/heads/master@{#458475}'), ChromiumCommit(host, position='refs/heads/master@{#458476}'), ChromiumCommit(host, position='refs/heads/master@{#458477}'), @@ -128,7 +128,7 @@ ), ], unsuccessful_merge_index=0) test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') - test_exporter.get_exportable_commits = lambda limit: [ + test_exporter.get_exportable_commits = lambda: [ ChromiumCommit(host, position='refs/heads/master@{#458475}'), ChromiumCommit(host, position='refs/heads/master@{#458476}'), ChromiumCommit(host, position='refs/heads/master@{#458477}'), @@ -159,7 +159,7 @@ test_exporter = TestExporter(host, 'gh-username', 'gh-token', gerrit_user=None, gerrit_token=None, dry_run=False) test_exporter.wpt_github = MockWPTGitHub(pull_requests=[]) - test_exporter.get_exportable_commits = lambda limit: [] + test_exporter.get_exportable_commits = lambda: [] test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') test_exporter.gerrit.get = lambda path, raw: base64.b64encode('sample diff') # pylint: disable=unused-argument test_exporter.gerrit.query_exportable_open_cls = lambda: [ @@ -196,7 +196,7 @@ PullRequest(title='title1', number=1234, body='description\nWPT-Export-Revision: 1', state='open'), ]) - test_exporter.get_exportable_commits = lambda limit: [] + test_exporter.get_exportable_commits = lambda: [] test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') test_exporter.gerrit.query_exportable_open_cls = lambda: [ GerritCL(data={ @@ -225,7 +225,7 @@ PullRequest(title='title1', number=1234, body='description\nWPT-Export-Revision: 1', state='open'), ]) - test_exporter.get_exportable_commits = lambda limit: [] + test_exporter.get_exportable_commits = lambda: [] test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') test_exporter.gerrit.get = lambda path, raw: base64.b64encode('sample diff') # pylint: disable=unused-argument test_exporter.gerrit.query_exportable_open_cls = lambda: [ @@ -274,7 +274,7 @@ body='description\nWPT-Export-Revision: 9\nChange-Id: decafbad', state='open'), ]) - test_exporter.get_exportable_commits = lambda limit: [ + test_exporter.get_exportable_commits = lambda: [ ChromiumCommit(host, sha='c881563d734a86f7d9cd57ac509653a61c45c240'), ] test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') @@ -296,7 +296,7 @@ test_exporter = TestExporter(host, 'gh-username', 'gh-token', gerrit_user=None, gerrit_token=None, dry_run=False) test_exporter.wpt_github = MockWPTGitHub(pull_requests=[]) - test_exporter.get_exportable_commits = lambda limit: [] + test_exporter.get_exportable_commits = lambda: [] test_exporter.gerrit = MockGerritAPI(host, 'gerrit-username', 'gerrit-token') test_exporter.gerrit.get = lambda path, raw: base64.b64encode('sample diff') # pylint: disable=unused-argument test_exporter.gerrit.query_exportable_open_cls = lambda: [
diff --git a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py index 07ac7033..0c546a17 100644 --- a/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py +++ b/third_party/WebKit/Tools/Scripts/webkitpy/w3c/test_importer.py
@@ -19,7 +19,7 @@ from webkitpy.common.path_finder import PathFinder from webkitpy.layout_tests.models.test_expectations import TestExpectations, TestExpectationParser from webkitpy.layout_tests.port.base import Port -from webkitpy.w3c.common import WPT_REPO_URL, WPT_DEST_NAME, exportable_commits_since +from webkitpy.w3c.common import WPT_REPO_URL, WPT_DEST_NAME, exportable_commits_over_last_n_commits from webkitpy.w3c.directory_owners_extractor import DirectoryOwnersExtractor from webkitpy.w3c.local_wpt import LocalWPT from webkitpy.w3c.test_copier import TestCopier @@ -156,10 +156,9 @@ A list of commits in the Chromium repo that are exportable but not yet exported to the web-platform-tests repo. """ - local_wpt = LocalWPT(self.host, path=wpt_path) assert self.host.filesystem.exists(wpt_path) - _, chromium_commit = local_wpt.most_recent_chromium_commit() - return exportable_commits_since(chromium_commit.sha, self.host, local_wpt) + local_wpt = LocalWPT(self.host, path=wpt_path) + return exportable_commits_over_last_n_commits(self.host, local_wpt) def clean_up_temp_repo(self, temp_repo_path): """Removes the temporary copy of the wpt repo that was downloaded."""
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 88049bc..9618664 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 7d56fd2386067a26878324ab48314e58e2b242ea +Revision: 63ccbd0e4c2fa9e1f69c0b1e5f4627ad66dcc4f1 License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 0c7f66b..742430d 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -38,7 +38,7 @@ 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - 'ef0ded8717340c9fe48e8e0f34f3e0e74d10a392', + '723e840a2f100a525f7feaad2e93df31d701780a', 'crashpad/third_party/zlib/zlib': Var('chromium_git') + '/chromium/src/third_party/zlib@' + '13dc246a58e4b72104d35f9b1809af95221ebda7',
diff --git a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc b/third_party/crashpad/crashpad/client/capture_context_mac_test.cc index ca52961e..15640210 100644 --- a/third_party/crashpad/crashpad/client/capture_context_mac_test.cc +++ b/third_party/crashpad/crashpad/client/capture_context_mac_test.cc
@@ -35,11 +35,15 @@ // gtest assertions. void SanityCheckContext(const NativeCPUContext& context) { #if defined(ARCH_CPU_X86) - ASSERT_EQ(context.tsh.flavor, x86_THREAD_STATE32); - ASSERT_EQ(context.tsh.count, implicit_cast<int>(x86_THREAD_STATE32_COUNT)); + ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), + implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); + ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT)); #elif defined(ARCH_CPU_X86_64) - ASSERT_EQ(context.tsh.flavor, x86_THREAD_STATE64); - ASSERT_EQ(context.tsh.count, implicit_cast<int>(x86_THREAD_STATE64_COUNT)); + ASSERT_EQ(implicit_cast<thread_state_flavor_t>(context.tsh.flavor), + implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); + ASSERT_EQ(implicit_cast<uint32_t>(context.tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT)); #endif #if defined(ARCH_CPU_X86_FAMILY)
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac.cc b/third_party/crashpad/crashpad/client/simulate_crash_mac.cc index 7e279015..2786438 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_mac.cc +++ b/third_party/crashpad/crashpad/client/simulate_crash_mac.cc
@@ -177,12 +177,12 @@ void SimulateCrash(const NativeCPUContext& cpu_context) { #if defined(ARCH_CPU_X86) - DCHECK_EQ(cpu_context.tsh.flavor, + DCHECK_EQ(implicit_cast<thread_state_flavor_t>(cpu_context.tsh.flavor), implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE32)); DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.tsh.count), x86_THREAD_STATE32_COUNT); #elif defined(ARCH_CPU_X86_64) - DCHECK_EQ(cpu_context.tsh.flavor, + DCHECK_EQ(implicit_cast<thread_state_flavor_t>(cpu_context.tsh.flavor), implicit_cast<thread_state_flavor_t>(x86_THREAD_STATE64)); DCHECK_EQ(implicit_cast<mach_msg_type_number_t>(cpu_context.tsh.count), x86_THREAD_STATE64_COUNT);
diff --git a/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc b/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc index de91ebb..c195352 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc +++ b/third_party/crashpad/crashpad/client/simulate_crash_mac_test.cc
@@ -130,12 +130,12 @@ reinterpret_cast<const x86_thread_state*>(old_state); switch (state->tsh.flavor) { case x86_THREAD_STATE32: - EXPECT_EQ(state->tsh.count, - implicit_cast<int>(x86_THREAD_STATE32_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE32_COUNT)); break; case x86_THREAD_STATE64: - EXPECT_EQ(state->tsh.count, - implicit_cast<int>(x86_THREAD_STATE64_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->tsh.count), + implicit_cast<uint32_t>(x86_THREAD_STATE64_COUNT)); break; default: ADD_FAILURE() << "unexpected tsh.flavor " << state->tsh.flavor; @@ -149,12 +149,12 @@ reinterpret_cast<const x86_float_state*>(old_state); switch (state->fsh.flavor) { case x86_FLOAT_STATE32: - EXPECT_EQ(state->fsh.count, - implicit_cast<int>(x86_FLOAT_STATE32_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->fsh.count), + implicit_cast<uint32_t>(x86_FLOAT_STATE32_COUNT)); break; case x86_FLOAT_STATE64: - EXPECT_EQ(state->fsh.count, - implicit_cast<int>(x86_FLOAT_STATE64_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->fsh.count), + implicit_cast<uint32_t>(x86_FLOAT_STATE64_COUNT)); break; default: ADD_FAILURE() << "unexpected fsh.flavor " << state->fsh.flavor; @@ -168,12 +168,12 @@ reinterpret_cast<const x86_debug_state*>(old_state); switch (state->dsh.flavor) { case x86_DEBUG_STATE32: - EXPECT_EQ(state->dsh.count, - implicit_cast<int>(x86_DEBUG_STATE32_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->dsh.count), + implicit_cast<uint32_t>(x86_DEBUG_STATE32_COUNT)); break; case x86_DEBUG_STATE64: - EXPECT_EQ(state->dsh.count, - implicit_cast<int>(x86_DEBUG_STATE64_COUNT)); + EXPECT_EQ(implicit_cast<uint32_t>(state->dsh.count), + implicit_cast<uint32_t>(x86_DEBUG_STATE64_COUNT)); break; default: ADD_FAILURE() << "unexpected dsh.flavor " << state->dsh.flavor;
diff --git a/third_party/crashpad/crashpad/compat/android/elf.h b/third_party/crashpad/crashpad/compat/android/elf.h deleted file mode 100644 index a3fc2a9a..0000000 --- a/third_party/crashpad/crashpad/compat/android/elf.h +++ /dev/null
@@ -1,25 +0,0 @@ -// Copyright 2017 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_COMPAT_ANDROID_ELF_H_ -#define CRASHPAD_COMPAT_ANDROID_ELF_H_ - -#include_next <elf.h> - -// Android 5.0.0 (API 21) NDK -#if !defined(NT_PRSTATUS) -#define NT_PRSTATUS 1 -#endif - -#endif // CRASHPAD_COMPAT_ANDROID_ELF_H_
diff --git a/third_party/crashpad/crashpad/compat/android/linux/elf.h b/third_party/crashpad/crashpad/compat/android/linux/elf.h new file mode 100644 index 0000000..e65d153 --- /dev/null +++ b/third_party/crashpad/crashpad/compat/android/linux/elf.h
@@ -0,0 +1,38 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_ +#define CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_ + +#include_next <linux/elf.h> + +// Android 5.0.0 (API 21) NDK + +#if defined(__i386__) || defined(__x86_64__) +#if !defined(NT_386_TLS) +#define NT_386_TLS 0x200 +#endif +#endif // __i386__ || __x86_64__ + +#if defined(__ARMEL__) || defined(__aarch64__) +#if !defined(NT_ARM_VFP) +#define NT_ARM_VFP 0x400 +#endif + +#if !defined(NT_ARM_TLS) +#define NT_ARM_TLS 0x401 +#endif +#endif // __ARMEL__ || __aarch64__ + +#endif // CRASHPAD_COMPAT_ANDROID_LINUX_ELF_H_
diff --git a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h b/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h index 4037eca6..f105f94 100644 --- a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h +++ b/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h
@@ -53,4 +53,10 @@ #define MAC_OS_X_VERSION_10_12 101200 #endif +// 10.13 SDK + +#ifndef MAC_OS_X_VERSION_10_13 +#define MAC_OS_X_VERSION_10_13 101300 +#endif + #endif // CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
diff --git a/third_party/crashpad/crashpad/compat/non_win/dbghelp.h b/third_party/crashpad/crashpad/compat/non_win/dbghelp.h index dedd8ad..a8d5a0f3 100644 --- a/third_party/crashpad/crashpad/compat/non_win/dbghelp.h +++ b/third_party/crashpad/crashpad/compat/non_win/dbghelp.h
@@ -533,11 +533,11 @@ uint32_t CheckSum; //! \brief The module’s timestamp, in `time_t` units, seconds since the POSIX - //! epoch. + //! epoch, or `0` if unknown. //! //! On Windows, this field comes from the `TimeDateStamp` field of the - //! module’s `IMAGE_HEADER` structure. It reflects the timestamp at the time - //! the module was linked. + //! module’s `IMAGE_FILE_HEADER` structure. It reflects the timestamp at the + //! time the module was linked. uint32_t TimeDateStamp; //! \brief ::RVA of a MINIDUMP_STRING containing the module’s path or file @@ -723,11 +723,11 @@ uint32_t CheckSum; //! \brief The module’s timestamp, in `time_t` units, seconds since the POSIX - //! epoch. + //! epoch, or `0` if unknown. //! //! On Windows, this field comes from the `TimeDateStamp` field of the - //! module’s `IMAGE_HEADER` structure. It reflects the timestamp at the time - //! the module was linked. + //! module’s `IMAGE_FILE_HEADER` structure. It reflects the timestamp at the + //! time the module was linked. uint32_t TimeDateStamp; //! \brief ::RVA of a MINIDUMP_STRING containing the module’s path or file
diff --git a/third_party/crashpad/crashpad/minidump/minidump_context.h b/third_party/crashpad/crashpad/minidump/minidump_context.h index b71b57c..f558832f 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_context.h +++ b/third_party/crashpad/crashpad/minidump/minidump_context.h
@@ -252,7 +252,7 @@ //! normally alias `dr6` and `dr7`, respectively. See Intel Software //! Developer’s Manual, Volume 3B: System Programming, Part 2 (253669-052), //! 17.2.2 “Debug Registers DR4 and DR5”. -struct ALIGNAS(16) MinidumpContextAMD64 { +struct alignas(16) MinidumpContextAMD64 { //! \brief Register parameter home address. //! //! On Windows, this field may contain the “home” address (on-stack, in the
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc index 53d4f62..697c14e 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_info_client_options_test.cc
@@ -21,6 +21,7 @@ #include "client/crashpad_info.h" #include "gtest/gtest.h" #include "test/errors.h" +#include "test/scoped_module_handle.h" #include "test/test_paths.h" #if defined(OS_MACOSX) @@ -138,48 +139,6 @@ } } -#if defined(OS_POSIX) -using DlHandle = void*; -#elif defined(OS_WIN) -using DlHandle = HMODULE; -#endif // OS_POSIX - -class ScopedDlHandle { - public: - explicit ScopedDlHandle(DlHandle dl_handle) - : dl_handle_(dl_handle) { - } - - ~ScopedDlHandle() { - if (dl_handle_) { -#if defined(OS_POSIX) - if (dlclose(dl_handle_) != 0) { - LOG(ERROR) << "dlclose: " << dlerror(); - } -#elif defined(OS_WIN) - if (!FreeLibrary(dl_handle_)) - PLOG(ERROR) << "FreeLibrary"; -#endif // OS_POSIX - } - } - - bool valid() const { return dl_handle_ != nullptr; } - - template <typename T> - T LookUpSymbol(const char* symbol_name) { -#if defined(OS_POSIX) - return reinterpret_cast<T>(dlsym(dl_handle_, symbol_name)); -#elif defined(OS_WIN) - return reinterpret_cast<T>(GetProcAddress(dl_handle_, symbol_name)); -#endif // OS_POSIX - } - - private: - DlHandle dl_handle_; - - DISALLOW_COPY_AND_ASSIGN(ScopedDlHandle); -}; - TEST(CrashpadInfoClientOptions, TwoModules) { // Open the module, which has its own CrashpadInfo structure. #if defined(OS_MACOSX) @@ -190,15 +149,15 @@ base::FilePath module_path = TestPaths::Executable().DirName().Append( FILE_PATH_LITERAL("crashpad_snapshot_test_module") + kDlExtension); #if defined(OS_MACOSX) - ScopedDlHandle dl_handle( + ScopedModuleHandle module( dlopen(module_path.value().c_str(), RTLD_LAZY | RTLD_LOCAL)); - ASSERT_TRUE(dl_handle.valid()) << "dlopen " << module_path.value() << ": " - << dlerror(); + ASSERT_TRUE(module.valid()) << "dlopen " << module_path.value() << ": " + << dlerror(); #elif defined(OS_WIN) - ScopedDlHandle dl_handle(LoadLibrary(module_path.value().c_str())); - ASSERT_TRUE(dl_handle.valid()) - << "LoadLibrary " << base::UTF16ToUTF8(module_path.value()) << ": " - << ErrorMessage(); + ScopedModuleHandle module(LoadLibrary(module_path.value().c_str())); + ASSERT_TRUE(module.valid()) << "LoadLibrary " + << base::UTF16ToUTF8(module_path.value()) << ": " + << ErrorMessage(); #else #error Port. #endif // OS_MACOSX @@ -207,7 +166,7 @@ // because it runs in the module, it returns the remote module’s CrashpadInfo // structure. CrashpadInfo* (*TestModule_GetCrashpadInfo)() = - dl_handle.LookUpSymbol<CrashpadInfo* (*)()>("TestModule_GetCrashpadInfo"); + module.LookUpSymbol<CrashpadInfo* (*)()>("TestModule_GetCrashpadInfo"); ASSERT_TRUE(TestModule_GetCrashpadInfo); auto options = SelfProcessSnapshotAndGetCrashpadOptions();
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc index d0b7a08..f16aa55 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader.cc
@@ -555,22 +555,14 @@ return false; } - mach_vm_size_t vmsize = segment->vmsize(); - if (segment_name == SEG_TEXT) { + mach_vm_size_t vmsize = segment->vmsize(); + if (vmsize == 0) { LOG(WARNING) << "zero-sized " SEG_TEXT " segment" << load_command_info; return false; } - mach_vm_size_t fileoff = segment->fileoff(); - if (fileoff != 0) { - LOG(WARNING) << base::StringPrintf( - SEG_TEXT " segment has unexpected fileoff 0x%llx", - fileoff) << load_command_info; - return false; - } - size_ = vmsize; // The slide is computed as the difference between the __TEXT segment’s
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc index 6c545bc..6d6e49d 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
@@ -577,8 +577,7 @@ // Now that all of the modules have been verified, make sure that dyld itself // can be read properly too. - const struct dyld_all_image_infos* dyld_image_infos = - _dyld_get_all_image_infos(); + const dyld_all_image_infos* dyld_image_infos = DyldGetAllImageInfos(); ASSERT_GE(dyld_image_infos->version, 1u); EXPECT_EQ(dyld_image_infos->infoArrayCount, count);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc index 9837a9c..06e1daf4 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
@@ -120,36 +120,29 @@ sections_.size(), load_command_info.c_str()); - if (section_segment_name != segment_name) { - // cl_kernels modules (for OpenCL) aren’t ld output, and they’re formatted - // incorrectly on OS X 10.10 and later. They have a single __TEXT segment, - // but one of the sections within it claims to belong to the __LD segment. - // This mismatch shouldn’t happen. This errant section also has the - // S_ATTR_DEBUG flag set, which shouldn’t happen unless all of the other - // sections in the segment also have this bit set (they don’t). These odd - // sections are reminiscent of unwind information stored in MH_OBJECT - // images, although cl_kernels images claim to be MH_BUNDLE. Because at - // least one cl_kernels module will commonly be found in a process, and - // sometimes more will be, tolerate this quirk. - // - // https://openradar.appspot.com/20239912 - bool ok = false; - if (file_type == MH_BUNDLE && module_name == "cl_kernels") { - int mac_os_x_minor_version = MacOSXMinorVersion(); - if ((mac_os_x_minor_version >= 10 && mac_os_x_minor_version <= 12) && - segment_name == SEG_TEXT && - section_segment_name == "__LD" && - section_name == "__compact_unwind" && - (section.flags & S_ATTR_DEBUG)) { - ok = true; - } - } - - if (!ok) { - LOG(WARNING) << "section.segname incorrect in segment " << segment_name - << section_info; - return false; - } + // cl_kernels modules (for OpenCL) aren’t ld output, and they’re formatted + // incorrectly on OS X 10.10 and later. They have a single __TEXT segment, + // but one of the sections within it claims to belong to the __LD segment. + // This mismatch shouldn’t happen. This errant section also has the + // S_ATTR_DEBUG flag set, which shouldn’t happen unless all of the other + // sections in the segment also have this bit set (they don’t). These odd + // sections are reminiscent of unwind information stored in MH_OBJECT + // images, although cl_kernels images claim to be MH_BUNDLE. Because at + // least one cl_kernels module will commonly be found in a process, and + // sometimes more will be, tolerate this quirk. + // + // https://openradar.appspot.com/20239912 + if (section_segment_name != segment_name && + !(file_type == MH_BUNDLE && + module_name == "cl_kernels" && + MacOSXMinorVersion() >= 10 && + segment_name == SEG_TEXT && + section_segment_name == "__LD" && + section_name == "__compact_unwind" && + (section.flags & S_ATTR_DEBUG))) { + LOG(WARNING) << "section.segname incorrect in segment " << segment_name + << section_info; + return false; } CheckedMachAddressRange section_range(
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc index 46083ab3fa..5e1f1c7 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader.cc
@@ -198,6 +198,46 @@ return modules_; } +mach_vm_address_t ProcessReader::DyldAllImageInfo( + mach_vm_size_t* all_image_info_size) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + task_dyld_info_data_t dyld_info; + mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; + kern_return_t kr = task_info( + task_, TASK_DYLD_INFO, reinterpret_cast<task_info_t>(&dyld_info), &count); + if (kr != KERN_SUCCESS) { + MACH_LOG(WARNING, kr) << "task_info"; + return 0; + } + + // TODO(mark): Deal with statically linked executables which don’t use dyld. + // This may look for the module that matches the executable path in the same + // data set that vmmap uses. + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + // The task_dyld_info_data_t struct grew in 10.7, adding the format field. + // Don’t check this field if it’s not present, which can happen when either + // the SDK used at compile time or the kernel at run time are too old and + // don’t know about it. + if (count >= TASK_DYLD_INFO_COUNT) { + const integer_t kExpectedFormat = + !Is64Bit() ? TASK_DYLD_ALL_IMAGE_INFO_32 : TASK_DYLD_ALL_IMAGE_INFO_64; + if (dyld_info.all_image_info_format != kExpectedFormat) { + LOG(WARNING) << "unexpected task_dyld_info_data_t::all_image_info_format " + << dyld_info.all_image_info_format; + DCHECK_EQ(dyld_info.all_image_info_format, kExpectedFormat); + return 0; + } + } +#endif + + if (all_image_info_size) { + *all_image_info_size = dyld_info.all_image_info_size; + } + return dyld_info.all_image_info_addr; +} + void ProcessReader::InitializeThreads() { DCHECK(!initialized_threads_); DCHECK(threads_.empty()); @@ -345,38 +385,12 @@ initialized_modules_ = true; - task_dyld_info_data_t dyld_info; - mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; - kern_return_t kr = task_info( - task_, TASK_DYLD_INFO, reinterpret_cast<task_info_t>(&dyld_info), &count); - if (kr != KERN_SUCCESS) { - MACH_LOG(WARNING, kr) << "task_info"; - return; - } - - // TODO(mark): Deal with statically linked executables which don’t use dyld. - // This may look for the module that matches the executable path in the same - // data set that vmmap uses. - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - // The task_dyld_info_data_t struct grew in 10.7, adding the format field. - // Don’t check this field if it’s not present, which can happen when either - // the SDK used at compile time or the kernel at run time are too old and - // don’t know about it. - if (count >= TASK_DYLD_INFO_COUNT) { - const integer_t kExpectedFormat = - !Is64Bit() ? TASK_DYLD_ALL_IMAGE_INFO_32 : TASK_DYLD_ALL_IMAGE_INFO_64; - if (dyld_info.all_image_info_format != kExpectedFormat) { - LOG(WARNING) << "unexpected task_dyld_info_data_t::all_image_info_format " - << dyld_info.all_image_info_format; - DCHECK_EQ(dyld_info.all_image_info_format, kExpectedFormat); - return; - } - } -#endif + mach_vm_size_t all_image_info_size; + mach_vm_address_t all_image_info_addr = + DyldAllImageInfo(&all_image_info_size); process_types::dyld_all_image_infos all_image_infos; - if (!all_image_infos.Read(this, dyld_info.all_image_info_addr)) { + if (!all_image_infos.Read(this, all_image_info_addr)) { LOG(WARNING) << "could not read dyld_all_image_infos"; return; } @@ -390,10 +404,10 @@ size_t expected_size = process_types::dyld_all_image_infos::ExpectedSizeForVersion( this, all_image_infos.version); - if (dyld_info.all_image_info_size < expected_size) { - LOG(WARNING) << "small dyld_all_image_infos size " - << dyld_info.all_image_info_size << " < " << expected_size - << " for version " << all_image_infos.version; + if (all_image_info_size < expected_size) { + LOG(WARNING) << "small dyld_all_image_infos size " << all_image_info_size + << " < " << expected_size << " for version " + << all_image_infos.version; return; }
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h b/third_party/crashpad/crashpad/snapshot/mac/process_reader.h index 72bd1dc..ddb49cb6 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader.h
@@ -150,6 +150,21 @@ //! corresponds to the dynamic loader, dyld. const std::vector<Module>& Modules(); + //! \brief Determines the location of the `dyld_all_image_infos` structure in + //! the process’ address space. + //! + //! This function is an internal implementation detail of Modules(), and + //! should not normally be used directly. It is exposed solely for use by test + //! code. + //! + //! \param[out] all_image_info_size The size of the `dyld_all_image_infos` + //! structure. Optional, may be `nullptr` if not required. + //! + //! \return The address of the `dyld_all_image_infos` structure in the + //! process’ address space, with \a all_image_info_size set appropriately. + //! On failure, returns `0` with a message logged. + mach_vm_address_t DyldAllImageInfo(mach_vm_size_t* all_image_info_size); + private: //! Performs lazy initialization of the \a threads_ vector on behalf of //! Threads().
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc index 3554326..3a6a1c8 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_test.cc
@@ -44,12 +44,13 @@ #include "util/stdlib/pointer_container.h" #include "util/synchronization/semaphore.h" -#if !defined(MAC_OS_X_VERSION_10_10) || \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 extern "C" { -// Redeclare a typedef whose availability (OSX 10.10) is newer than the + +// Redeclare a typedef whose availability (OS X 10.10) is newer than the // deployment target. typedef struct _cl_device_id* cl_device_id; + } // extern "C" #endif @@ -698,8 +699,7 @@ // is also reported as 0. EXPECT_EQ(modules[index].timestamp, 0); - const struct dyld_all_image_infos* dyld_image_infos = - _dyld_get_all_image_infos(); + const dyld_all_image_infos* dyld_image_infos = DyldGetAllImageInfos(); if (dyld_image_infos->version >= 2) { ASSERT_TRUE(modules[index].reader); EXPECT_EQ(modules[index].reader->Address(), @@ -781,8 +781,7 @@ FileHandle write_handle = WritePipeHandle(); uint32_t dyld_image_count = _dyld_image_count(); - const struct dyld_all_image_infos* dyld_image_infos = - _dyld_get_all_image_infos(); + const dyld_all_image_infos* dyld_image_infos = DyldGetAllImageInfos(); uint32_t write_image_count = dyld_image_count; if (dyld_image_infos->version >= 2) {
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc index 53d8903..aeff88bb 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
@@ -42,6 +42,15 @@ } template <> +inline void Assign<process_types::internal::Reserved32_32Only64, + process_types::internal::Reserved32_32Only32>( + process_types::internal::Reserved32_32Only64* destination, + const process_types::internal::Reserved32_32Only32& source) { + // Reserved32_32Only32 carries no data and has no storage in the 64-bit + // structure. +} + +template <> inline void Assign<process_types::internal::Reserved32_64Only64, process_types::internal::Reserved32_64Only32>( process_types::internal::Reserved32_64Only64* destination,
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.h b/third_party/crashpad/crashpad/snapshot/mac/process_types.h index 7274515..eb397b9 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.h
@@ -37,8 +37,10 @@ // Some structure definitions differ in 32-bit and 64-bit environments by having // additional “reserved” padding fields present only in the 64-bit environment. -// These Reserved*_64Only* types allow the process_types system to replicate +// These Reserved*_*Only* types allow the process_types system to replicate // these structures more precisely. +using Reserved32_32Only32 = uint32_t; +using Reserved32_32Only64 = Nothing; using Reserved32_64Only32 = Nothing; using Reserved32_64Only64 = uint32_t; using Reserved64_64Only32 = Nothing; @@ -71,6 +73,7 @@ using Pointer = internal::TraitsGeneric::Pointer; \ using IntPtr = internal::TraitsGeneric::IntPtr; \ using UIntPtr = internal::TraitsGeneric::UIntPtr; \ + using Reserved32_32Only = internal::TraitsGeneric::Reserved32_32Only; \ using Reserved32_64Only = internal::TraitsGeneric::Reserved32_64Only; \ using Reserved64_64Only = internal::TraitsGeneric::Reserved64_64Only; \ using Nothing = internal::TraitsGeneric::Nothing; \ @@ -162,6 +165,7 @@ using Pointer = typename Traits::Pointer; \ using IntPtr = typename Traits::IntPtr; \ using UIntPtr = typename Traits::UIntPtr; \ + using Reserved32_32Only = typename Traits::Reserved32_32Only; \ using Reserved32_64Only = typename Traits::Reserved32_64Only; \ using Reserved64_64Only = typename Traits::Reserved64_64Only; \ using Nothing = typename Traits::Nothing; \
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc index c896ebf..7839b40 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -80,7 +80,9 @@ offsetof(dyld_all_image_infos<Traits>, sharedCacheSlide), // 11 offsetof(dyld_all_image_infos<Traits>, sharedCacheUUID), // 12 offsetof(dyld_all_image_infos<Traits>, infoArrayChangeTimestamp), // 13 - offsetof(dyld_all_image_infos<Traits>, end), // 14 + offsetof(dyld_all_image_infos<Traits>, end_14_15), // 14 + offsetof(dyld_all_image_infos<Traits>, end_14_15), // 15 + sizeof(dyld_all_image_infos<Traits>), // 16 }; if (version >= arraysize(kSizeForVersion)) {
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype index 3470ee8..f92a800 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype
@@ -116,20 +116,28 @@ // Version 14 (OS X 10.9) // As of the 10.12 SDK, this is declared as reserved[9] for 64-bit platforms - // and reserved[4] for 32-bit platforms. + // and reserved[4] for 32-bit platforms. It was expanded to reserved[5] for + // 32-bit platforms in the 10.13 SDK to provide proper padding, but because + // the runtimes that use versions 14 and 15 were built with SDKs that did not + // have this extra padding, it’s necessary to treat the element at index 4 on + // 32-bit systems as outside of the version 14 and 15 structure. This is why + // |reserved| is only declared a 4-element array, with a special end_14_15 + // member (not present in the native definition) available to indicate the + // end of the native version 14 and 15 structure, preceding the padding in the + // 32-bit structure that would natively be addressed at index 4 of |reserved|. + // Treat reserved_4_32 as only available in version 16 of the structure. PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, reserved, [4]) - PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_4) + PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_4_64) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_5) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_6) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_7) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_8) + PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_14_15) + PROCESS_TYPE_STRUCT_MEMBER(Reserved32_32Only, reserved_4_32) - // The 32-bit version of the structure will have four extra bytes of tail - // padding when built for 64-bit systems than it does natively and when built - // for 32-bit systems. Instead of using sizeof(dyld_all_image_infos), use - // offsetof(dyld_all_image_infos, end) to avoid taking this tail padding into - // account. - PROCESS_TYPE_STRUCT_MEMBER(Nothing, end) + // Version 16 (macOS 10.13) + PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, compact_dyld_image_info_addr) + PROCESS_TYPE_STRUCT_MEMBER(ULong, compact_dyld_image_info_size) // size_t PROCESS_TYPE_STRUCT_END(dyld_all_image_infos) #endif // ! PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO &&
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/traits.h b/third_party/crashpad/crashpad/snapshot/mac/process_types/traits.h index 396799be..613f4f57 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/traits.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/traits.h
@@ -36,6 +36,7 @@ using Pointer = uint##lp_bits##_t __VA_ARGS__; \ using IntPtr = int##lp_bits##_t __VA_ARGS__; \ using UIntPtr = uint##lp_bits##_t __VA_ARGS__; \ + using Reserved32_32Only = Reserved32_32Only##lp_bits; \ using Reserved32_64Only = Reserved32_64Only##lp_bits; \ using Reserved64_64Only = Reserved64_64Only##lp_bits; \ using Nothing = Nothing; \
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc index 18595f0..8ab15c8 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -46,9 +46,13 @@ TEST(ProcessTypes, DyldImagesSelf) { // Get the in-process view of dyld_all_image_infos, and check it for sanity. - const struct dyld_all_image_infos* self_image_infos = - _dyld_get_all_image_infos(); + const dyld_all_image_infos* self_image_infos = DyldGetAllImageInfos(); int mac_os_x_minor_version = MacOSXMinorVersion(); + + // The 10.13 SDK defines dyld_all_image_infos version 16 and says that it’s + // used on 10.13, but 10.13db1 17A264c uses version 15. + // + // TODO(mark): Recheck later in the beta period, up to the 10.13 release. if (mac_os_x_minor_version >= 12) { EXPECT_GE(self_image_infos->version, 15u); } else if (mac_os_x_minor_version >= 9) { @@ -100,16 +104,18 @@ ProcessReader process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 - const uint32_t kDyldAllImageInfosVersionInSDK = 15; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 16; +#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 15; #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 - const uint32_t kDyldAllImageInfosVersionInSDK = 14; + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 14; #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - const uint32_t kDyldAllImageInfosVersionInSDK = 12; + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 12; #elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - const uint32_t kDyldAllImageInfosVersionInSDK = 7; + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 7; #else - const uint32_t kDyldAllImageInfosVersionInSDK = 1; + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 1; #endif // Make sure that the size of the structure as declared in the SDK matches the @@ -120,7 +126,7 @@ // Make sure that the computed sizes of various versions of this structure are // correct at different bitnessses. - const struct { + constexpr struct { uint32_t version; size_t size_32; size_t size_64; @@ -139,6 +145,7 @@ {13, 104, 184}, {14, 164, 304}, {15, 164, 304}, + {16, 176, 320}, }; for (size_t index = 0; index < arraysize(kVersionsAndSizes); ++index) { uint32_t version = kVersionsAndSizes[index].version; @@ -290,7 +297,8 @@ << "index " << index; } #if defined(ARCH_CPU_64_BITS) - EXPECT_EQ(proctype_image_infos.reserved_4, self_image_infos->reserved[4]); + EXPECT_EQ(proctype_image_infos.reserved_4_64, + self_image_infos->reserved[4]); EXPECT_EQ(proctype_image_infos.reserved_5, self_image_infos->reserved[5]); EXPECT_EQ(proctype_image_infos.reserved_6, self_image_infos->reserved[6]); EXPECT_EQ(proctype_image_infos.reserved_7, self_image_infos->reserved[7]); @@ -299,6 +307,15 @@ } #endif +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 + if (proctype_image_infos.version >= 16) { + EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_addr, + self_image_infos->compact_dyld_image_info_addr); + EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_size, + self_image_infos->compact_dyld_image_info_size); + } +#endif + if (proctype_image_infos.version >= 1) { std::vector<process_types::dyld_image_info> proctype_image_info_vector( proctype_image_infos.infoArrayCount);
diff --git a/third_party/crashpad/crashpad/test/mac/dyld.cc b/third_party/crashpad/crashpad/test/mac/dyld.cc new file mode 100644 index 0000000..6fa2176 --- /dev/null +++ b/third_party/crashpad/crashpad/test/mac/dyld.cc
@@ -0,0 +1,99 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test/mac/dyld.h" + +#include <AvailabilityMacros.h> +#include <dlfcn.h> +#include <mach/mach.h> +#include <mach-o/dyld.h> +#include <stdint.h> + +#include "base/logging.h" +#include "snapshot/mac/process_reader.h" +#include "test/scoped_module_handle.h" +#include "util/numeric/safe_assignment.h" + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 +extern "C" { + +// A non-public dyld API, declared in 10.12.4 +// dyld-433.5/include/mach-o/dyld_priv.h. The code still exists in 10.13, but +// its symbol is no longer public, so it can’t be used there. +const dyld_all_image_infos* _dyld_get_all_image_infos() + __attribute__((weak_import)); + +} // extern "C" +#endif + +namespace crashpad { +namespace test { + +const dyld_all_image_infos* DyldGetAllImageInfos() { +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 + // When building with the pre-10.13 SDK, the weak_import declaration above is + // available and a symbol will be present in the SDK to link against. If the + // old interface is also available at run time (running on pre-10.13), use it. + if (_dyld_get_all_image_infos) { + return _dyld_get_all_image_infos(); + } +#elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_13 + // When building with the 10.13 SDK or later, but able to run on pre-10.13, + // look for _dyld_get_all_image_infos in the same module that provides + // _dyld_image_count. There’s no symbol in the SDK to link against, so this is + // a little more involved than the pre-10.13 SDK case above. + Dl_info dli; + if (!dladdr(reinterpret_cast<void*>(_dyld_image_count), &dli)) { + LOG(WARNING) << "dladdr: failed"; + } else { + ScopedModuleHandle module( + dlopen(dli.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD)); + if (!module.valid()) { + LOG(WARNING) << "dlopen: " << dlerror(); + } else { + using DyldGetAllImageInfosType = const dyld_all_image_infos*(*)(); + const auto _dyld_get_all_image_infos = + module.LookUpSymbol<DyldGetAllImageInfosType>( + "_dyld_get_all_image_infos"); + if (_dyld_get_all_image_infos) { + return _dyld_get_all_image_infos(); + } + } + } +#endif + + // On 10.13 and later, do it the hard way. + ProcessReader process_reader; + if (!process_reader.Initialize(mach_task_self())) { + return nullptr; + } + + mach_vm_address_t all_image_info_addr_m = + process_reader.DyldAllImageInfo(nullptr); + if (!all_image_info_addr_m) { + return nullptr; + } + + uintptr_t all_image_info_addr_u; + if (!AssignIfInRange(&all_image_info_addr_u, all_image_info_addr_m)) { + LOG(ERROR) << "all_image_info_addr_m " << all_image_info_addr_m + << " out of range"; + return nullptr; + } + + return reinterpret_cast<const dyld_all_image_infos*>(all_image_info_addr_u); +} + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/mac/dyld.h b/third_party/crashpad/crashpad/test/mac/dyld.h index e436c5d1..0a688f3e 100644 --- a/third_party/crashpad/crashpad/test/mac/dyld.h +++ b/third_party/crashpad/crashpad/test/mac/dyld.h
@@ -17,13 +17,17 @@ #include <mach-o/dyld_images.h> -extern "C" { +namespace crashpad { +namespace test { -// Returns a pointer to this process’ dyld_all_image_infos structure. This is -// implemented as a non-public dyld API, declared in 10.9.2 -// dyld-239.4/include/mach-o/dyld_priv.h. -const struct dyld_all_image_infos* _dyld_get_all_image_infos(); +//! \brief Calls or emulates the `_dyld_get_all_image_infos()` private/internal +//! function. +//! +//! \return A pointer to this process’ dyld_all_image_infos structure, or +//! `nullptr` on failure with a message logged. +const dyld_all_image_infos* DyldGetAllImageInfos(); -} // extern "C" +} // namespace test +} // namespace crashpad #endif // CRASHPAD_TEST_MAC_DYLD_H_
diff --git a/third_party/crashpad/crashpad/test/scoped_module_handle.cc b/third_party/crashpad/crashpad/test/scoped_module_handle.cc new file mode 100644 index 0000000..3854222 --- /dev/null +++ b/third_party/crashpad/crashpad/test/scoped_module_handle.cc
@@ -0,0 +1,46 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test/scoped_module_handle.h" + +#include "base/logging.h" + +namespace crashpad { +namespace test { + +// static +void ScopedModuleHandle::Impl::Close(ModuleHandle handle) { +#if defined(OS_POSIX) + if (dlclose(handle) != 0) { + LOG(ERROR) << "dlclose: " << dlerror(); + } +#elif defined(OS_WIN) + if (!FreeLibrary(handle)) { + PLOG(ERROR) << "FreeLibrary"; + } +#else +#error Port +#endif +} + +ScopedModuleHandle::ScopedModuleHandle(ModuleHandle handle) : handle_(handle) {} + +ScopedModuleHandle::~ScopedModuleHandle() { + if (valid()) { + Impl::Close(handle_); + } +} + +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/test/scoped_module_handle.h b/third_party/crashpad/crashpad/test/scoped_module_handle.h new file mode 100644 index 0000000..3863cad --- /dev/null +++ b/third_party/crashpad/crashpad/test/scoped_module_handle.h
@@ -0,0 +1,81 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_TEST_SCOPED_MODULE_HANDLE_H_ +#define CRASHPAD_TEST_SCOPED_MODULE_HANDLE_H_ + +#include "base/macros.h" +#include "build/build_config.h" + +#if defined(OS_POSIX) +#include <dlfcn.h> +#elif defined(OS_WIN) +#include <windows.h> +#endif + +namespace crashpad { +namespace test { + +//! \brief Maintains ownership of a loadable module handle, releasing it as +//! appropriate on destruction. +class ScopedModuleHandle { + private: + class Impl { + public: +#if defined(OS_POSIX) + using ModuleHandle = void*; + + static void* LookUpSymbol(ModuleHandle handle, const char* symbol_name) { + return dlsym(handle, symbol_name); + } +#elif defined(OS_WIN) + using ModuleHandle = HMODULE; + + static void* LookUpSymbol(ModuleHandle handle, const char* symbol_name) { + return GetProcAddress(handle, symbol_name); + } +#endif + + static void Close(ModuleHandle handle); + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(Impl); + }; + + public: + using ModuleHandle = Impl::ModuleHandle; + + explicit ScopedModuleHandle(ModuleHandle handle); + ~ScopedModuleHandle(); + + //! \return `true` if this object manages a valid loadable module handle. + bool valid() const { return handle_ != nullptr; } + + //! \return The value of the symbol named by \a symbol_name, or `nullptr` on + //! failure. + template <typename T> + T LookUpSymbol(const char* symbol_name) const { + return reinterpret_cast<T>(Impl::LookUpSymbol(handle_, symbol_name)); + } + + private: + ModuleHandle handle_; + + DISALLOW_COPY_AND_ASSIGN(ScopedModuleHandle); +}; + +} // namespace test +} // namespace crashpad + +#endif // CRASHPAD_TEST_SCOPED_MODULE_HANDLE_H_
diff --git a/third_party/crashpad/crashpad/test/test.gyp b/third_party/crashpad/crashpad/test/test.gyp index 94b198c..f2682c0 100644 --- a/third_party/crashpad/crashpad/test/test.gyp +++ b/third_party/crashpad/crashpad/test/test.gyp
@@ -22,6 +22,7 @@ 'type': 'static_library', 'dependencies': [ '../compat/compat.gyp:crashpad_compat', + '../snapshot/snapshot.gyp:crashpad_snapshot', '../third_party/gtest/gtest.gyp:gtest', '../third_party/mini_chromium/mini_chromium.gyp:base', '../util/util.gyp:crashpad_util', @@ -37,6 +38,7 @@ 'gtest_death_check.h', 'hex_string.cc', 'hex_string.h', + 'mac/dyld.cc', 'mac/dyld.h', 'mac/mach_errors.cc', 'mac/mach_errors.h', @@ -49,6 +51,8 @@ 'multiprocess_exec_posix.cc', 'multiprocess_exec_win.cc', 'multiprocess_posix.cc', + 'scoped_module_handle.cc', + 'scoped_module_handle.h', 'scoped_temp_dir.cc', 'scoped_temp_dir.h', 'scoped_temp_dir_posix.cc',
diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc new file mode 100644 index 0000000..8852e614 --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.cc
@@ -0,0 +1,104 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/linux/auxiliary_vector.h" + +#include <linux/auxvec.h> +#include <stdio.h> +#include <string.h> + +#include <algorithm> + +#include "base/files/file_path.h" +#include "base/logging.h" +#include "util/file/file_reader.h" +#include "util/stdlib/map_insert.h" + +namespace crashpad { + +AuxiliaryVector::AuxiliaryVector() : values_() {} + +AuxiliaryVector::~AuxiliaryVector() {} + +bool AuxiliaryVector::Initialize(pid_t pid, bool is_64_bit) { + return is_64_bit ? Read<uint64_t>(pid) : Read<uint32_t>(pid); +} + +template <typename ULong> +bool AuxiliaryVector::Read(pid_t pid) { + char path[32]; + snprintf(path, sizeof(path), "/proc/%d/auxv", pid); + FileReader aux_file; + if (!aux_file.Open(base::FilePath(path))) { + return false; + } + + ULong type; + ULong value; + while (aux_file.ReadExactly(&type, sizeof(type)) && + aux_file.ReadExactly(&value, sizeof(value))) { + if (type == AT_NULL && value == 0) { + return true; + } + if (type == AT_IGNORE) { + continue; + } + if (!MapInsertOrReplace(&values_, type, value, nullptr)) { + LOG(ERROR) << "duplicate auxv entry"; + return false; + } + } + return false; +} + +// static +bool AuxiliaryVector::VariableSizeBitCast(uint64_t data, + char* dest, + size_t dest_size) { + auto data_p = reinterpret_cast<const char*>(&data); + constexpr size_t data_size = sizeof(uint64_t); + + // Verify that any unused bytes from data are zero. + // The unused bytes are at the start of the data buffer for big-endian and the + // end of the buffer for little-endian. + if (dest_size < data_size) { + uint64_t zero = 0; + auto extra_bytes = data_p; +#if defined(ARCH_CPU_LITTLE_ENDIAN) + extra_bytes += dest_size; +#endif // ARCH_CPU_LITTLE_ENDIAN + if (memcmp(extra_bytes, &zero, data_size - dest_size) != 0) { + LOG(ERROR) << "information loss"; + return false; + } + } + + // Zero out the destination, in case it is larger than data. + memset(dest, 0, dest_size); + +#if defined(ARCH_CPU_LITTLE_ENDIAN) + // Copy a prefix of data to a prefix of dest for little-endian + memcpy(dest, data_p, std::min(dest_size, data_size)); +#else + // or the suffix of data to the suffix of dest for big-endian + if (data_size >= dest_size) { + memcpy(dest, data_p + data_size - dest_size, dest_size); + } else { + memcpy(dest + dest_size - data_size, data_p, data_size); + } +#endif // ARCH_CPU_LITTLE_ENDIAN + return true; +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector.h b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.h new file mode 100644 index 0000000..904eada --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/auxiliary_vector.h
@@ -0,0 +1,76 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_UTIL_LINUX_AUXILIARY_VECTOR_H_ +#define CRASHPAD_UTIL_LINUX_AUXILIARY_VECTOR_H_ + +#include <sys/types.h> + +#include <map> + +#include "base/logging.h" +#include "base/macros.h" + +namespace crashpad { + +//! \brief Read the auxiliary vector for a target process. +class AuxiliaryVector { + public: + AuxiliaryVector(); + ~AuxiliaryVector(); + + //! \brief Initializes this object with the auxiliary vector for the process + //! with process ID \a pid. + //! + //! This method must be called successfully prior to calling any other method + //! in this class. + //! + //! \param[in] pid The process ID of a target process. + //! \param[in] is_64_bit Whether the target process is 64-bit. + //! + //! \return `true` on success, `false` on failure with a message logged. + bool Initialize(pid_t pid, bool is_64_bit); + + //! \brief Retrieve a value from the vector. + //! + //! \param[in] type Specifies which value should be retrieved. The possible + //! values for this parameter are defined by `<linux/auxvec.h>`. + //! \param[out] value The value, casted to an appropriate type, if found. + //! \return `true` if the value is found. + template <typename V> + bool GetValue(uint64_t type, V* value) const { + auto iter = values_.find(type); + if (iter == values_.end()) { + LOG(ERROR) << "value not found"; + return false; + } + return VariableSizeBitCast( + iter->second, reinterpret_cast<char*>(value), sizeof(V)); + } + + protected: + std::map<uint64_t, uint64_t> values_; + + private: + template <typename ULong> + bool Read(pid_t pid); + + static bool VariableSizeBitCast(uint64_t data, char* dest, size_t dest_size); + + DISALLOW_COPY_AND_ASSIGN(AuxiliaryVector); +}; + +} // namespace crashpad + +#endif // CRASHPAD_UTIL_LINUX_AUXILIARY_VECTOR_H_
diff --git a/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc b/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc new file mode 100644 index 0000000..89bc3c7 --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/auxiliary_vector_test.cc
@@ -0,0 +1,209 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/linux/auxiliary_vector.h" + +#include <linux/auxvec.h> +#include <sys/utsname.h> +#include <unistd.h> + +#include <limits> + +#include "base/macros.h" +#include "gtest/gtest.h" +#include "test/errors.h" +#include "test/multiprocess.h" +#include "util/linux/address_types.h" +#include "util/linux/memory_map.h" +#include "util/linux/process_memory.h" +#include "util/misc/from_pointer_cast.h" +#include "util/numeric/int128.h" + +extern "C" { +extern void _start(); +} // extern "C" + +namespace crashpad { +namespace test { +namespace { + +void TestAgainstCloneOrSelf(pid_t pid) { +#if defined(ARCH_CPU_64_BITS) + constexpr bool am_64_bit = true; +#else + constexpr bool am_64_bit = false; +#endif + AuxiliaryVector aux; + ASSERT_TRUE(aux.Initialize(pid, am_64_bit)); + + MemoryMap mappings; + ASSERT_TRUE(mappings.Initialize(pid)); + + LinuxVMAddress phdrs; + ASSERT_TRUE(aux.GetValue(AT_PHDR, &phdrs)); + EXPECT_TRUE(mappings.FindMapping(phdrs)); + + int pagesize; + ASSERT_TRUE(aux.GetValue(AT_PAGESZ, &pagesize)); + EXPECT_EQ(pagesize, getpagesize()); + + LinuxVMAddress interp_base; + ASSERT_TRUE(aux.GetValue(AT_BASE, &interp_base)); + EXPECT_TRUE(mappings.FindMapping(interp_base)); + + LinuxVMAddress entry_addr; + ASSERT_TRUE(aux.GetValue(AT_ENTRY, &entry_addr)); + EXPECT_EQ(entry_addr, FromPointerCast<LinuxVMAddress>(_start)); + + uid_t uid; + ASSERT_TRUE(aux.GetValue(AT_UID, &uid)); + EXPECT_EQ(uid, getuid()); + + uid_t euid; + ASSERT_TRUE(aux.GetValue(AT_EUID, &euid)); + EXPECT_EQ(euid, geteuid()); + + gid_t gid; + ASSERT_TRUE(aux.GetValue(AT_GID, &gid)); + EXPECT_EQ(gid, getgid()); + + gid_t egid; + ASSERT_TRUE(aux.GetValue(AT_EGID, &egid)); + EXPECT_EQ(egid, getegid()); + + ProcessMemory memory; + ASSERT_TRUE(memory.Initialize(pid)); + + LinuxVMAddress platform_addr; + ASSERT_TRUE(aux.GetValue(AT_PLATFORM, &platform_addr)); + std::string platform; + ASSERT_TRUE(memory.ReadCStringSizeLimited(platform_addr, 10, &platform)); +#if defined(ARCH_CPU_X86) + EXPECT_STREQ(platform.c_str(), "i686"); +#elif defined(ARCH_CPU_X86_64) + EXPECT_STREQ(platform.c_str(), "x86_64"); +#elif defined(ARCH_CPU_ARMEL) + // Machine name and platform are set in Linux:/arch/arm/kernel/setup.c + // Machine typically looks like "armv7l". + // Platform typically looks like "v7l". + utsname sys_names; + ASSERT_EQ(uname(&sys_names), 0); + std::string machine_name(sys_names.machine); + EXPECT_NE(machine_name.find(platform), std::string::npos); +#elif defined(ARCH_CPU_ARM64) + EXPECT_STREQ(platform.c_str(), "aarch64"); +#endif // ARCH_CPU_X86 + +#if defined(AT_SYSINFO_EHDR) + LinuxVMAddress vdso_addr; + ASSERT_TRUE(aux.GetValue(AT_SYSINFO_EHDR, &vdso_addr)); + EXPECT_TRUE(mappings.FindMapping(vdso_addr)); +#endif // AT_SYSINFO_EHDR + +#if defined(AT_EXECFN) + LinuxVMAddress filename_addr; + ASSERT_TRUE(aux.GetValue(AT_EXECFN, &filename_addr)); + std::string filename; + ASSERT_TRUE(memory.ReadCStringSizeLimited(filename_addr, 4096, &filename)); + EXPECT_TRUE(filename.find("crashpad_util_test") != std::string::npos); +#endif // AT_EXECFN + + int ignore; + EXPECT_FALSE(aux.GetValue(AT_NULL, &ignore)); + + char too_small; + EXPECT_FALSE(aux.GetValue(AT_PAGESZ, &too_small)); + + uint128_struct big_dest; + memset(&big_dest, 0xf, sizeof(big_dest)); + ASSERT_TRUE(aux.GetValue(AT_PHDR, &big_dest)); + EXPECT_EQ(big_dest.lo, phdrs); +} + +TEST(AuxiliaryVector, ReadSelf) { + TestAgainstCloneOrSelf(getpid()); +} + +class ReadChildTest : public Multiprocess { + public: + ReadChildTest() : Multiprocess() {} + ~ReadChildTest() {} + + private: + void MultiprocessParent() override { TestAgainstCloneOrSelf(ChildPID()); } + + void MultiprocessChild() override { CheckedReadFileAtEOF(ReadPipeHandle()); } + + DISALLOW_COPY_AND_ASSIGN(ReadChildTest); +}; + +TEST(AuxiliaryVector, ReadChild) { + ReadChildTest test; + test.Run(); +} + +class AuxVecTester : public AuxiliaryVector { + public: + AuxVecTester() : AuxiliaryVector() {} + void Insert(uint64_t type, uint64_t value) { values_[type] = value; } +}; + +TEST(AuxiliaryVector, SignedBit) { +#if defined(ARCH_CPU_64_BITS) + constexpr bool am_64_bit = true; +#else + constexpr bool am_64_bit = false; +#endif + AuxVecTester aux; + ASSERT_TRUE(aux.Initialize(getpid(), am_64_bit)); + constexpr uint64_t type = 0x0000000012345678; + + constexpr int32_t neg1_32 = -1; + aux.Insert(type, bit_cast<uint32_t>(neg1_32)); + int32_t outval32s; + ASSERT_TRUE(aux.GetValue(type, &outval32s)); + EXPECT_EQ(outval32s, neg1_32); + + constexpr int32_t int32_max = std::numeric_limits<int32_t>::max(); + aux.Insert(type, bit_cast<uint32_t>(int32_max)); + ASSERT_TRUE(aux.GetValue(type, &outval32s)); + EXPECT_EQ(outval32s, int32_max); + + constexpr uint32_t uint32_max = std::numeric_limits<uint32_t>::max(); + aux.Insert(type, uint32_max); + uint32_t outval32u; + ASSERT_TRUE(aux.GetValue(type, &outval32u)); + EXPECT_EQ(outval32u, uint32_max); + + constexpr int64_t neg1_64 = -1; + aux.Insert(type, bit_cast<uint64_t>(neg1_64)); + int64_t outval64s; + ASSERT_TRUE(aux.GetValue(type, &outval64s)); + EXPECT_EQ(outval64s, neg1_64); + + constexpr int64_t int64_max = std::numeric_limits<int64_t>::max(); + aux.Insert(type, bit_cast<uint64_t>(int64_max)); + ASSERT_TRUE(aux.GetValue(type, &outval64s)); + EXPECT_EQ(outval64s, int64_max); + + constexpr uint64_t uint64_max = std::numeric_limits<uint64_t>::max(); + aux.Insert(type, uint64_max); + uint64_t outval64u; + ASSERT_TRUE(aux.GetValue(type, &outval64u)); + EXPECT_EQ(outval64u, uint64_max); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/linux/memory_map.cc b/third_party/crashpad/crashpad/util/linux/memory_map.cc index d1ef6c0..4283cb8 100644 --- a/third_party/crashpad/crashpad/util/linux/memory_map.cc +++ b/third_party/crashpad/crashpad/util/linux/memory_map.cc
@@ -255,4 +255,16 @@ return nullptr; } +const MemoryMap::Mapping* MemoryMap::FindMappingWithName( + const std::string& name) const { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + + for (const auto& mapping : mappings_) { + if (mapping.name == name) { + return &mapping; + } + } + return nullptr; +} + } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/linux/memory_map.h b/third_party/crashpad/crashpad/util/linux/memory_map.h index 2d7a01a1..22f4448b 100644 --- a/third_party/crashpad/crashpad/util/linux/memory_map.h +++ b/third_party/crashpad/crashpad/util/linux/memory_map.h
@@ -63,11 +63,17 @@ //! \return `true` on success, `false` on failure with a message logged. bool Initialize(pid_t pid); - //! \return The Mapping containing \a address. The caller does not take - //! ownership of this object. It is scoped to the lifetime of the - //! MemoryMap object that it was obtained from. + //! \return The Mapping containing \a address or `nullptr` if no match is + //! found. The caller does not take ownership of this object. It is scoped + //! to the lifetime of the MemoryMap object that it was obtained from. const Mapping* FindMapping(LinuxVMAddress address) const; + //! \return The Mapping with the lowest base address whose name is \a name or + //! `nullptr` if no match is found. The caller does not take ownership of + //! this object. It is scoped to the lifetime of the MemoryMap object that + //! it was obtained from. + const Mapping* FindMappingWithName(const std::string& name) const; + private: std::vector<Mapping> mappings_; InitializationStateDcheck initialized_;
diff --git a/third_party/crashpad/crashpad/util/linux/memory_map_test.cc b/third_party/crashpad/crashpad/util/linux/memory_map_test.cc index cf5c9e2..aab5c4ac 100644 --- a/third_party/crashpad/crashpad/util/linux/memory_map_test.cc +++ b/third_party/crashpad/crashpad/util/linux/memory_map_test.cc
@@ -149,6 +149,7 @@ << ErrnoMessage("stat"); EXPECT_EQ(mapping->device, file_stat.st_dev); EXPECT_EQ(mapping->inode, file_stat.st_ino); + EXPECT_EQ(map.FindMappingWithName(mapping->name), mapping); } void MultiprocessChild() override {
diff --git a/third_party/crashpad/crashpad/util/linux/thread_info.cc b/third_party/crashpad/crashpad/util/linux/thread_info.cc new file mode 100644 index 0000000..d389763 --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/thread_info.cc
@@ -0,0 +1,332 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/linux/thread_info.h" + +#include <linux/elf.h> +#include <string.h> +#include <sys/ptrace.h> +#include <sys/uio.h> + +#include "base/logging.h" +#include "util/misc/from_pointer_cast.h" + +#if defined(ARCH_CPU_X86_FAMILY) +#include <asm/ldt.h> +#endif + +namespace crashpad { + +namespace { + +#if defined(ARCH_CPU_ARMEL) +// PTRACE_GETREGSET, introduced in Linux 2.6.34 (2225a122ae26), requires kernel +// support enabled by HAVE_ARCH_TRACEHOOK. This has been set for x86 (including +// x86_64) since Linux 2.6.28 (99bbc4b1e677a), but for ARM only since +// Linux 3.5.0 (0693bf68148c4). Older Linux kernels support PTRACE_GETREGS, +// PTRACE_GETFPREGS, and PTRACE_GETVFPREGS instead, which don't allow checking +// the size of data copied. +// +// Fortunately, 64-bit ARM support only appeared in Linux 3.7.0, so if +// PTRACE_GETREGSET fails on ARM with EIO, indicating that the request is not +// supported, the kernel must be old enough that 64-bit ARM isn’t supported +// either. +// +// TODO(mark): Once helpers to interpret the kernel version are available, add +// a DCHECK to ensure that the kernel is older than 3.5. + +bool GetGeneralPurposeRegistersLegacy(pid_t tid, ThreadContext* context) { + if (ptrace(PTRACE_GETREGS, tid, nullptr, &context->t32) != 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + return true; +} + +bool GetFloatingPointRegistersLegacy(pid_t tid, FloatContext* context) { + if (ptrace(PTRACE_GETFPREGS, tid, nullptr, &context->f32.fpregs) != 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + context->f32.have_fpregs = true; + + if (ptrace(PTRACE_GETVFPREGS, tid, nullptr, &context->f32.vfp) != 0) { + switch (errno) { + case EINVAL: + // These registers are optional on 32-bit ARM cpus + break; + default: + PLOG(ERROR) << "ptrace"; + return false; + } + } else { + context->f32.have_vfp = true; + } + return true; +} +#endif // ARCH_CPU_ARMEL + +#if defined(ARCH_CPU_ARM_FAMILY) +// Normally, the Linux kernel will copy out register sets according to the size +// of the struct that contains them. Tracing a 32-bit ARM process running in +// compatibility mode on a 64-bit ARM cpu will only copy data for the number of +// registers times the size of the register, which won't include any possible +// trailing padding in the struct. These are the sizes of the register data, not +// including any possible padding. +constexpr size_t kArmVfpSize = 32 * 8 + 4; + +// Target is 32-bit +bool GetFloatingPointRegisters32(pid_t tid, FloatContext* context) { + context->f32.have_fpregs = false; + context->f32.have_vfp = false; + + iovec iov; + iov.iov_base = &context->f32.fpregs; + iov.iov_len = sizeof(context->f32.fpregs); + if (ptrace( + PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_PRFPREG), &iov) != + 0) { + switch (errno) { +#if defined(ARCH_CPU_ARMEL) + case EIO: + return GetFloatingPointRegistersLegacy(tid, context); +#endif // ARCH_CPU_ARMEL + case EINVAL: + // A 32-bit process running on a 64-bit CPU doesn't have this register + // set. It should have a VFP register set instead. + break; + default: + PLOG(ERROR) << "ptrace"; + return false; + } + } else { + if (iov.iov_len != sizeof(context->f32.fpregs)) { + LOG(ERROR) << "Unexpected registers size"; + return false; + } + context->f32.have_fpregs = true; + } + + iov.iov_base = &context->f32.vfp; + iov.iov_len = sizeof(context->f32.vfp); + if (ptrace( + PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_ARM_VFP), &iov) != + 0) { + switch (errno) { + case EINVAL: + // VFP may not be present on 32-bit ARM cpus. + break; + default: + PLOG(ERROR) << "ptrace"; + return false; + } + } else { + if (iov.iov_len != kArmVfpSize && iov.iov_len != sizeof(context->f32.vfp)) { + LOG(ERROR) << "Unexpected registers size"; + return false; + } + context->f32.have_vfp = true; + } + + if (!(context->f32.have_fpregs || context->f32.have_vfp)) { + LOG(ERROR) << "Unable to collect registers"; + return false; + } + return true; +} + +// Target is 64-bit +bool GetFloatingPointRegisters64(pid_t tid, FloatContext* context) { + iovec iov; + iov.iov_base = context; + iov.iov_len = sizeof(*context); + if (ptrace( + PTRACE_GETREGSET, tid, reinterpret_cast<void*>(NT_PRFPREG), &iov) != + 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + if (iov.iov_len != sizeof(context->f64)) { + LOG(ERROR) << "Unexpected registers size"; + return false; + } + return true; +} +#endif // ARCH_CPU_ARM_FAMILY + +} // namespace + +ThreadContext::ThreadContext() { + memset(this, 0, sizeof(*this)); +} + +ThreadContext::~ThreadContext() {} + +FloatContext::FloatContext() { + memset(this, 0, sizeof(*this)); +} + +FloatContext::~FloatContext() {} + +ThreadInfo::ThreadInfo() + : context_(), attachment_(), tid_(-1), initialized_(), is_64_bit_(false) {} + +ThreadInfo::~ThreadInfo() {} + +bool ThreadInfo::Initialize(pid_t tid) { + INITIALIZATION_STATE_SET_INITIALIZING(initialized_); + + if (!attachment_.ResetAttach(tid)) { + return false; + } + tid_ = tid; + + size_t length = GetGeneralPurposeRegistersAndLength(&context_); + if (length == sizeof(context_.t64)) { + is_64_bit_ = true; + } else if (length == sizeof(context_.t32)) { + is_64_bit_ = false; + } else { + LOG(ERROR) << "Unexpected registers size"; + return false; + } + + INITIALIZATION_STATE_SET_VALID(initialized_); + return true; +} + +bool ThreadInfo::Is64Bit() { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + return is_64_bit_; +} + +void ThreadInfo::GetGeneralPurposeRegisters(ThreadContext* context) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + *context = context_; +} + +size_t ThreadInfo::GetGeneralPurposeRegistersAndLength(ThreadContext* context) { + iovec iov; + iov.iov_base = context; + iov.iov_len = sizeof(*context); + if (ptrace( + PTRACE_GETREGSET, tid_, reinterpret_cast<void*>(NT_PRSTATUS), &iov) != + 0) { + switch (errno) { +#if defined(ARCH_CPU_ARMEL) + case EIO: + if (GetGeneralPurposeRegistersLegacy(tid_, context)) { + return sizeof(context->t32); + } +#endif // ARCH_CPU_ARMEL + default: + PLOG(ERROR) << "ptrace"; + return 0; + } + } + return iov.iov_len; +} + +bool ThreadInfo::GetFloatingPointRegisters(FloatContext* context) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + +#if defined(ARCH_CPU_X86_FAMILY) + iovec iov; + iov.iov_base = context; + iov.iov_len = sizeof(*context); + if (ptrace( + PTRACE_GETREGSET, tid_, reinterpret_cast<void*>(NT_PRFPREG), &iov) != + 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + if (is_64_bit_ && iov.iov_len == sizeof(context->f64)) { + return true; + } + if (!is_64_bit_ && iov.iov_len == sizeof(context->f32)) { + return true; + } + LOG(ERROR) << "Unexpected registers size"; + return false; + +#elif defined(ARCH_CPU_ARM_FAMILY) + return is_64_bit_ ? GetFloatingPointRegisters64(tid_, context) + : GetFloatingPointRegisters32(tid_, context); +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY +} + +bool ThreadInfo::GetThreadArea(LinuxVMAddress* address) { + INITIALIZATION_STATE_DCHECK_VALID(initialized_); + +#if defined(ARCH_CPU_X86_FAMILY) + if (is_64_bit_) { + *address = context_.t64.fs_base; + return true; + } + + user_desc desc; + iovec iov; + iov.iov_base = &desc; + iov.iov_len = sizeof(desc); + *address = 0; + if (ptrace( + PTRACE_GETREGSET, tid_, reinterpret_cast<void*>(NT_386_TLS), &iov) != + 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + *address = desc.base_addr; + return true; + +#elif defined(ARCH_CPU_ARM_FAMILY) + if (is_64_bit_) { + iovec iov; + iov.iov_base = address; + iov.iov_len = sizeof(*address); + if (ptrace(PTRACE_GETREGSET, + tid_, + reinterpret_cast<void*>(NT_ARM_TLS), + &iov) != 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + if (iov.iov_len != 8) { + LOG(ERROR) << "address size mismatch"; + return false; + } + return true; + } + +#if defined(ARCH_CPU_ARMEL) + void* result; + if (ptrace(PTRACE_GET_THREAD_AREA, tid_, nullptr, &result) != 0) { + PLOG(ERROR) << "ptrace"; + return false; + } + *address = FromPointerCast<LinuxVMAddress>(result); + return true; +#else + // TODO(jperaza): it doesn't look like there is a way for a 64-bit ARM process + // to get the thread area for a 32-bit ARM process with ptrace. + LOG(WARNING) << "64-bit ARM cannot trace TLS area for a 32-bit process"; + return false; +#endif // ARCH_CPU_ARMEL +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/linux/thread_info.h b/third_party/crashpad/crashpad/util/linux/thread_info.h new file mode 100644 index 0000000..6fb2621d --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/thread_info.h
@@ -0,0 +1,284 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_UTIL_LINUX_THREAD_INFO_H_ +#define CRASHPAD_UTIL_LINUX_THREAD_INFO_H_ + +#include <stdint.h> +#include <sys/types.h> +#include <sys/user.h> + +#include <type_traits> + +#include "build/build_config.h" +#include "util/linux/address_types.h" +#include "util/linux/scoped_ptrace_attach.h" +#include "util/misc/initialization_state_dcheck.h" +#include "util/numeric/int128.h" + +namespace crashpad { + +//! \brief The set of general purpose registers for an architecture family. +union ThreadContext { + ThreadContext(); + ~ThreadContext(); + + //! \brief The general purpose registers used by the 32-bit variant of the + //! architecture. + struct t32 { +#if defined(ARCH_CPU_X86_FAMILY) + // Reflects user_regs_struct in sys/user.h. + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t esi; + uint32_t edi; + uint32_t ebp; + uint32_t eax; + uint32_t xds; + uint32_t xes; + uint32_t xfs; + uint32_t xgs; + uint32_t orig_eax; + uint32_t eip; + uint32_t xcs; + uint32_t eflags; + uint32_t esp; + uint32_t xss; +#elif defined(ARCH_CPU_ARM_FAMILY) + // Reflects user_regs in sys/user.h. + uint32_t regs[11]; + uint32_t fp; + uint32_t ip; + uint32_t sp; + uint32_t lr; + uint32_t pc; + uint32_t cpsr; + uint32_t orig_r0; +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY + } t32; + + //! \brief The general purpose registers used by the 64-bit variant of the + //! architecture. + struct t64 { +#if defined(ARCH_CPU_X86_FAMILY) + // Reflects user_regs_struct in sys/user.h. + uint64_t r15; + uint64_t r14; + uint64_t r13; + uint64_t r12; + uint64_t rbp; + uint64_t rbx; + uint64_t r11; + uint64_t r10; + uint64_t r9; + uint64_t r8; + uint64_t rax; + uint64_t rcx; + uint64_t rdx; + uint64_t rsi; + uint64_t rdi; + uint64_t orig_rax; + uint64_t rip; + uint64_t cs; + uint64_t eflags; + uint64_t rsp; + uint64_t ss; + uint64_t fs_base; + uint64_t gs_base; + uint64_t ds; + uint64_t es; + uint64_t fs; + uint64_t gs; +#elif defined(ARCH_CPU_ARM_FAMILY) + // Reflects user_regs_struct in sys/user.h. + uint64_t regs[31]; + uint64_t sp; + uint64_t pc; + uint64_t pstate; +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY + } t64; + +#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64) + using NativeThreadContext = user_regs_struct; +#elif defined(ARCH_CPU_ARMEL) + using NativeThreadContext = user_regs; +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY || ARCH_CPU_ARM64 + +#if defined(ARCH_CPU_32_BITS) + static_assert(sizeof(t32) == sizeof(NativeThreadContext), "Size mismatch"); +#else // ARCH_CPU_64_BITS + static_assert(sizeof(t64) == sizeof(NativeThreadContext), "Size mismatch"); +#endif // ARCH_CPU_32_BITS +}; +static_assert(std::is_standard_layout<ThreadContext>::value, + "Not standard layout"); + +//! \brief The floating point registers used for an architecture family. +union FloatContext { + FloatContext(); + ~FloatContext(); + + //! \brief The floating point registers used by the 32-bit variant of the + //! architecture. + struct f32 { +#if defined(ARCH_CPU_X86_FAMILY) + // Reflects user_fpregs_struct in sys/user.h. + uint32_t cwd; + uint32_t swd; + uint32_t twd; + uint32_t fip; + uint32_t fcs; + uint32_t foo; + uint32_t fos; + uint32_t st_space[20]; +#elif defined(ARCH_CPU_ARM_FAMILY) + // Reflects user_fpregs in sys/user.h. + struct fpregs { + struct fp_reg { + uint32_t sign1 : 1; + uint32_t unused : 15; + uint32_t sign2 : 1; + uint32_t exponent : 14; + uint32_t j : 1; + uint32_t mantissa1 : 31; + uint32_t mantisss0 : 32; + } fpregs[8]; + uint32_t fpsr : 32; + uint32_t fpcr : 32; + uint8_t type[8]; + uint32_t init_flag; + } fpregs; + + // Reflects user_vfp in sys/user.h. + struct vfp { + uint64_t fpregs[32]; + uint32_t fpscr; + } vfp; + + bool have_fpregs; + bool have_vfp; +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY + } f32; + + //! \brief The floating point registers used by the 64-bit variant of the + //! architecture. + struct f64 { +#if defined(ARCH_CPU_X86_FAMILY) + uint16_t cwd; + uint16_t swd; + uint16_t ftw; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcr_mask; + uint32_t st_space[32]; + uint32_t xmm_space[64]; + uint32_t padding[24]; +#elif defined(ARCH_CPU_ARM_FAMILY) + uint128_struct vregs[32]; + uint32_t fpsr; + uint32_t fpcr; + uint8_t padding[8]; +#else +#error Port. +#endif // ARCH_CPU_X86_FAMILY + } f64; + +#if defined(ARCH_CPU_X86) + static_assert(sizeof(f32) == sizeof(user_fpregs_struct), "Size mismatch"); +#elif defined(ARCH_CPU_X86_64) + static_assert(sizeof(f64) == sizeof(user_fpregs_struct), "Size mismatch"); +#elif defined(ARCH_CPU_ARMEL) + static_assert(sizeof(f32::fpregs) == sizeof(user_fpregs), "Size mismatch"); + static_assert(sizeof(f32::vfp) == sizeof(user_vfp), "Size mismatch"); +#elif defined(ARCH_CPU_ARM64) + static_assert(sizeof(f64) == sizeof(user_fpsimd_struct), "Size mismatch"); +#else +#error Port. +#endif // ARCH_CPU_X86 +}; +static_assert(std::is_standard_layout<FloatContext>::value, + "Not standard layout"); + +class ThreadInfo { + public: + ThreadInfo(); + ~ThreadInfo(); + + //! \brief Initializes this object with information about the thread whose ID + //! is \a tid. + //! + //! This method must be called successfully prior to calling any other method + //! in this class. This method may only be called once. + //! + //! It is unspecified whether the information that an object of this class + //! returns is loaded at the time Initialize() is called or subsequently, and + //! whether this information is cached in the object or not. + //! + //! \param[in] tid The thread ID to obtain information for. + //! + //! \return `true` on success, `false` on failure with a message logged. + bool Initialize(pid_t tid); + + //! \brief Determines the target thread’s bitness. + //! + //! \return `true` if the target is 64-bit. + bool Is64Bit(); + + //! \brief Uses `ptrace` to collect general purpose registers from the target + //! thread and places the result in \a context. + //! + //! \param[out] context The registers read from the target thread. + void GetGeneralPurposeRegisters(ThreadContext* context); + + //! \brief Uses `ptrace` to collect floating point registers from the target + //! thread and places the result in \a context. + //! + //! \param[out] context The registers read from the target thread. + //! + //! \return `true` on success, with \a context set. Otherwise, `false` with a + //! message logged. + bool GetFloatingPointRegisters(FloatContext* context); + + //! \brief Uses `ptrace` to determine the thread-local storage address for the + //! target thread and places the result in \a address. + //! + //! \param[out] address The address of the TLS area. + //! + //! \return `true` on success. `false` on failure with a message logged. + bool GetThreadArea(LinuxVMAddress* address); + + private: + size_t GetGeneralPurposeRegistersAndLength(ThreadContext* context); + + ThreadContext context_; + ScopedPtraceAttach attachment_; + pid_t tid_; + InitializationStateDcheck initialized_; + bool is_64_bit_; +}; + +} // namespace crashpad + +#endif // CRASHPAD_UTIL_LINUX_THREAD_INFO_H_
diff --git a/third_party/crashpad/crashpad/util/linux/thread_info_test.cc b/third_party/crashpad/crashpad/util/linux/thread_info_test.cc new file mode 100644 index 0000000..fe05b4a --- /dev/null +++ b/third_party/crashpad/crashpad/util/linux/thread_info_test.cc
@@ -0,0 +1,100 @@ +// Copyright 2017 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/linux/thread_info.h" + +#include "build/build_config.h" +#include "gtest/gtest.h" +#include "test/multiprocess.h" +#include "util/file/file_io.h" +#include "util/misc/from_pointer_cast.h" + +namespace crashpad { +namespace test { +namespace { + +class SameBitnessTest : public Multiprocess { + public: + SameBitnessTest() : Multiprocess() {} + ~SameBitnessTest() {} + + private: + void MultiprocessParent() override { + LinuxVMAddress expected_tls; + CheckedReadFileExactly( + ReadPipeHandle(), &expected_tls, sizeof(expected_tls)); + + ThreadInfo thread_info; + ASSERT_TRUE(thread_info.Initialize(ChildPID())); + +#if defined(ARCH_CPU_64_BITS) + const bool am_64_bit = true; +#else + const bool am_64_bit = false; +#endif // ARCH_CPU_64_BITS + + EXPECT_EQ(thread_info.Is64Bit(), am_64_bit); + + ThreadContext thread_context; + thread_info.GetGeneralPurposeRegisters(&thread_context); + +#if defined(ARCH_CPU_X86_64) + EXPECT_EQ(thread_context.t64.fs_base, expected_tls); +#endif // ARCH_CPU_X86_64 + + FloatContext float_context; + EXPECT_TRUE(thread_info.GetFloatingPointRegisters(&float_context)); + + LinuxVMAddress tls_address; + ASSERT_TRUE(thread_info.GetThreadArea(&tls_address)); + EXPECT_EQ(tls_address, expected_tls); + } + + void MultiprocessChild() override { + LinuxVMAddress expected_tls; +#if defined(ARCH_CPU_ARMEL) + // 0xffff0fe0 is the address of the kernel user helper __kuser_get_tls(). + auto kuser_get_tls = reinterpret_cast<void* (*)()>(0xffff0fe0); + expected_tls = FromPointerCast<LinuxVMAddress>(kuser_get_tls()); +#elif defined(ARCH_CPU_ARM64) + // Linux/aarch64 places the tls address in system register tpidr_el0. + asm("mrs %0, tpidr_el0" : "=r"(expected_tls)); +#elif defined(ARCH_CPU_X86) + uint32_t expected_tls_32; + asm("movl %%gs:0x0, %0" : "=r"(expected_tls_32)); + expected_tls = expected_tls_32; +#elif defined(ARCH_CPU_X86_64) + asm("movq %%fs:0x0, %0" : "=r"(expected_tls)); +#else +#error Port. +#endif // ARCH_CPU_ARMEL + + CheckedWriteFile(WritePipeHandle(), &expected_tls, sizeof(expected_tls)); + + CheckedReadFileAtEOF(ReadPipeHandle()); + } + + DISALLOW_COPY_AND_ASSIGN(SameBitnessTest); +}; + +TEST(ThreadInfo, SameBitness) { + SameBitnessTest test; + test.Run(); +} + +// TODO(jperaza): Test against a process with different bitness. + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/posix/process_info_linux.cc b/third_party/crashpad/crashpad/util/posix/process_info_linux.cc index 65d9644..ac3a2ae 100644 --- a/third_party/crashpad/crashpad/util/posix/process_info_linux.cc +++ b/third_party/crashpad/crashpad/util/posix/process_info_linux.cc
@@ -15,12 +15,8 @@ #include "util/posix/process_info.h" #include <ctype.h> -#include <elf.h> #include <errno.h> #include <string.h> -#include <sys/ptrace.h> -#include <sys/uio.h> -#include <sys/user.h> #include <time.h> #include <unistd.h> @@ -33,7 +29,7 @@ #include "util/file/delimited_file_reader.h" #include "util/file/file_io.h" #include "util/file/file_reader.h" -#include "util/linux/scoped_ptrace_attach.h" +#include "util/linux/thread_info.h" namespace crashpad { @@ -305,57 +301,11 @@ if (pid_ == getpid()) { is_64_bit_ = am_64_bit; } else { - ScopedPtraceAttach ptrace_attach; - if (!ptrace_attach.ResetAttach(pid_)) { + ThreadInfo thread_info; + if (!thread_info.Initialize(pid_)) { return false; } - - // Allocate more buffer space than is required to hold registers for this - // process. If the kernel fills the extra space, the target process uses - // more/larger registers than this process. If the kernel fills less space - // than sizeof(regs) then the target process uses smaller/fewer registers. - struct { -#if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM64) - using PrStatusType = user_regs_struct; -#elif defined(ARCH_CPU_ARMEL) - using PrStatusType = user_regs; -#endif - PrStatusType regs; - char extra; - } regbuf; - - iovec iov; - iov.iov_base = ®buf; - iov.iov_len = sizeof(regbuf); - if (ptrace(PTRACE_GETREGSET, - pid_, - reinterpret_cast<void*>(NT_PRSTATUS), - &iov) != 0) { - switch (errno) { -#if defined(ARCH_CPU_ARMEL) - case EIO: - // PTRACE_GETREGSET, introduced in Linux 2.6.34 (2225a122ae26), - // requires kernel support enabled by HAVE_ARCH_TRACEHOOK. This has - // been set for x86 (including x86_64) since Linux 2.6.28 - // (99bbc4b1e677a), but for ARM only since Linux 3.5.0 - // (0693bf68148c4). Fortunately, 64-bit ARM support only appeared in - // Linux 3.7.0, so if PTRACE_GETREGSET fails on ARM with EIO, - // indicating that the request is not supported, the kernel must be - // old enough that 64-bit ARM isn’t supported either. - // - // TODO(mark): Once helpers to interpret the kernel version are - // available, add a DCHECK to ensure that the kernel is older than - // 3.5. - is_64_bit_ = false; - break; -#endif - default: - PLOG(ERROR) << "ptrace"; - return false; - } - } else { - is_64_bit_ = am_64_bit == (iov.iov_len == sizeof(regbuf.regs)); - } + is_64_bit_ = thread_info.Is64Bit(); } is_64_bit_initialized_.set_valid();
diff --git a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc index 2799558e..4a018f5 100644 --- a/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc +++ b/third_party/crashpad/crashpad/util/stdlib/aligned_allocator_test.cc
@@ -16,6 +16,7 @@ #include <stdint.h> +#include "base/compiler_specific.h" #include "gtest/gtest.h" #if defined(OS_WIN)
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp index e3074e9a..8e5c7cfe 100644 --- a/third_party/crashpad/crashpad/util/util.gyp +++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -45,11 +45,15 @@ 'file/string_file.cc', 'file/string_file.h', 'linux/address_types.h', + 'linux/auxiliary_vector.cc', + 'linux/auxiliary_vector.h', 'linux/checked_address_range.h', 'linux/memory_map.cc', 'linux/memory_map.h', 'linux/process_memory.cc', 'linux/process_memory.h', + 'linux/thread_info.cc', + 'linux/thread_info.h', 'linux/scoped_ptrace_attach.cc', 'linux/scoped_ptrace_attach.h', 'mac/checked_mach_address_range.h',
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp index db54a9b0..ef5a681 100644 --- a/third_party/crashpad/crashpad/util/util_test.gyp +++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -39,8 +39,10 @@ 'file/file_io_test.cc', 'file/file_reader_test.cc', 'file/string_file_test.cc', + 'linux/auxiliary_vector_test.cc', 'linux/memory_map_test.cc', 'linux/process_memory_test.cc', + 'linux/thread_info_test.cc', 'linux/scoped_ptrace_attach_test.cc', 'mac/launchd_test.mm', 'mac/mac_util_test.mm',
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index cbf76fc1..662f9a8 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -269,6 +269,40 @@ </metric> </event> +<event name="Event.ScrollBegin.Touch"> + <owner>nzolghadr@chromium.org</owner> + <summary> + Metrics related to first scroll action caused by the generated ScrollUpdate + gesture event. + </summary> + <metric name="TimeToScrollUpdateSwapBegin"> + <summary> + The time in microseconds between initial creation of a touch event and the + start of the frame swap on the GPU service caused by the generated + ScrollUpdate gesture event if that ScrollUpdate is the first such event in + a given scroll gesture event sequence. If no swap was induced by the + event, no recording is made. + </summary> + </metric> +</event> + +<event name="Event.ScrollBegin.Wheel"> + <owner>nzolghadr@chromium.org</owner> + <summary> + Metrics related to first scroll action caused by the generated ScrollUpdate + gesture event. + </summary> + <metric name="TimeToScrollUpdateSwapBegin"> + <summary> + The time in microseconds between the initial creation of a wheel event and + the start of the frame swap on the GPU service caused by the generated + ScrollUpdate gesture event if that ScrollUpdate is the first such event in + a given scroll gesture event sequence. If no swap was induced by the + event, no recording is made. + </summary> + </metric> +</event> + <event name="Media.WatchTime"> <owner>dalecurtis@chromium.org</owner> <summary>
diff --git a/ui/app_list/views/page_switcher_vertical.cc b/ui/app_list/views/page_switcher_vertical.cc index 3155bf7d..a22d1d9 100644 --- a/ui/app_list/views/page_switcher_vertical.cc +++ b/ui/app_list/views/page_switcher_vertical.cc
@@ -14,6 +14,11 @@ #include "ui/gfx/canvas.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/skia_util.h" +#include "ui/views/animation/flood_fill_ink_drop_ripple.h" +#include "ui/views/animation/ink_drop_highlight.h" +#include "ui/views/animation/ink_drop_impl.h" +#include "ui/views/animation/ink_drop_mask.h" +#include "ui/views/animation/ink_drop_painted_layer_delegates.h" #include "ui/views/controls/button/custom_button.h" #include "ui/views/layout/box_layout.h" @@ -21,103 +26,137 @@ namespace { -const int kPreferredWidth = 58; +constexpr int kNormalButtonRadius = 3; +constexpr int kSelectedButtonRadius = 4; +constexpr int kInkDropRadius = 8; +// The padding on top/bottom side of each button. +constexpr int kButtonPadding = 12; +// The padding of a list of buttons as a button strip. +constexpr int kButtonStripPadding = 24; +constexpr int kMaxButtonRadius = 8; +constexpr int kPreferredButtonStripWidth = + kMaxButtonRadius * 2 + kButtonStripPadding * 2; -const int kMaxButtonSpacing = 18; -const int kMinButtonSpacing = 4; -const int kMaxButtonHeight = 68; -const int kMinButtonHeight = 28; -const int kButtonWidth = 6; -const int kButtonCornerRadius = 2; -const int kButtonStripPadding = 20; +// The selected button color. +constexpr SkColor kSelectedButtonColor = SK_ColorWHITE; +// The normal button color (54% white). +constexpr SkColor kNormalColor = SkColorSetA(SK_ColorWHITE, 138); +constexpr SkColor kInkDropBaseColor = SK_ColorWHITE; +constexpr SkColor kInkDropRippleColor = SkColorSetA(kInkDropBaseColor, 20); +constexpr SkColor kInkDropHighlightColor = SkColorSetA(kInkDropBaseColor, 15); + +constexpr SkScalar kStrokeWidth = SkIntToScalar(1); class PageSwitcherButton : public views::CustomButton { public: explicit PageSwitcherButton(views::ButtonListener* listener) - : views::CustomButton(listener), - button_height_(kMaxButtonHeight), - selected_range_(0) {} - ~PageSwitcherButton() override {} - - void SetSelectedRange(double selected_range) { - if (selected_range_ == selected_range) - return; - - selected_range_ = selected_range; - SchedulePaint(); + : views::CustomButton(listener) { + SetInkDropMode(InkDropMode::ON); } - void set_button_height(int button_height) { button_height_ = button_height; } + ~PageSwitcherButton() override {} + + void SetSelected(bool selected) { + if (selected == selected_) + return; + + selected_ = selected; + SchedulePaint(); + } // Overridden from views::View: gfx::Size CalculatePreferredSize() const override { - return gfx::Size(kButtonWidth, button_height_); + return gfx::Size(kMaxButtonRadius * 2, kMaxButtonRadius * 2); } void PaintButtonContents(gfx::Canvas* canvas) override { - if (state() == STATE_HOVERED) - PaintButton(canvas, kPagerHoverColor); - else - PaintButton(canvas, kPagerNormalColor); + PaintButton(canvas, BuildPaintButtonInfo()); } - void OnGestureEvent(ui::GestureEvent* event) override { - CustomButton::OnGestureEvent(event); + protected: + bool IsTriggerableEvent(const ui::Event& event) override { + return event.IsMouseEvent() && + (triggerable_event_flags() & event.flags()) != 0; + } - if (event->type() == ui::ET_GESTURE_TAP_DOWN) - SetState(views::CustomButton::STATE_HOVERED); - else if (event->type() == ui::ET_GESTURE_TAP_CANCEL || - event->type() == ui::ET_GESTURE_TAP) - SetState(views::CustomButton::STATE_NORMAL); - SchedulePaint(); + std::unique_ptr<views::InkDrop> CreateInkDrop() override { + std::unique_ptr<views::InkDropImpl> ink_drop = + CustomButton::CreateDefaultInkDropImpl(); + ink_drop->SetShowHighlightOnHover(false); + ink_drop->SetAutoHighlightMode( + views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE); + return std::move(ink_drop); + } + + std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override { + return base::MakeUnique<views::CircleInkDropMask>( + size(), GetLocalBounds().CenterPoint(), kMaxButtonRadius); + } + + std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override { + gfx::Point center = GetLocalBounds().CenterPoint(); + gfx::Rect bounds(center.x() - kMaxButtonRadius, + center.y() - kMaxButtonRadius, 2 * kMaxButtonRadius, + 2 * kMaxButtonRadius); + return base::MakeUnique<views::FloodFillInkDropRipple>( + size(), GetLocalBounds().InsetsFrom(bounds), + GetInkDropCenterBasedOnLastEvent(), kInkDropRippleColor, 1.0f); + } + + std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() + const override { + return base::MakeUnique<views::InkDropHighlight>( + gfx::PointF(GetLocalBounds().CenterPoint()), + base::MakeUnique<views::CircleLayerDelegate>(kInkDropHighlightColor, + kInkDropRadius)); + } + + void NotifyClick(const ui::Event& event) override { + CustomButton::NotifyClick(event); + GetInkDrop()->AnimateToState(views::InkDropState::ACTION_TRIGGERED); } private: - // Paints a button that has two rounded corner at bottom. - void PaintButton(gfx::Canvas* canvas, SkColor base_color) { - gfx::Rect rect(GetContentsBounds()); - rect.ClampToCenteredSize(gfx::Size(kButtonWidth, button_height_)); + // Stores the information of how to paint the button. + struct PaintButtonInfo { + SkColor color; + cc::PaintFlags::Style style; + SkScalar radius; + SkScalar stroke_width; + }; + // Returns the information of how to paint selected/normal button. + PaintButtonInfo BuildPaintButtonInfo() { + PaintButtonInfo info; + if (selected_) { + info.color = kSelectedButtonColor; + info.style = cc::PaintFlags::kFill_Style; + info.radius = SkIntToScalar(kSelectedButtonRadius); + info.stroke_width = SkIntToScalar(0); + } else { + info.color = kNormalColor; + info.style = cc::PaintFlags::kStroke_Style; + info.radius = SkIntToScalar(kNormalButtonRadius); + info.stroke_width = kStrokeWidth; + } + return info; + } + + // Paints a button based on the |info|. + void PaintButton(gfx::Canvas* canvas, PaintButtonInfo info) { + gfx::Rect rect(GetContentsBounds()); SkPath path; - path.addRoundRect(gfx::RectToSkRect(rect), - SkIntToScalar(kButtonCornerRadius), - SkIntToScalar(kButtonCornerRadius)); + path.addCircle(rect.CenterPoint().x(), rect.CenterPoint().y(), info.radius); cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setStyle(cc::PaintFlags::kFill_Style); - flags.setColor(base_color); + flags.setStyle(info.style); + flags.setColor(info.color); canvas->DrawPath(path, flags); - - int selected_start_y = 0; - int selected_height = 0; - if (selected_range_ > 0) { - selected_height = selected_range_ * rect.height(); - } else if (selected_range_ < 0) { - selected_height = -selected_range_ * rect.height(); - selected_start_y = rect.bottom() - selected_height; - } - - if (selected_height) { - gfx::Rect selected_rect(rect); - selected_rect.set_y(selected_start_y); - selected_rect.set_height(selected_height); - - SkPath selected_path; - selected_path.addRoundRect(gfx::RectToSkRect(selected_rect), - SkIntToScalar(kButtonCornerRadius), - SkIntToScalar(kButtonCornerRadius)); - flags.setColor(kPagerSelectedColor); - canvas->DrawPath(selected_path, flags); - } } - int button_height_; - - // [-1, 1] range that represents the portion of the button that should be - // painted with kSelectedColor. Positive range starts from top side and - // negative range starts from the bottom side. - double selected_range_; + // If this button is selected, set to true. By default, set to false; + bool selected_ = false; DISALLOW_COPY_AND_ASSIGN(PageSwitcherButton); }; @@ -131,6 +170,10 @@ PageSwitcherVertical::PageSwitcherVertical(PaginationModel* model) : model_(model), buttons_(new views::View) { + buttons_->SetLayoutManager(new views::BoxLayout( + views::BoxLayout::kVertical, + gfx::Insets(kButtonStripPadding, kButtonStripPadding), kButtonPadding)); + AddChildView(buttons_); TotalPagesChanged(); @@ -179,14 +222,13 @@ gfx::Size PageSwitcherVertical::CalculatePreferredSize() const { // Always return a size with correct width so that container resize is not // needed when more pages are added. - return gfx::Size(kPreferredWidth, buttons_->GetPreferredSize().height()); + return gfx::Size(kPreferredButtonStripWidth, + buttons_->GetPreferredSize().height()); } void PageSwitcherVertical::Layout() { gfx::Rect rect(GetContentsBounds()); - CalculateButtonHeightAndSpacing(rect.height()); - // Makes |buttons_| vertically center and horizontally fill. gfx::Size buttons_size(buttons_->GetPreferredSize()); gfx::Rect buttons_bounds(rect.x(), @@ -195,38 +237,6 @@ buttons_->SetBoundsRect(gfx::IntersectRects(rect, buttons_bounds)); } -void PageSwitcherVertical::CalculateButtonHeightAndSpacing( - int contents_height) { - const int button_count = buttons_->child_count(); - if (!button_count) - return; - - contents_height -= 2 * kButtonStripPadding; - - int button_height = kMinButtonHeight; - int button_spacing = kMinButtonSpacing; - if (button_count > 1) { - button_spacing = - (contents_height - button_height * button_count) / (button_count - 1); - button_spacing = std::min(kMaxButtonSpacing, - std::max(kMinButtonSpacing, button_spacing)); - } - - button_height = - (contents_height - (button_count - 1) * button_spacing) / button_count; - button_height = - std::min(kMaxButtonHeight, std::max(kMinButtonHeight, button_height)); - - buttons_->SetLayoutManager(new views::BoxLayout( - views::BoxLayout::kVertical, gfx::Insets(kButtonStripPadding, 0), - button_spacing)); - for (int i = 0; i < button_count; ++i) { - PageSwitcherButton* button = - static_cast<PageSwitcherButton*>(buttons_->child_at(i)); - button->set_button_height(button_height); - } -} - void PageSwitcherVertical::ButtonPressed(views::Button* sender, const ui::Event& event) { for (int i = 0; i < buttons_->child_count(); ++i) { @@ -241,7 +251,7 @@ buttons_->RemoveAllChildViews(true); for (int i = 0; i < model_->total_pages(); ++i) { PageSwitcherButton* button = new PageSwitcherButton(this); - button->SetSelectedRange(i == model_->selected_page() ? 1 : 0); + button->SetSelected(i == model_->selected_page() ? true : false); buttons_->AddChildView(button); } buttons_->SetVisible(model_->total_pages() > 1); @@ -251,28 +261,13 @@ void PageSwitcherVertical::SelectedPageChanged(int old_selected, int new_selected) { if (old_selected >= 0 && old_selected < buttons_->child_count()) - GetButtonByIndex(buttons_, old_selected)->SetSelectedRange(0); + GetButtonByIndex(buttons_, old_selected)->SetSelected(false); if (new_selected >= 0 && new_selected < buttons_->child_count()) - GetButtonByIndex(buttons_, new_selected)->SetSelectedRange(1); + GetButtonByIndex(buttons_, new_selected)->SetSelected(true); } void PageSwitcherVertical::TransitionStarted() {} -void PageSwitcherVertical::TransitionChanged() { - const int current_page = model_->selected_page(); - const int target_page = model_->transition().target_page; - - double progress = model_->transition().progress; - double remaining = progress - 1; - - if (current_page > target_page) { - remaining = -remaining; - progress = -progress; - } - - GetButtonByIndex(buttons_, current_page)->SetSelectedRange(remaining); - if (model_->is_valid_page(target_page)) - GetButtonByIndex(buttons_, target_page)->SetSelectedRange(progress); -} +void PageSwitcherVertical::TransitionChanged() {} } // namespace app_list
diff --git a/ui/app_list/views/page_switcher_vertical.h b/ui/app_list/views/page_switcher_vertical.h index 0f2198ad..39547a4 100644 --- a/ui/app_list/views/page_switcher_vertical.h +++ b/ui/app_list/views/page_switcher_vertical.h
@@ -33,8 +33,6 @@ void Layout() override; private: - void CalculateButtonHeightAndSpacing(int contents_height); - // Overridden from views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override;
diff --git a/ui/latency/latency_tracker.cc b/ui/latency/latency_tracker.cc index 494a89c..5be7a26c 100644 --- a/ui/latency/latency_tracker.cc +++ b/ui/latency/latency_tracker.cc
@@ -159,6 +159,10 @@ ".TimeToScrollUpdateSwapBegin2", original_component, gpu_swap_begin_component); + ReportUkmScrollLatency("Event.ScrollBegin." + input_modality, + "TimeToScrollUpdateSwapBegin", original_component, + gpu_swap_begin_component); + // TODO(lanwei): Will remove them when M56 is stable, see // https://crbug.com/669618. UMA_HISTOGRAM_INPUT_LATENCY_HIGH_RESOLUTION_MICROSECONDS( @@ -179,6 +183,7 @@ ReportRapporScrollLatency( "Event.Latency.ScrollUpdate.Touch.TimeToScrollUpdateSwapBegin2", original_component, gpu_swap_begin_component); + ReportUkmScrollLatency("Event.ScrollUpdate.Touch", "TimeToScrollUpdateSwapBegin", original_component, gpu_swap_begin_component);
diff --git a/ui/views/bubble/bubble_dialog_delegate.h b/ui/views/bubble/bubble_dialog_delegate.h index e027988d..76d0235 100644 --- a/ui/views/bubble/bubble_dialog_delegate.h +++ b/ui/views/bubble/bubble_dialog_delegate.h
@@ -148,7 +148,7 @@ void SetAnchorRect(const gfx::Rect& rect); // Resize and potentially move the bubble to fit the content's preferred size. - void SizeToContents(); + virtual void SizeToContents(); BubbleFrameView* GetBubbleFrameView() const;
diff --git a/ui/views/bubble/tray_bubble_view.cc b/ui/views/bubble/tray_bubble_view.cc index 9f106c1..816b701 100644 --- a/ui/views/bubble/tray_bubble_view.cc +++ b/ui/views/bubble/tray_bubble_view.cc
@@ -265,6 +265,11 @@ return ui::DIALOG_BUTTON_NONE; } +void TrayBubbleView::SizeToContents() { + BubbleDialogDelegateView::SizeToContents(); + bubble_content_mask_->layer()->SetBounds(layer()->bounds()); +} + void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params, Widget* bubble_widget) const { // Apply a WM-provided shadow (see ui/wm/core/).
diff --git a/ui/views/bubble/tray_bubble_view.h b/ui/views/bubble/tray_bubble_view.h index 81042a8..0a11f8a 100644 --- a/ui/views/bubble/tray_bubble_view.h +++ b/ui/views/bubble/tray_bubble_view.h
@@ -145,6 +145,7 @@ protected: // Overridden from views::BubbleDialogDelegateView. int GetDialogButtons() const override; + void SizeToContents() override; // Overridden from views::View. void ChildPreferredSizeChanged(View* child) override;