diff --git a/DEPS b/DEPS index 8e98445..a0cf8672 100644 --- a/DEPS +++ b/DEPS
@@ -52,7 +52,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '794607025b69599dd2607391cb13e51f39423f5d', + 'angle_revision': '982f6e0125af4eaa40ee05157d27cbbd9259d969', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other.
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index c686e6b..70490754 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -191,11 +191,7 @@ # These assets are needed by both monochrome and stand alone WebView, but not by # Chrome. android_assets("monochrome_webview_assets") { - sources = [ - webview_license_path, - ] deps = [ - ":generate_webview_license_notice", "//third_party/icu:icu_assets", "//v8:v8_external_startup_data_assets", ]
diff --git a/android_webview/apk/BUILD.gn b/android_webview/apk/BUILD.gn new file mode 100644 index 0000000..a846f82 --- /dev/null +++ b/android_webview/apk/BUILD.gn
@@ -0,0 +1,15 @@ +# 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. + +import("//build/config/android/rules.gni") + +# Since Monochrome has its own content provider, these two files are put +# in two different targets. +android_library("webview_license_provider_java") { + java_files = [ "//android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java" ] +} + +android_library("webview_license_activity_java") { + java_files = [ "//android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java" ] +}
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/LicenseActivity.java b/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java similarity index 72% rename from android_webview/glue/java/src/com/android/webview/chromium/LicenseActivity.java rename to android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java index 7607a94..7427d0d 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/LicenseActivity.java +++ b/android_webview/apk/java/src/com/android/webview/chromium/LicenseActivity.java
@@ -17,18 +17,20 @@ * other than LicenseContentProvider. */ public class LicenseActivity extends Activity { + private static final String LICENSES_URI_SUFFIX = "LicenseContentProvider/webview_licenses"; + private static final String LICENSES_CONTENT_TYPE = "text/html"; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final String packageName = getPackageName(); final Intent intent = new Intent(Intent.ACTION_VIEW); - final String licenseUri = String.format("content://%s.%s", - packageName, LicenseContentProvider.LICENSES_URI_SUFFIX); - intent.setDataAndType( - Uri.parse(licenseUri), LicenseContentProvider.LICENSES_CONTENT_TYPE); + final String licenseUri = + String.format("content://%s.%s", packageName, LICENSES_URI_SUFFIX); + intent.setDataAndType(Uri.parse(licenseUri), LICENSES_CONTENT_TYPE); intent.addCategory(Intent.CATEGORY_DEFAULT); - final int titleId = getResources().getIdentifier( - "license_activity_title", "string", packageName); + final int titleId = + getResources().getIdentifier("license_activity_title", "string", packageName); if (titleId != 0) { intent.putExtra(Intent.EXTRA_TITLE, getString(titleId)); }
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java b/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java similarity index 95% rename from android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java rename to android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java index 0571e7cb..ef2dd2f 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java +++ b/android_webview/apk/java/src/com/android/webview/chromium/LicenseContentProvider.java
@@ -68,8 +68,7 @@ } @Override - public int update(Uri uri, ContentValues values, String where, - String[] whereArgs) { + public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { throw new UnsupportedOperationException(); } @@ -84,8 +83,8 @@ } @Override - public Cursor query(Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { throw new UnsupportedOperationException(); } -} +} \ No newline at end of file
diff --git a/android_webview/glue/BUILD.gn b/android_webview/glue/BUILD.gn index ab52954..b114738 100644 --- a/android_webview/glue/BUILD.gn +++ b/android_webview/glue/BUILD.gn
@@ -61,8 +61,6 @@ "java/src/com/android/webview/chromium/DrawGLFunctor.java", "java/src/com/android/webview/chromium/GeolocationPermissionsAdapter.java", "java/src/com/android/webview/chromium/GraphicsUtils.java", - "java/src/com/android/webview/chromium/LicenseActivity.java", - "java/src/com/android/webview/chromium/LicenseContentProvider.java", "java/src/com/android/webview/chromium/MonochromeLibraryPreloader.java", "java/src/com/android/webview/chromium/ServiceWorkerClientAdapter.java", "java/src/com/android/webview/chromium/ServiceWorkerControllerAdapter.java",
diff --git a/ash/touch_hud/BUILD.gn b/ash/touch_hud/BUILD.gn index 8c509ef..4411118 100644 --- a/ash/touch_hud/BUILD.gn +++ b/ash/touch_hud/BUILD.gn
@@ -15,6 +15,7 @@ deps = [ "//base", + "//cc/paint", "//skia", "//ui/compositor", "//ui/events",
diff --git a/ash/touch_hud/touch_hud_renderer.cc b/ash/touch_hud/touch_hud_renderer.cc index d6ce0c34..473fcae 100644 --- a/ash/touch_hud/touch_hud_renderer.cc +++ b/ash/touch_hud/touch_hud_renderer.cc
@@ -84,7 +84,7 @@ alpha = static_cast<int>(fadeout_->CurrentValueBetween(alpha, 0)); fill_flags_.setAlpha(alpha); stroke_flags_.setAlpha(alpha); - fill_flags_.setShader(SkGradientShader::MakeRadial( + fill_flags_.setShader(cc::PaintShader::MakeRadialGradient( gradient_center_, SkIntToScalar(kPointRadius), gradient_colors_, gradient_pos_, arraysize(gradient_colors_), SkShader::kMirror_TileMode));
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h index 61e54d8..91a8153ff 100644 --- a/base/memory/shared_memory.h +++ b/base/memory/shared_memory.h
@@ -64,22 +64,6 @@ bool share_read_only = false; }; -// Enumeration of different shared memory error types. Note: Currently only -// errors from Mac POSIX shared memory implementation are fully instrumented. -// TODO(asvitkine): Evaluate whether we want to keep this ability after -// crbug.com/703649 is fixed and expand to all platforms or remove. -enum class SharedMemoryError { - NO_ERRORS, - NO_FILE, - BAD_PARAMS, - STAT_FAILED, - TRUNCATE_FAILED, - NO_TEMP_DIR, - MAKE_READONLY_FAILED, - INODE_MISMATCH, - MMAP_FAILED, -}; - // Platform abstraction for shared memory. // SharedMemory consumes a SharedMemoryHandle [potentially one that it created] // to map a shared memory OS resource into the virtual address space of the @@ -226,13 +210,6 @@ // failure. SharedMemoryHandle GetReadOnlyHandle(); - // Returns the last error encountered as a result of a call to Create() or - // Map(). Note: Currently only errors from Mac POSIX shared memory - // implementation are fully instrumented. - // TODO(asvitkine): Evaluate whether we want to keep this ability after - // crbug.com/703649 is fixed and expand to all platforms or remove. - SharedMemoryError get_last_error() const { return last_error_; } - private: #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \ (!defined(OS_MACOSX) || defined(OS_IOS)) @@ -263,7 +240,6 @@ void* memory_ = nullptr; bool read_only_ = false; size_t requested_size_ = 0; - SharedMemoryError last_error_ = SharedMemoryError::NO_ERRORS; DISALLOW_COPY_AND_ASSIGN(SharedMemory); };
diff --git a/base/memory/shared_memory_helper.cc b/base/memory/shared_memory_helper.cc index 87c3d36..d210808 100644 --- a/base/memory/shared_memory_helper.cc +++ b/base/memory/shared_memory_helper.cc
@@ -25,8 +25,7 @@ bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, ScopedFILE* fp, ScopedFD* readonly_fd, - FilePath* path, - SharedMemoryError* error) { + FilePath* path) { #if !(defined(OS_MACOSX) && !defined(OS_IOS)) // It doesn't make sense to have a open-existing private piece of shmem DCHECK(!options.open_existing_deprecated); @@ -35,16 +34,13 @@ // A: Because they're limited to 4mb on OS X. FFFFFFFUUUUUUUUUUU FilePath directory; ScopedPathUnlinker path_unlinker; - if (!GetShmemTempDir(options.executable, &directory)) { - *error = SharedMemoryError::NO_TEMP_DIR; + if (!GetShmemTempDir(options.executable, &directory)) return false; - } fp->reset(base::CreateAndOpenTemporaryFileInDir(directory, path)); - if (!*fp) { - *error = SharedMemoryError::NO_FILE; + + if (!*fp) return false; - } // Deleting the file prevents anyone else from mapping it in (making it // private), and prevents the need for cleanup (once the last fd is @@ -57,7 +53,6 @@ if (!readonly_fd->is_valid()) { DPLOG(ERROR) << "open(\"" << path->value() << "\", O_RDONLY) failed"; fp->reset(); - *error = SharedMemoryError::MAKE_READONLY_FAILED; return false; } } @@ -67,14 +62,11 @@ bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd, int* mapped_file, - int* readonly_mapped_file, - SharedMemoryError* error) { + int* readonly_mapped_file) { DCHECK_EQ(-1, *mapped_file); DCHECK_EQ(-1, *readonly_mapped_file); - if (!fp) { - *error = SharedMemoryError::NO_FILE; + if (fp == NULL) return false; - } // This function theoretically can block on the disk, but realistically // the temporary files we create will just go into the buffer cache @@ -91,7 +83,6 @@ NOTREACHED(); if (st.st_dev != readonly_st.st_dev || st.st_ino != readonly_st.st_ino) { LOG(ERROR) << "writable and read-only inodes don't match; bailing"; - *error = SharedMemoryError::INODE_MISMATCH; return false; } }
diff --git a/base/memory/shared_memory_helper.h b/base/memory/shared_memory_helper.h index 5c8b86e..ca681e1 100644 --- a/base/memory/shared_memory_helper.h +++ b/base/memory/shared_memory_helper.h
@@ -16,21 +16,18 @@ // with the fdopened FILE. |readonly_fd| is populated with the opened fd if // options.share_read_only is true. |path| is populated with the location of // the file before it was unlinked. -// Returns false if there's a failure and sets |error|. +// Returns false if there's an unhandled failure. bool CreateAnonymousSharedMemory(const SharedMemoryCreateOptions& options, ScopedFILE* fp, ScopedFD* readonly_fd, - FilePath* path, - SharedMemoryError* error); + FilePath* path); // Takes the outputs of CreateAnonymousSharedMemory and maps them properly to // |mapped_file| or |readonly_mapped_file|, depending on which one is populated. -// Returns false if there's a failure and sets |error|. bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly_fd, int* mapped_file, - int* readonly_mapped_file, - SharedMemoryError* error); + int* readonly_mapped_file); #endif } // namespace base
diff --git a/base/memory/shared_memory_mac.cc b/base/memory/shared_memory_mac.cc index 9719e97..00a32d3 100644 --- a/base/memory/shared_memory_mac.cc +++ b/base/memory/shared_memory_mac.cc
@@ -128,15 +128,11 @@ // "name == L"". The exception is in the StatsTable. bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { DCHECK(!shm_.IsValid()); - if (options.size == 0) { - last_error_ = SharedMemoryError::BAD_PARAMS; + if (options.size == 0) return false; - } - if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) { - last_error_ = SharedMemoryError::BAD_PARAMS; + if (options.size > static_cast<size_t>(std::numeric_limits<int>::max())) return false; - } if (options.type == SharedMemoryHandle::MACH) { shm_ = SharedMemoryHandle(options.size, UnguessableToken::Create()); @@ -153,31 +149,26 @@ ScopedFD readonly_fd; FilePath path; - bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path, - &last_error_); + bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); if (!result) return false; DCHECK(fp); // Should be guaranteed by CreateAnonymousSharedMemory(). // Get current size. struct stat stat; - if (fstat(fileno(fp.get()), &stat) != 0) { - last_error_ = SharedMemoryError::STAT_FAILED; + if (fstat(fileno(fp.get()), &stat) != 0) return false; - } const size_t current_size = stat.st_size; if (current_size != options.size) { - if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) { - last_error_ = SharedMemoryError::TRUNCATE_FAILED; + if (HANDLE_EINTR(ftruncate(fileno(fp.get()), options.size)) != 0) return false; - } } requested_size_ = options.size; int mapped_file = -1; int readonly_mapped_file = -1; result = PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, - &readonly_mapped_file, &last_error_); + &readonly_mapped_file); shm_ = SharedMemoryHandle(FileDescriptor(mapped_file, false), options.size, UnguessableToken::Create()); readonly_shm_ = @@ -187,18 +178,12 @@ } bool SharedMemory::MapAt(off_t offset, size_t bytes) { - if (!shm_.IsValid()) { - last_error_ = SharedMemoryError::BAD_PARAMS; + if (!shm_.IsValid()) return false; - } - if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) { - last_error_ = SharedMemoryError::BAD_PARAMS; + if (bytes > static_cast<size_t>(std::numeric_limits<int>::max())) return false; - } - if (memory_) { - last_error_ = SharedMemoryError::BAD_PARAMS; + if (memory_) return false; - } bool success = shm_.MapAt(offset, bytes, &memory_, read_only_); if (success) { @@ -208,7 +193,6 @@ mapped_memory_mechanism_ = shm_.type_; SharedMemoryTracker::GetInstance()->IncrementMemoryUsage(*this); } else { - last_error_ = SharedMemoryError::MMAP_FAILED; memory_ = NULL; }
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc index b123849f..90b8aa4 100644 --- a/base/memory/shared_memory_posix.cc +++ b/base/memory/shared_memory_posix.cc
@@ -100,8 +100,8 @@ FilePath path; if (options.name_deprecated == NULL || options.name_deprecated->empty()) { - bool result = CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path, - &last_error_); + bool result = + CreateAnonymousSharedMemory(options, &fp, &readonly_fd, &path); if (!result) return false; } else { @@ -192,9 +192,8 @@ int mapped_file = -1; int readonly_mapped_file = -1; - bool result = - PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, - &readonly_mapped_file, &last_error_); + bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd), + &mapped_file, &readonly_mapped_file); shm_ = SharedMemoryHandle(base::FileDescriptor(mapped_file, false), options.size, UnguessableToken::Create()); readonly_shm_ = @@ -234,9 +233,8 @@ } int mapped_file = -1; int readonly_mapped_file = -1; - bool result = - PrepareMapFile(std::move(fp), std::move(readonly_fd), &mapped_file, - &readonly_mapped_file, &last_error_); + bool result = PrepareMapFile(std::move(fp), std::move(readonly_fd), + &mapped_file, &readonly_mapped_file); // This form of sharing shared memory is deprecated. https://crbug.com/345734. // However, we can't get rid of it without a significant refactor because its // used to communicate between two versions of the same service process, very
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc index 2d07818d8..9c2110a 100644 --- a/base/metrics/field_trial.cc +++ b/base/metrics/field_trial.cc
@@ -11,7 +11,6 @@ #include "base/build_time.h" #include "base/command_line.h" #include "base/debug/activity_tracker.h" -#include "base/debug/crash_logging.h" #include "base/logging.h" #include "base/metrics/field_trial_param_associator.h" #include "base/process/memory.h" @@ -1280,25 +1279,11 @@ #endif std::unique_ptr<SharedMemory> shm(new SharedMemory()); - if (!shm->Create(options)) { -#if !defined(OS_NACL) - // Temporary for http://crbug.com/703649. - base::debug::ScopedCrashKey crash_key( - "field_trial_shmem_create_error", - base::IntToString(static_cast<int>(shm->get_last_error()))); -#endif + if (!shm->Create(options)) OnOutOfMemory(kFieldTrialAllocationSize); - } - if (!shm->Map(kFieldTrialAllocationSize)) { -#if !defined(OS_NACL) - // Temporary for http://crbug.com/703649. - base::debug::ScopedCrashKey crash_key( - "field_trial_shmem_map_error", - base::IntToString(static_cast<int>(shm->get_last_error()))); -#endif + if (!shm->Map(kFieldTrialAllocationSize)) OnOutOfMemory(kFieldTrialAllocationSize); - } global_->field_trial_allocator_.reset( new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false));
diff --git a/base/process/process.h b/base/process/process.h index 8979dd4..9902fafd 100644 --- a/base/process/process.h +++ b/base/process/process.h
@@ -139,6 +139,9 @@ // Returns true if the priority was changed, false otherwise. If // |port_provider| is null, this is a no-op and it returns false. bool SetProcessBackgrounded(PortProvider* port_provider, bool value); + + // Returns |true| if helper processes should participate in AppNap. + static bool IsAppNapEnabled(); #else // A process is backgrounded when it's priority is lower than normal. // Return true if this process is backgrounded, false otherwise.
diff --git a/base/process/process_mac.cc b/base/process/process_mac.cc index f83fbb99..bc045cd72a 100644 --- a/base/process/process_mac.cc +++ b/base/process/process_mac.cc
@@ -8,15 +8,27 @@ #include "base/feature_list.h" #include "base/mac/mach_logging.h" +#include "base/metrics/field_trial_params.h" namespace base { +namespace { +const char kAppNapFeatureParamName[] = "app_nap"; +} + // Enables backgrounding hidden renderers on Mac. const Feature kMacAllowBackgroundingProcesses{"MacAllowBackgroundingProcesses", FEATURE_DISABLED_BY_DEFAULT}; +bool Process::IsAppNapEnabled() { + return !base::GetFieldTrialParamValueByFeature( + kMacAllowBackgroundingProcesses, kAppNapFeatureParamName) + .empty(); +} + bool Process::CanBackgroundProcesses() { - return FeatureList::IsEnabled(kMacAllowBackgroundingProcesses); + return FeatureList::IsEnabled(kMacAllowBackgroundingProcesses) && + !IsAppNapEnabled(); } bool Process::IsProcessBackgrounded(PortProvider* port_provider) const {
diff --git a/base/sequenced_task_runner.h b/base/sequenced_task_runner.h index e42ba7f..fa768fb2 100644 --- a/base/sequenced_task_runner.h +++ b/base/sequenced_task_runner.h
@@ -158,8 +158,7 @@ // std::unique_ptr<Foo, base::OnTaskRunnerDeleter> ptr( // new Foo, base::OnTaskRunnerDeleter(my_task_runner)); // -// TODO: RefCounted isn't yet supported per RefCountedTraits using a static -// deleter and thus not be bindable to a specific TaskRunner. +// For RefCounted see base::RefCountedDeleteOnSequence. struct BASE_EXPORT OnTaskRunnerDeleter { explicit OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner); ~OnTaskRunnerDeleter();
diff --git a/base/trace_event/heap_profiler_allocation_context_tracker.cc b/base/trace_event/heap_profiler_allocation_context_tracker.cc index 5d884e5..bd16f2b4 100644 --- a/base/trace_event/heap_profiler_allocation_context_tracker.cc +++ b/base/trace_event/heap_profiler_allocation_context_tracker.cc
@@ -42,7 +42,7 @@ // Cannot call ThreadIdNameManager::GetName because it holds a lock and causes // deadlock when lock is already held by ThreadIdNameManager before the current // allocation. Gets the thread name from kernel if available or returns a string -// with id. This function intenionally leaks the allocated strings since they +// with id. This function intentionally leaks the allocated strings since they // are used to tag allocations even after the thread dies. const char* GetAndLeakThreadName() { char name[16]; @@ -156,7 +156,6 @@ task_contexts_.pop_back(); } -// static bool AllocationContextTracker::GetContextSnapshot(AllocationContext* ctx) { if (ignore_scope_depth_) return false;
diff --git a/base/trace_event/heap_profiler_allocation_register.h b/base/trace_event/heap_profiler_allocation_register.h index d7e8c91..bead7b2 100644 --- a/base/trace_event/heap_profiler_allocation_register.h +++ b/base/trace_event/heap_profiler_allocation_register.h
@@ -379,7 +379,7 @@ // // This is a slightly abstraction to allow for constant propagation. It // knows that the sentinel will be the first item inserted into the table - // and that the first index retuned will be 0. The constructor DCHECKs + // and that the first index returned will be 0. The constructor DCHECKs // this assumption. enum : BacktraceMap::KVIndex { kOutOfStorageBacktraceIndex = 0 };
diff --git a/base/trace_event/malloc_dump_provider.h b/base/trace_event/malloc_dump_provider.h index 08495a7..b2487d0a 100644 --- a/base/trace_event/malloc_dump_provider.h +++ b/base/trace_event/malloc_dump_provider.h
@@ -5,9 +5,6 @@ #ifndef BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ #define BASE_TRACE_EVENT_MALLOC_DUMP_PROVIDER_H_ -#include <istream> -#include <memory> - #include "base/macros.h" #include "base/memory/singleton.h" #include "base/threading/platform_thread.h" @@ -53,7 +50,7 @@ // When in OnMemoryDump(), this contains the current thread ID. // This is to prevent re-entrancy in the heap profiler when the heap dump - // generation is malloc/new-ing for its own bookeeping data structures. + // generation is malloc/new-ing for its own bookkeeping data structures. PlatformThreadId tid_dumping_heap_; DISALLOW_COPY_AND_ASSIGN(MallocDumpProvider);
diff --git a/base/win/com_init_util.cc b/base/win/com_init_util.cc index a90e588..53a6d73d 100644 --- a/base/win/com_init_util.cc +++ b/base/win/com_init_util.cc
@@ -14,12 +14,6 @@ namespace { -enum class ComInitStatus { - NONE, - STA, - MTA, -}; - // Derived from combase.dll. struct OleTlsData { enum ApartmentFlags { @@ -36,27 +30,31 @@ // to work between x86 and x64 builds. }; -ComInitStatus GetComInitStatusForThread() { +ComApartmentType GetComApartmentTypeForThread() { TEB* teb = NtCurrentTeb(); OleTlsData* ole_tls_data = reinterpret_cast<OleTlsData*>(teb->ReservedForOle); if (!ole_tls_data) - return ComInitStatus::NONE; + return ComApartmentType::NONE; if (ole_tls_data->apartment_flags & OleTlsData::ApartmentFlags::STA) - return ComInitStatus::STA; + return ComApartmentType::STA; if ((ole_tls_data->apartment_flags & OleTlsData::ApartmentFlags::MTA) == OleTlsData::ApartmentFlags::MTA) { - return ComInitStatus::MTA; + return ComApartmentType::MTA; } - return ComInitStatus::NONE; + return ComApartmentType::NONE; } } // namespace void AssertComInitialized() { - DCHECK_NE(ComInitStatus::NONE, GetComInitStatusForThread()); + DCHECK_NE(ComApartmentType::NONE, GetComApartmentTypeForThread()); +} + +void AssertComApartmentType(ComApartmentType apartment_type) { + DCHECK_EQ(apartment_type, GetComApartmentTypeForThread()); } #endif // DCHECK_IS_ON()
diff --git a/base/win/com_init_util.h b/base/win/com_init_util.h index 29312893..46794e9 100644 --- a/base/win/com_init_util.h +++ b/base/win/com_init_util.h
@@ -11,11 +11,27 @@ namespace base { namespace win { -// DCHECKs if COM is not initialized on this thread as an STA or MTA. +enum class ComApartmentType { + // Uninitialized or has an unrecognized apartment type. + NONE, + // Single-threaded Apartment. + STA, + // Multi-threaded Apartment. + MTA, +}; + #if DCHECK_IS_ON() + +// DCHECKs if COM is not initialized on this thread as an STA or MTA. BASE_EXPORT void AssertComInitialized(); + +// DCHECKs if |apartment_type| is not the same as the current thread's apartment +// type. +BASE_EXPORT void AssertComApartmentType(ComApartmentType apartment_type); + #else // DCHECK_IS_ON() void AssertComInitialized() {} +void AssertComApartmentType(ComApartmentType apartment_type) {} #endif // DCHECK_IS_ON() } // namespace win
diff --git a/base/win/com_init_util_unittest.cc b/base/win/com_init_util_unittest.cc index 8f6f512..f5387d0 100644 --- a/base/win/com_init_util_unittest.cc +++ b/base/win/com_init_util_unittest.cc
@@ -16,6 +16,8 @@ } TEST(ComInitUtil, AssertUninitialized) { + // When COM is uninitialized, the TLS data will remain, but the apartment + // status will be updated. This covers that case. { ScopedCOMInitializer com_initializer; ASSERT_TRUE(com_initializer.succeeded()); @@ -37,5 +39,37 @@ AssertComInitialized(); } +TEST(ComInitUtil, AssertNoneApartmentType) { + AssertComApartmentType(ComApartmentType::NONE); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA)); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA)); +} + +TEST(ComInitUtil, AssertNoneApartmentTypeUninitialized) { + // When COM is uninitialized, the TLS data will remain, but the apartment + // status will be updated. This covers that case. + { + ScopedCOMInitializer com_initializer; + ASSERT_TRUE(com_initializer.succeeded()); + } + AssertComApartmentType(ComApartmentType::NONE); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA)); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA)); +} + +TEST(ComInitUtil, AssertSTAApartmentType) { + ScopedCOMInitializer com_initializer; + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::NONE)); + AssertComApartmentType(ComApartmentType::STA); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA)); +} + +TEST(ComInitUtil, AssertMTAApartmentType) { + ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::NONE)); + EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA)); + AssertComApartmentType(ComApartmentType::MTA); +} + } // namespace win } // namespace base
diff --git a/build/win/merge_pgc_files.py b/build/win/merge_pgc_files.py index dac547a0b..024bc6b 100755 --- a/build/win/merge_pgc_files.py +++ b/build/win/merge_pgc_files.py
@@ -23,6 +23,26 @@ import vs_toolchain +# Number of PGC files that should be merged in each iteration, merging all +# the files one by one is really slow but merging more than 10 at a time doesn't +# really seem to impact the total time (when merging 180 files). +# +# Number of pgc merged per iteration | Time (in min) +# 1 | 27.2 +# 10 | 12.8 +# 20 | 12.0 +# 30 | 11.5 +# 40 | 11.4 +# 50 | 11.5 +# 60 | 11.6 +# 70 | 11.6 +# 80 | 11.7 +# +# TODO(sebmarchand): Measure the memory usage of pgomgr.exe to see how it get +# affected by the number of pgc files. +_BATCH_SIZE_DEFAULT = 10 + + def find_pgomgr(chrome_checkout_dir): """Find pgomgr.exe.""" win_toolchain_json_file = os.path.join(chrome_checkout_dir, 'build', @@ -49,6 +69,20 @@ return pgomgr_path +def merge_pgc_files(pgomgr_path, files, pgd_path): + """Merge all the pgc_files in |files| to |pgd_path|.""" + merge_command = [ + pgomgr_path, + '/merge' + ] + merge_command.extend(files) + merge_command.append(pgd_path) + proc = subprocess.Popen(merge_command, stdout=subprocess.PIPE) + stdout, _ = proc.communicate() + print stdout + return proc.returncode + + def main(): parser = optparse.OptionParser(usage='%prog [options]') parser.add_option('--checkout-dir', help='The Chrome checkout directory.') @@ -56,6 +90,9 @@ parser.add_option('--build-dir', help='Chrome build directory.') parser.add_option('--binary-name', help='The binary for which the PGC files ' 'should be merged, without extension.') + parser.add_option('--files-per-iter', help='The number of PGC files to merge ' + 'in each iteration, default to %d.' % _BATCH_SIZE_DEFAULT, + type='int', default=_BATCH_SIZE_DEFAULT) options, _ = parser.parse_args() if not options.checkout_dir: @@ -70,25 +107,7 @@ pgc_files = glob.glob(os.path.join(options.build_dir, '%s*.pgc' % options.binary_name)) - - # Number of PGC files that should be merged in each iterations, merging all - # the files one by one is really slow but merging more to 10 at a time doesn't - # really seem to impact the total time. - # - # Number of pgc merged per iteration | Time (in min) - # 1 | 27.2 - # 10 | 12.8 - # 20 | 12.0 - # 30 | 11.5 - # 40 | 11.4 - # 50 | 11.5 - # 60 | 11.6 - # 70 | 11.6 - # 80 | 11.7 - # - # TODO(sebmarchand): Measure the memory usage of pgomgr.exe to see how it get - # affected by the number of pgc files. - pgc_per_iter = 20 + pgd_file = os.path.join(options.build_dir, '%s.pgd' % options.binary_name) def _split_in_chunks(items, chunk_size): """Split |items| in chunks of size |chunk_size|. @@ -97,25 +116,29 @@ """ for i in xrange(0, len(items), chunk_size): yield items[i:i + chunk_size] - - for chunk in _split_in_chunks(pgc_files, pgc_per_iter): - merge_command = [ - pgomgr_path, - '/merge' - ] + for chunk in _split_in_chunks(pgc_files, options.files_per_iter): + files_to_merge = [] for pgc_file in chunk: - merge_command.append([ - os.path.join(options.build_dir, os.path.basename(pgc_file)) - ]) - - merge_command.append([ - os.path.join(options.build_dir, '%s.pgd' % options.binary_name) - ]) - proc = subprocess.Popen(merge_command, stdout=subprocess.PIPE) - stdout, stderr = proc.communicate() - print stdout - if proc.returncode != 0: - raise Exception('Error while trying to merge the PGC files:\n%s' % stderr) + files_to_merge.append( + os.path.join(options.build_dir, os.path.basename(pgc_file))) + ret = merge_pgc_files(pgomgr_path, files_to_merge, pgd_file) + # pgomgr.exe sometimes fails to merge too many files at the same time (it + # usually complains that a stream is missing, but if you try to merge this + # file individually it works), try to merge all the PGCs from this batch one + # at a time instead. Don't fail the build if we can't merge a file. + # TODO(sebmarchand): Report this to Microsoft, check if this is still + # happening with VS2017. + if ret != 0: + print ('Error while trying to merge several PGC files at the same time, ' + 'trying to merge them one by one.' + for pgc_file in chunk: + ret = merge_pgc_files( + pgomgr_path, + [os.path.join(options.build_dir, os.path.basename(pgc_file))], + pgd_file + ) + if ret != 0: + print 'Error while trying to merge %s, continuing.' % pgc_file if __name__ == '__main__':
diff --git a/cc/animation/transform_operations.cc b/cc/animation/transform_operations.cc index 27d14909..f43cddd 100644 --- a/cc/animation/transform_operations.cc +++ b/cc/animation/transform_operations.cc
@@ -303,11 +303,9 @@ return false; gfx::DecomposedTransform to_return; - if (!gfx::BlendDecomposedTransforms(&to_return, - *decomposed_transform_.get(), - *from.decomposed_transform_.get(), - progress)) - return false; + to_return = gfx::BlendDecomposedTransforms(*decomposed_transform_.get(), + *from.decomposed_transform_.get(), + progress); *result = ComposeTransform(to_return); return true;
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn index 8728420f..baa9458a 100644 --- a/cc/paint/BUILD.gn +++ b/cc/paint/BUILD.gn
@@ -29,6 +29,7 @@ "paint_record.h", "paint_recorder.cc", "paint_recorder.h", + "paint_shader.cc", "paint_shader.h", "record_paint_canvas.cc", "record_paint_canvas.h",
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc index 4f1fc48..4d8368b 100644 --- a/cc/paint/discardable_image_map_unittest.cc +++ b/cc/paint/discardable_image_map_unittest.cc
@@ -597,8 +597,9 @@ SkMatrix scale = SkMatrix::MakeScale(std::max(x * 0.5f, kMinScale), std::max(y * 0.5f, kMinScale)); PaintFlags flags; - flags.setShader(discardable_image[y][x]->makeShader( - SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, &scale)); + flags.setShader(PaintShader::MakeImage( + discardable_image[y][x], SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, &scale)); content_layer_client.add_draw_rect( gfx::Rect(x * 512 + 6, y * 512 + 6, 500, 500), flags); }
diff --git a/cc/paint/discardable_image_store.cc b/cc/paint/discardable_image_store.cc index 1545e32a..4f635fd6 100644 --- a/cc/paint/discardable_image_store.cc +++ b/cc/paint/discardable_image_store.cc
@@ -176,7 +176,7 @@ // are not yet handled. void DiscardableImageStore::AddImageFromFlags(const SkRect& rect, const PaintFlags& flags) { - SkShader* shader = flags.getShader(); + SkShader* shader = flags.getSkShader(); if (shader) { SkMatrix matrix; SkShader::TileMode xy[2];
diff --git a/cc/paint/paint_flags.cc b/cc/paint/paint_flags.cc index e16a8bb..03a5fe61 100644 --- a/cc/paint/paint_flags.cc +++ b/cc/paint/paint_flags.cc
@@ -16,7 +16,7 @@ return false; if (getPathEffect()) return false; - if (getShader()) + if (HasShader()) return false; if (getMaskFilter()) return false;
diff --git a/cc/paint/paint_flags.h b/cc/paint/paint_flags.h index c884098..b8e5fb8 100644 --- a/cc/paint/paint_flags.h +++ b/cc/paint/paint_flags.h
@@ -7,6 +7,7 @@ #include "base/compiler_specific.h" #include "cc/paint/paint_export.h" +#include "cc/paint/paint_shader.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkDrawLooper.h" @@ -19,8 +20,6 @@ namespace cc { -using PaintShader = SkShader; - class CC_PAINT_EXPORT PaintFlags { public: enum Style { @@ -160,9 +159,21 @@ ALWAYS_INLINE void setMaskFilter(sk_sp<SkMaskFilter> mask) { paint_.setMaskFilter(std::move(mask)); } - ALWAYS_INLINE PaintShader* getShader() const { return paint_.getShader(); } - ALWAYS_INLINE void setShader(sk_sp<PaintShader> shader) { - paint_.setShader(std::move(shader)); + // TODO(vmpstr): Remove this from recording calls, since we want to avoid + // constructing the shader until rasterization. + ALWAYS_INLINE SkShader* getSkShader() const { return paint_.getShader(); } + + // Returns true if the shader has been set on the flags. + ALWAYS_INLINE bool HasShader() const { return !!paint_.getShader(); } + + // Returns whether the shader is opaque. Note that it is only valid to call + // this function if HasShader() returns true. + ALWAYS_INLINE bool ShaderIsOpaque() const { + return paint_.getShader()->isOpaque(); + } + + ALWAYS_INLINE void setShader(std::unique_ptr<PaintShader> shader) { + paint_.setShader(shader ? shader->sk_shader() : nullptr); } ALWAYS_INLINE SkPathEffect* getPathEffect() const { return paint_.getPathEffect();
diff --git a/cc/paint/paint_op_buffer.h b/cc/paint/paint_op_buffer.h index d48044b..22cc137 100644 --- a/cc/paint/paint_op_buffer.h +++ b/cc/paint/paint_op_buffer.h
@@ -117,7 +117,7 @@ if (!IsDrawOp()) return false; - SkShader* shader = flags.getShader(); + SkShader* shader = flags.getSkShader(); SkImage* image = shader ? shader->isAImage(nullptr, nullptr) : nullptr; return image && image->isLazyGenerated(); }
diff --git a/cc/paint/paint_op_buffer_unittest.cc b/cc/paint/paint_op_buffer_unittest.cc index 9686955..a6bcbb7 100644 --- a/cc/paint/paint_op_buffer_unittest.cc +++ b/cc/paint/paint_op_buffer_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "cc/paint/paint_op_buffer.h" +#include "base/memory/ptr_util.h" #include "cc/paint/display_item_list.h" #include "cc/test/skia_common.h" #include "cc/test/test_skcanvas.h" @@ -447,8 +448,9 @@ PaintOpBuffer buffer; PaintFlags flags; sk_sp<SkImage> image = CreateDiscardableImage(gfx::Size(100, 100)); - flags.setShader( - image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)); + flags.setShader(PaintShader::MakeImage(std::move(image), + SkShader::kClamp_TileMode, + SkShader::kClamp_TileMode, nullptr)); buffer.push<DrawRectOp>(SkRect::MakeWH(100, 100), flags); EXPECT_TRUE(buffer.HasDiscardableImages()); }
diff --git a/cc/paint/paint_shader.cc b/cc/paint/paint_shader.cc new file mode 100644 index 0000000..fb8bb25 --- /dev/null +++ b/cc/paint/paint_shader.cc
@@ -0,0 +1,115 @@ +// 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 "cc/paint/paint_shader.h" + +#include "base/memory/ptr_util.h" +#include "cc/paint/paint_record.h" +#include "third_party/skia/include/effects/SkGradientShader.h" + +namespace cc { + +std::unique_ptr<PaintShader> PaintShader::MakeColor(SkColor color) { + return base::WrapUnique(new PaintShader(nullptr, color)); +} + +std::unique_ptr<PaintShader> PaintShader::MakeLinearGradient( + const SkPoint points[], + const SkColor colors[], + const SkScalar pos[], + int count, + SkShader::TileMode mode, + uint32_t flags, + const SkMatrix* local_matrix, + SkColor fallback_color) { + return base::WrapUnique( + new PaintShader(SkGradientShader::MakeLinear(points, colors, pos, count, + mode, flags, local_matrix), + fallback_color)); +} + +std::unique_ptr<PaintShader> PaintShader::MakeRadialGradient( + const SkPoint& center, + SkScalar radius, + const SkColor colors[], + const SkScalar pos[], + int color_count, + SkShader::TileMode mode, + uint32_t flags, + const SkMatrix* local_matrix, + SkColor fallback_color) { + return base::WrapUnique(new PaintShader( + SkGradientShader::MakeRadial(center, radius, colors, pos, color_count, + mode, flags, local_matrix), + fallback_color)); +} + +std::unique_ptr<PaintShader> PaintShader::MakeTwoPointConicalGradient( + const SkPoint& start, + SkScalar start_radius, + const SkPoint& end, + SkScalar end_radius, + const SkColor colors[], + const SkScalar pos[], + int color_count, + SkShader::TileMode mode, + uint32_t flags, + const SkMatrix* local_matrix, + SkColor fallback_color) { + return base::WrapUnique( + new PaintShader(SkGradientShader::MakeTwoPointConical( + start, start_radius, end, end_radius, colors, pos, + color_count, mode, flags, local_matrix), + fallback_color)); +} + +std::unique_ptr<PaintShader> PaintShader::MakeSweepGradient( + SkScalar cx, + SkScalar cy, + const SkColor colors[], + const SkScalar pos[], + int color_count, + uint32_t flags, + const SkMatrix* local_matrix, + SkColor fallback_color) { + return base::WrapUnique(new PaintShader( + SkGradientShader::MakeSweep(cx, cy, colors, pos, color_count, flags, + local_matrix), + fallback_color)); +} + +std::unique_ptr<PaintShader> PaintShader::MakeImage( + sk_sp<const SkImage> image, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* local_matrix) { + return base::WrapUnique(new PaintShader( + image->makeShader(tx, ty, local_matrix), SK_ColorTRANSPARENT)); +} + +std::unique_ptr<PaintShader> PaintShader::MakePaintRecord( + sk_sp<PaintRecord> record, + const SkRect& tile, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* local_matrix) { + return base::WrapUnique(new PaintShader( + SkShader::MakePictureShader(ToSkPicture(std::move(record), tile), tx, ty, + local_matrix, nullptr), + SK_ColorTRANSPARENT)); +} + +PaintShader::PaintShader(sk_sp<SkShader> shader, SkColor fallback_color) + : sk_shader_(shader ? std::move(shader) + : SkShader::MakeColorShader(fallback_color)) { + DCHECK(sk_shader_); +} +PaintShader::PaintShader(const PaintShader& other) = default; +PaintShader::PaintShader(PaintShader&& other) = default; +PaintShader::~PaintShader() = default; + +PaintShader& PaintShader::operator=(const PaintShader& other) = default; +PaintShader& PaintShader::operator=(PaintShader&& other) = default; + +} // namespace cc
diff --git a/cc/paint/paint_shader.h b/cc/paint/paint_shader.h index 019174443b..6fc1a46 100644 --- a/cc/paint/paint_shader.h +++ b/cc/paint/paint_shader.h
@@ -5,32 +5,92 @@ #ifndef CC_PAINT_PAINT_SHADER_H_ #define CC_PAINT_PAINT_SHADER_H_ -#include "cc/paint/paint_record.h" +#include <memory> + +#include "cc/paint/paint_export.h" #include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkScalar.h" #include "third_party/skia/include/core/SkShader.h" namespace cc { -using PaintShader = SkShader; -inline sk_sp<PaintShader> WrapSkShader(sk_sp<SkShader> shader) { - return shader; -} +class PaintOpBuffer; +using PaintRecord = PaintOpBuffer; -inline sk_sp<PaintShader> MakePaintShaderImage(sk_sp<const SkImage> image, - SkShader::TileMode tx, - SkShader::TileMode ty, - const SkMatrix* local_matrix) { - return image->makeShader(tx, ty, local_matrix); -} +class CC_PAINT_EXPORT PaintShader { + public: + static std::unique_ptr<PaintShader> MakeColor(SkColor color); -inline sk_sp<PaintShader> MakePaintShaderRecord(sk_sp<PaintRecord> record, - const SkRect& tile, + static std::unique_ptr<PaintShader> MakeLinearGradient( + const SkPoint points[], + const SkColor colors[], + const SkScalar pos[], + int count, + SkShader::TileMode mode, + uint32_t flags = 0, + const SkMatrix* local_matrix = nullptr, + SkColor fallback_color = SK_ColorTRANSPARENT); + + static std::unique_ptr<PaintShader> MakeRadialGradient( + const SkPoint& center, + SkScalar radius, + const SkColor colors[], + const SkScalar pos[], + int color_count, + SkShader::TileMode mode, + uint32_t flags = 0, + const SkMatrix* local_matrix = nullptr, + SkColor fallback_color = SK_ColorTRANSPARENT); + + static std::unique_ptr<PaintShader> MakeTwoPointConicalGradient( + const SkPoint& start, + SkScalar start_radius, + const SkPoint& end, + SkScalar end_radius, + const SkColor colors[], + const SkScalar pos[], + int color_count, + SkShader::TileMode mode, + uint32_t flags = 0, + const SkMatrix* local_matrix = nullptr, + SkColor fallback_color = SK_ColorTRANSPARENT); + + static std::unique_ptr<PaintShader> MakeSweepGradient( + SkScalar cx, + SkScalar cy, + const SkColor colors[], + const SkScalar pos[], + int color_count, + uint32_t flags = 0, + const SkMatrix* local_matrix = nullptr, + SkColor fallback_color = SK_ColorTRANSPARENT); + + static std::unique_ptr<PaintShader> MakeImage(sk_sp<const SkImage> image, SkShader::TileMode tx, SkShader::TileMode ty, - const SkMatrix* local_matrix) { - return SkShader::MakePictureShader(ToSkPicture(record, tile), tx, ty, - local_matrix, nullptr); -} + const SkMatrix* local_matrix); + + static std::unique_ptr<PaintShader> MakePaintRecord( + sk_sp<PaintRecord> record, + const SkRect& tile, + SkShader::TileMode tx, + SkShader::TileMode ty, + const SkMatrix* local_matrix); + + PaintShader(const PaintShader& other); + PaintShader(PaintShader&& other); + ~PaintShader(); + + PaintShader& operator=(const PaintShader& other); + PaintShader& operator=(PaintShader&& other); + + const sk_sp<SkShader>& sk_shader() const { return sk_shader_; } + + private: + PaintShader(sk_sp<SkShader> shader, SkColor fallback_color); + + sk_sp<SkShader> sk_shader_; +}; } // namespace cc
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 88e42716..6bee9fc 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -494,6 +494,7 @@ "//net/android:net_java", "//net/android:net_java_test_support", "//printing:printing_java", + "//services:service_javatests", "//third_party/WebKit/public:android_mojo_bindings_java", "//third_party/WebKit/public:blink_headers_java", "//third_party/android_protobuf:protobuf_nano_javalib",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 69980874..566de37 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -122,9 +122,11 @@ } deps += [ "//android_webview:monochrome_webview_assets", + "//android_webview/apk:webview_license_activity_java", "//android_webview/glue", "//chrome/android:chrome_public_non_pak_assets", "//chrome/android:monochrome_pak_assets", + "//chrome/android/monochrome:monochrome_license_provider_java", ] if (!is_java_debug) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java index 100e403..75850a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -95,6 +95,14 @@ "WebApk.Install.GooglePlayInstallResult", result, GOOGLE_PLAY_INSTALL_RESULT_MAX); } + /** Records the error code if installing a WebAPK via Google Play fails. */ + public static void recordGooglePlayInstallErrorCode(int errorCode) { + // Don't use an enumerated histogram as there are > 30 potential error codes. In practice, + // a given client will always get the same error code. + RecordHistogram.recordSparseSlowlyHistogram( + "WebApk.Install.GooglePlayErrorCode", Math.min(errorCode, 1000)); + } + /** * Records whether updating a WebAPK from Google Play succeeded. If not, records the reason * that the update failed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java index cf50fb3..e1c8b93 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java
@@ -55,7 +55,6 @@ /** Whether an offline sub-feature is enabled or not. */ private static Boolean sOfflineBookmarksEnabled; - private static Boolean sBackgroundLoadingEnabled; private static Boolean sIsPageSharingEnabled; /** @@ -528,6 +527,11 @@ return nativeGetOfflinePage(mNativeOfflinePageBridge, webContents); } + /** + * Allows setting the offline bookmarks feature as enabled or disabled for testing. This is + * required for tests that don't load the native binary otherwise UnsatisfiedLinkError sadness + * will occur. + */ @VisibleForTesting static void setOfflineBookmarksEnabledForTesting(boolean enabled) { sOfflineBookmarksEnabled = enabled;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillEditorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillEditorBase.java index 59bee9c..52d540f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillEditorBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/autofill/AutofillEditorBase.java
@@ -84,7 +84,7 @@ getActivity().finish(); return true; } else if (item.getItemId() == R.id.help_menu_id) { - EditorDialog.launchAutofillHelpPage(mContext); + EditorDialog.launchAutofillHelpPage(getActivity()); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java index 7de2c24..c19430a2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java
@@ -4,34 +4,13 @@ package org.chromium.chrome.browser.webapps; -import android.support.annotation.IntDef; - import org.chromium.base.Callback; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * Defines an interface for installing WebAPKs via Google Play. */ public interface GooglePlayWebApkInstallDelegate { /** - * The app state transitions provided by Google Play during download and installation process. - */ - @Retention(RetentionPolicy.SOURCE) - @IntDef({INVALID, DOWNLOAD_PENDING, DOWNLOADING, DOWNLOAD_CANCELLED, DOWNLOAD_ERROR, - INSTALLING, INSTALL_ERROR, INSTALLED}) - public @interface InstallerPackageEvent {} - public static final int INVALID = -1; - public static final int DOWNLOAD_PENDING = 0; - public static final int DOWNLOADING = 1; - public static final int DOWNLOAD_CANCELLED = 2; - public static final int DOWNLOAD_ERROR = 3; - public static final int INSTALLING = 4; - public static final int INSTALL_ERROR = 5; - public static final int INSTALLED = 6; - - /** * Uses Google Play to install WebAPK asynchronously. * @param packageName The package name of WebAPK to install. * @param version The version of WebAPK to install. @@ -54,10 +33,4 @@ */ void updateAsync(String packageName, int version, String title, String token, String url, Callback<Integer> callback); - /** - * Calls the callback once the installation either succeeded or failed. - * @param packageName The package name of WebAPK for the installation. - * @param event The result of the install. - */ - void onGotInstallEvent(String packageName, @InstallerPackageEvent int event); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index c8b2e8d..ecba3522 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -84,10 +84,9 @@ // The default shell Apk version of WebAPKs. static final int DEFAULT_SHELL_APK_VERSION = 1; - // Unset/invalid constants for last used times and URLs. 0 is used as the null last used time as - // WebappRegistry assumes that this is always a valid timestamp. - static final long LAST_USED_UNSET = 0; - static final long LAST_USED_INVALID = -1; + // Invalid constants for timestamps and URLs. '0' is used as the invalid timestamp as + // WebappRegistry and WebApkUpdateManager assume that timestamps are always valid. + static final long TIMESTAMP_INVALID = 0; static final String URL_INVALID = ""; static final int VERSION_INVALID = 0; @@ -139,14 +138,8 @@ * Opens an instance of WebappDataStorage for the web app specified. * @param webappId The ID of the web app. */ - static WebappDataStorage open(final String webappId) { - final WebappDataStorage storage = sFactory.create(webappId); - if (storage.getLastUsedTime() == LAST_USED_INVALID) { - // If the last used time is invalid then ensure that there is no data in the - // WebappDataStorage which needs to be cleaned up. - assert storage.isEmpty(); - } - return storage; + static WebappDataStorage open(String webappId) { + return sFactory.create(webappId); } /** @@ -321,10 +314,7 @@ void clearHistory() { SharedPreferences.Editor editor = mPreferences.edit(); - // The last used time is set to 0 to ensure that a valid value is always present. - // If the web app is not launched prior to the next cleanup, then its remaining data will be - // removed. Otherwise, the next launch from home screen will update the last used time. - editor.putLong(KEY_LAST_USED, LAST_USED_UNSET); + editor.remove(KEY_LAST_USED); editor.remove(KEY_URL); editor.remove(KEY_SCOPE); editor.remove(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME); @@ -364,7 +354,7 @@ * Returns the last used time of this object, or -1 if it is not stored. */ public long getLastUsedTime() { - return mPreferences.getLong(KEY_LAST_USED, LAST_USED_INVALID); + return mPreferences.getLong(KEY_LAST_USED, TIMESTAMP_INVALID); } /** @@ -406,7 +396,7 @@ * updated. This time needs to be set when the WebAPK is registered. */ private long getLastCheckForWebManifestUpdateTime() { - return mPreferences.getLong(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME, LAST_USED_INVALID); + return mPreferences.getLong(KEY_LAST_CHECK_WEB_MANIFEST_UPDATE_TIME, TIMESTAMP_INVALID); } /** @@ -423,7 +413,7 @@ * This time needs to be set when the WebAPK is registered. */ long getLastWebApkUpdateRequestCompletionTime() { - return mPreferences.getLong(KEY_LAST_UPDATE_REQUEST_COMPLETE_TIME, LAST_USED_INVALID); + return mPreferences.getLong(KEY_LAST_UPDATE_REQUEST_COMPLETE_TIME, TIMESTAMP_INVALID); } /** @@ -485,7 +475,7 @@ */ boolean didPreviousUpdateSucceed() { long lastUpdateCompletionTime = getLastWebApkUpdateRequestCompletionTime(); - if (lastUpdateCompletionTime == WebappDataStorage.LAST_USED_INVALID) { + if (lastUpdateCompletionTime == TIMESTAMP_INVALID) { return true; } return getDidLastWebApkUpdateRequestSucceed();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index 1997ce9..2880e3f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -117,8 +117,10 @@ @Override protected final void onPostExecute(WebappDataStorage storage) { - // Guarantee that last used time != WebappDataStorage.LAST_USED_INVALID. Must be - // run on the main thread as SharedPreferences.Editor.apply() is called. + // Update the last used time in order to prevent + // {@link WebappRegistry@unregisterOldWebapps()} from deleting the + // WebappDataStorage. Must be run on the main thread as + // SharedPreferences.Editor.apply() is called. mStorages.put(webappId, storage); mPreferences.edit().putStringSet(KEY_WEBAPP_SET, mStorages.keySet()).apply(); storage.updateLastUsedTime();
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index 13fcb49..c5aa7ed3 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1760,7 +1760,7 @@ "junit/src/org/chromium/chrome/browser/offlinepages/OfflineBackgroundTaskTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeUnitTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageTabObserverTest.java", - "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java", + "junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/ShadowDeviceConditions.java", "junit/src/org/chromium/chrome/browser/offlinepages/TaskExtrasPackerTest.java", "junit/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridgeTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java index a45433d7..c06f1b44 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridgeTest.java
@@ -42,8 +42,7 @@ /** Unit tests for {@link OfflinePageBridge}. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({"enable-features=OfflineBookmarks", - ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) public class OfflinePageBridgeTest { @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java index da04976..bff40f0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageRequestTest.java
@@ -33,8 +33,7 @@ /** Unit tests for offline page request handling. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({"enable-features=OfflineBookmarks", - ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) public class OfflinePageRequestTest { @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java index fa4c93ea..3256c1b9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java
@@ -41,9 +41,9 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.TimeUnit; -/** Unit tests for {@link OfflinePageUtils}. */ +/** Instrumentation tests for {@link OfflinePageUtils}. */ @RunWith(ChromeJUnit4ClassRunner.class) -@CommandLineFlags.Add({"enable-features=OfflineBookmarks", "enable-features=OfflinePagesSharing", +@CommandLineFlags.Add({"enable-features=OfflinePagesSharing", ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) public class OfflinePageUtilsTest {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java index bd270dc..1808c63 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/RecentTabsTest.java
@@ -39,8 +39,7 @@ /** Integration tests for the Last 1 feature of Offline Pages. */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, - ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG, - "enable-features=OfflineRecentPages"}) + ChromeActivityTestRule.DISABLE_NETWORK_PREDICTION_FLAG}) public class RecentTabsTest { @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java similarity index 96% rename from chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java rename to chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java index 96a0747..32e440b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtilsUnitTest.java
@@ -42,8 +42,8 @@ */ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE, application = BaseChromiumApplication.class, - shadows = {OfflinePageUtilsTest.WrappedEnvironment.class, ShadowMultiDex.class}) -public class OfflinePageUtilsTest { + shadows = {OfflinePageUtilsUnitTest.WrappedEnvironment.class, ShadowMultiDex.class}) +public class OfflinePageUtilsUnitTest { @Mock private File mMockDataDirectory; @Mock @@ -78,6 +78,8 @@ .getOfflinePageBridge((Profile) isNull()); OfflinePageUtils.setInstanceForTesting(mOfflinePageUtils); + // Setting the default value is required because unit tests don't load native code needed + // to normally call the respective getter. OfflinePageBridge.setOfflineBookmarksEnabledForTesting(true); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java index 6b36fd8..693f4ebb 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerTest.java
@@ -71,7 +71,7 @@ /** {@link WebappDataStorage#Clock} subclass which enables time to be manually advanced. */ private static class MockClock extends WebappDataStorage.Clock { - // 0 has a special meaning: {@link WebappDataStorage#LAST_USED_UNSET}. + // 0 has a special meaning: {@link WebappDataStorage#TIMESTAMP_INVALID}. private long mTimeMillis = 1; public void advance(long millis) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java index 757e15c..89b2c24 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappDataStorageTest.java
@@ -18,7 +18,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowLooper; @@ -194,11 +193,10 @@ storage.updateLastUsedTime(); assertTrue(storage.wasLaunchedRecently()); - long lastUsedTime = mSharedPreferences.getLong(WebappDataStorage.KEY_LAST_USED, - WebappDataStorage.LAST_USED_INVALID); + long lastUsedTime = mSharedPreferences.getLong( + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); - assertTrue(lastUsedTime != WebappDataStorage.LAST_USED_UNSET); - assertTrue(lastUsedTime != WebappDataStorage.LAST_USED_INVALID); + assertTrue(lastUsedTime != WebappDataStorage.TIMESTAMP_INVALID); // Move the last used time one day in the past. mSharedPreferences.edit()
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java index 1dc4165..f52d40af 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -17,7 +17,6 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; - import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowLooper; @@ -127,8 +126,8 @@ long after = System.currentTimeMillis(); SharedPreferences webAppPrefs = ContextUtils.getApplicationContext().getSharedPreferences( WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "test", Context.MODE_PRIVATE); - long actual = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, - WebappDataStorage.LAST_USED_INVALID); + long actual = webAppPrefs.getLong( + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); assertTrue("Timestamp is out of range", actual <= after); } @@ -247,8 +246,8 @@ Set<String> actual = getRegisteredWebapps(); assertEquals(new HashSet<>(Arrays.asList("oldWebapp")), actual); - long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, - WebappDataStorage.LAST_USED_INVALID); + long actualLastUsed = webAppPrefs.getLong( + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); assertEquals(Long.MIN_VALUE, actualLastUsed); // The last cleanup time was set to 0 in setUp() so check that this hasn't changed. @@ -280,8 +279,8 @@ Set<String> actual = getRegisteredWebapps(); assertEquals(new HashSet<>(Arrays.asList("recentWebapp")), actual); - long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, - WebappDataStorage.LAST_USED_INVALID); + long actualLastUsed = webAppPrefs.getLong( + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); assertEquals(lastUsed, actualLastUsed); long lastCleanup = mSharedPreferences.getLong(WebappRegistry.KEY_LAST_CLEANUP, -1); @@ -311,9 +310,9 @@ Set<String> actual = getRegisteredWebapps(); assertTrue(actual.isEmpty()); - long actualLastUsed = webAppPrefs.getLong(WebappDataStorage.KEY_LAST_USED, - WebappDataStorage.LAST_USED_INVALID); - assertEquals(WebappDataStorage.LAST_USED_INVALID, actualLastUsed); + long actualLastUsed = webAppPrefs.getLong( + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertEquals(WebappDataStorage.TIMESTAMP_INVALID, actualLastUsed); long lastCleanup = mSharedPreferences.getLong(WebappRegistry.KEY_LAST_CLEANUP, -1); assertEquals(currentTime, lastCleanup); @@ -421,11 +420,11 @@ WebappDataStorage.SHARED_PREFS_FILE_PREFIX + "webapp2", Context.MODE_PRIVATE); long webapp1OriginalLastUsed = webapp2Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); long webapp2OriginalLastUsed = webapp2Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); - assertTrue(webapp1OriginalLastUsed != WebappDataStorage.LAST_USED_UNSET); - assertTrue(webapp2OriginalLastUsed != WebappDataStorage.LAST_USED_UNSET); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertTrue(webapp1OriginalLastUsed != WebappDataStorage.TIMESTAMP_INVALID); + assertTrue(webapp2OriginalLastUsed != WebappDataStorage.TIMESTAMP_INVALID); // Clear data for |webapp1Url|. WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl( @@ -437,12 +436,12 @@ assertTrue(actual.contains("webapp2")); // Verify that the last used time for the first web app is - // WebappDataStorage.LAST_USED_UNSET, while for the second one it's unchanged. + // WebappDataStorage.TIMESTAMP_INVALID, while for the second one it's unchanged. long actualLastUsed = webapp1Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); - assertEquals(WebappDataStorage.LAST_USED_UNSET, actualLastUsed); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertEquals(WebappDataStorage.TIMESTAMP_INVALID, actualLastUsed); actualLastUsed = webapp2Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); assertEquals(webapp2OriginalLastUsed, actualLastUsed); // Verify that the URL and scope for the first web app is WebappDataStorage.URL_INVALID, @@ -463,13 +462,13 @@ // Clear data for all urls. WebappRegistry.getInstance().clearWebappHistoryForUrlsImpl(new UrlFilters.AllUrls()); - // Verify that the last used time for both web apps is WebappDataStorage.LAST_USED_UNSET. + // Verify that the last used time for both web apps is WebappDataStorage.TIMESTAMP_INVALID. actualLastUsed = webapp1Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); - assertEquals(WebappDataStorage.LAST_USED_UNSET, actualLastUsed); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertEquals(WebappDataStorage.TIMESTAMP_INVALID, actualLastUsed); actualLastUsed = webapp2Prefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_UNSET); - assertEquals(WebappDataStorage.LAST_USED_UNSET, actualLastUsed); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertEquals(WebappDataStorage.TIMESTAMP_INVALID, actualLastUsed); // Verify that the URL and scope for both web apps is WebappDataStorage.URL_INVALID. actualScope = webapp1Prefs.getString( @@ -500,9 +499,8 @@ // Verify that the last used time is valid. long actualLastUsed = webappPrefs.getLong( - WebappDataStorage.KEY_LAST_USED, WebappDataStorage.LAST_USED_INVALID); - assertTrue(WebappDataStorage.LAST_USED_INVALID != actualLastUsed); - assertTrue(WebappDataStorage.LAST_USED_UNSET != actualLastUsed); + WebappDataStorage.KEY_LAST_USED, WebappDataStorage.TIMESTAMP_INVALID); + assertTrue(WebappDataStorage.TIMESTAMP_INVALID != actualLastUsed); } @Test
diff --git a/chrome/android/monochrome/BUILD.gn b/chrome/android/monochrome/BUILD.gn new file mode 100644 index 0000000..2553c5d --- /dev/null +++ b/chrome/android/monochrome/BUILD.gn
@@ -0,0 +1,16 @@ +# 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. + +import("//build/config/android/rules.gni") + +android_library("monochrome_license_provider_java") { + java_files = + [ "java/src/com/android/webview/chromium/LicenseContentProvider.java" ] + + deps = [ + "//base:base_java", + "//chrome/android:chrome_java", + "//components/about_ui/android:aboutui_java", + ] +}
diff --git a/chrome/android/monochrome/java/DEPS b/chrome/android/monochrome/java/DEPS new file mode 100644 index 0000000..69fc978 --- /dev/null +++ b/chrome/android/monochrome/java/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+components/about_ui/android/java", +]
diff --git a/android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java b/chrome/android/monochrome/java/src/com/android/webview/chromium/LicenseContentProvider.java similarity index 70% copy from android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java copy to chrome/android/monochrome/java/src/com/android/webview/chromium/LicenseContentProvider.java index 0571e7cb..5bc5c683 100644 --- a/android_webview/glue/java/src/com/android/webview/chromium/LicenseContentProvider.java +++ b/chrome/android/monochrome/java/src/com/android/webview/chromium/LicenseContentProvider.java
@@ -14,15 +14,18 @@ import android.os.ParcelFileDescriptor; import android.util.Log; +import org.chromium.base.ThreadUtils; +import org.chromium.base.library_loader.ProcessInitException; +import org.chromium.chrome.browser.init.ChromeBrowserInitializer; +import org.chromium.components.aboutui.CreditUtils; + import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; /** * Content provider for the OSS licenses file. - * This is compiled into the stub WebView and so should not depend on any classes from Chromium. */ @TargetApi(Build.VERSION_CODES.KITKAT) public class LicenseContentProvider @@ -47,15 +50,21 @@ @Override public void writeDataToPipe( ParcelFileDescriptor output, Uri uri, String mimeType, Bundle opts, String filename) { - try (InputStream in = getContext().getAssets().open(filename); - OutputStream out = new FileOutputStream(output.getFileDescriptor());) { - byte[] buf = new byte[8192]; - int size = -1; - while ((size = in.read(buf)) != -1) { - out.write(buf, 0, size); - } + try (OutputStream out = new FileOutputStream(output.getFileDescriptor());) { + ThreadUtils.runOnUiThreadBlocking(new Runnable() { + @Override + public void run() { + try { + ChromeBrowserInitializer.getInstance(getContext()) + .handleSynchronousStartup(); + } catch (ProcessInitException e) { + Log.e(TAG, "Fail to initialize the Chrome Browser.", e); + } + } + }); + out.write(CreditUtils.nativeGetJavaWrapperCredits()); } catch (IOException e) { - Log.e(TAG, "Failed to read the license file", e); + Log.e(TAG, "Failed to write the license file", e); } } @@ -68,8 +77,7 @@ } @Override - public int update(Uri uri, ContentValues values, String where, - String[] whereArgs) { + public int update(Uri uri, ContentValues values, String where, String[] whereArgs) { throw new UnsupportedOperationException(); } @@ -84,8 +92,8 @@ } @Override - public Cursor query(Uri uri, String[] projection, String selection, - String[] selectionArgs, String sortOrder) { + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, + String sortOrder) { throw new UnsupportedOperationException(); } }
diff --git a/chrome/app/chrome_crash_reporter_client_win.cc b/chrome/app/chrome_crash_reporter_client_win.cc index 23ed8d8..6963b31b 100644 --- a/chrome/app/chrome_crash_reporter_client_win.cc +++ b/chrome/app/chrome_crash_reporter_client_win.cc
@@ -182,10 +182,6 @@ {"engine_params", crash_keys::kMediumSize}, {"engine1_params", crash_keys::kMediumSize}, {"engine2_params", crash_keys::kMediumSize}, - - // Temporary for http://crbug.com/703649. - {"field_trial_shmem_create_error", crash_keys::kSmallSize}, - {"field_trial_shmem_map_error", crash_keys::kSmallSize}, }; // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/app/helper-Info.plist b/chrome/app/helper-Info.plist index cd9991a2..5fca138 100644 --- a/chrome/app/helper-Info.plist +++ b/chrome/app/helper-Info.plist
@@ -26,5 +26,7 @@ <string>1</string> <key>NSSupportsAutomaticGraphicsSwitching</key> <true/> + <key>NSSupportsAppNap</key> + <true/> </dict> </plist>
diff --git a/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc b/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc index 12bd237d..ab47895 100644 --- a/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc +++ b/chrome/browser/android/offline_pages/offline_page_utils_unittest.cc
@@ -127,11 +127,6 @@ OfflinePageUtilsTest::~OfflinePageUtilsTest() {} void OfflinePageUtilsTest::SetUp() { - // Enables offline pages feature. - // TODO(jianli): Remove this once the feature is completely enabled. - scoped_feature_list_.InitAndEnableFeature( - offline_pages::kOfflineBookmarksFeature); - // Create a test web contents. web_contents_.reset(content::WebContents::Create( content::WebContents::CreateParams(profile())));
diff --git a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc index 3e4c535..5f66503 100644 --- a/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc +++ b/chrome/browser/android/offline_pages/recent_tab_helper_unittest.cc
@@ -156,7 +156,6 @@ size_t model_removed_count_; std::vector<OfflinePageItem> all_pages_; bool all_pages_needs_updating_; - base::test::ScopedFeatureList scoped_feature_list_; // Mocks the RenderViewHostTestHarness' main thread runner. Needs to be delay // initialized in SetUp() -- can't be a simple member -- since @@ -209,7 +208,6 @@ mocked_main_runner_ = base::MakeUnique<base::ScopedMockTimeMessageLoopTaskRunner>(); - scoped_feature_list_.InitAndEnableFeature(kOffliningRecentPagesFeature); // Sets up the factories for testing. OfflinePageModelFactory::GetInstance()->SetTestingFactoryAndUse( browser_context(), BuildTestOfflinePageModel); @@ -655,7 +653,7 @@ // Download requests should still work. TEST_F(RecentTabHelperTest, LastNFeatureNotEnabled) { base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.Init(); + scoped_feature_list.InitAndDisableFeature(kOffliningRecentPagesFeature); NavigateAndCommit(kTestPageUrl); recent_tab_helper()->DocumentOnLoadCompletedInMainFrame(); FastForwardSnapshotController();
diff --git a/chrome/browser/android/vr_shell/BUILD.gn b/chrome/browser/android/vr_shell/BUILD.gn index 0b7c25f..3296458 100644 --- a/chrome/browser/android/vr_shell/BUILD.gn +++ b/chrome/browser/android/vr_shell/BUILD.gn
@@ -60,6 +60,8 @@ "ui_elements/button.h", "ui_elements/exit_prompt.cc", "ui_elements/exit_prompt.h", + "ui_elements/exit_prompt_backplane.cc", + "ui_elements/exit_prompt_backplane.h", "ui_elements/exit_warning.cc", "ui_elements/exit_warning.h", "ui_elements/loading_indicator.cc",
diff --git a/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.cc b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.cc new file mode 100644 index 0000000..6dcd5a8 --- /dev/null +++ b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.cc
@@ -0,0 +1,25 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.h" + +#include "base/memory/ptr_util.h" + +namespace vr_shell { + +ExitPromptBackplane::ExitPromptBackplane( + const base::Callback<void()>& click_callback) + : click_callback_(click_callback) {} + +ExitPromptBackplane::~ExitPromptBackplane() = default; + +void ExitPromptBackplane::OnButtonUp(const gfx::PointF& position) { + // We always run the callback. That is, if the user clicks the controller + // button on the backplane and releases it on another element in front of the + // backplane, this callback will still be called. Elements are input locked + // on button down and it's probably not worth special-casing the backplane. + click_callback_.Run(); +} + +} // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.h b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.h new file mode 100644 index 0000000..8b9f7cb --- /dev/null +++ b/chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.h
@@ -0,0 +1,30 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_BACKPLANE_H_ +#define CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_BACKPLANE_H_ + +#include "base/callback.h" +#include "chrome/browser/android/vr_shell/ui_elements/ui_element.h" + +namespace vr_shell { + +// An invisible but hittable plane behind the exit prompt, to keep the reticle +// roughly planar with the prompt when its near the prompt. +class ExitPromptBackplane : public UiElement { + public: + explicit ExitPromptBackplane(const base::Callback<void()>& click_callback); + ~ExitPromptBackplane() override; + + void OnButtonUp(const gfx::PointF& position) override; + + private: + base::Callback<void()> click_callback_; + + DISALLOW_COPY_AND_ASSIGN(ExitPromptBackplane); +}; + +} // namespace vr_shell + +#endif // CHROME_BROWSER_ANDROID_VR_SHELL_UI_ELEMENTS_EXIT_PROMPT_BACKPLANE_H_
diff --git a/chrome/browser/android/vr_shell/ui_elements/loading_indicator.cc b/chrome/browser/android/vr_shell/ui_elements/loading_indicator.cc index c186768..7a2add7 100644 --- a/chrome/browser/android/vr_shell/ui_elements/loading_indicator.cc +++ b/chrome/browser/android/vr_shell/ui_elements/loading_indicator.cc
@@ -30,7 +30,6 @@ if (enabled_ == enabled) return; enabled_ = enabled; - ResetVisibilityTimer(); SetVisibility(); }
diff --git a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h index e43db65..c0042fc 100644 --- a/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h +++ b/chrome/browser/android/vr_shell/ui_elements/ui_element_debug_id.h
@@ -26,6 +26,7 @@ kScreenDimmer, kExitWarning, kExitPrompt, + kExitPromptBackplane, }; } // namespace vr_shell
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.cc b/chrome/browser/android/vr_shell/ui_scene_manager.cc index f3f9026b..476ebf8 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/android/vr_shell/ui_elements/audio_capture_indicator.h" #include "chrome/browser/android/vr_shell/ui_elements/button.h" #include "chrome/browser/android/vr_shell/ui_elements/exit_prompt.h" +#include "chrome/browser/android/vr_shell/ui_elements/exit_prompt_backplane.h" #include "chrome/browser/android/vr_shell/ui_elements/exit_warning.h" #include "chrome/browser/android/vr_shell/ui_elements/loading_indicator.h" #include "chrome/browser/android/vr_shell/ui_elements/permanent_security_warning.h" @@ -55,6 +56,7 @@ static constexpr float kExitPromptWidth = 0.672 * kContentDistance; static constexpr float kExitPromptHeight = 0.2 * kContentDistance; static constexpr float kExitPromptVerticalOffset = -0.09 * kContentDistance; +static constexpr float kExitPromptBackplaneSize = 1000.0; static constexpr float kUrlBarDistance = 2.4; static constexpr float kUrlBarWidth = 0.672 * kUrlBarDistance; @@ -105,6 +107,7 @@ CreateUrlBar(); CreateCloseButton(); CreateScreenDimmer(); + CreateExitPrompt(); ConfigureScene(); ConfigureSecurityWarnings(); @@ -229,26 +232,9 @@ element->set_size({kBackplaneSize, kBackplaneSize, 1.0}); element->set_translation({0.0, 0.0, -kTextureOffset}); element->set_parent_id(main_content_->id()); - main_content_backplane_ = element.get(); content_elements_.push_back(element.get()); scene_->AddUiElement(std::move(element)); - element = base::MakeUnique<ExitPrompt>( - 512, - base::Bind(&UiSceneManager::OnExitPromptPrimaryButtonClicked, - base::Unretained(this)), - base::Bind(&UiSceneManager::OnExitPromptSecondaryButtonClicked, - base::Unretained(this))); - element->set_debug_id(kExitPrompt); - element->set_id(AllocateId()); - element->set_fill(vr_shell::Fill::NONE); - element->set_size({kExitPromptWidth, kExitPromptHeight, 1}); - element->set_translation({0.0, kExitPromptVerticalOffset, kTextureOffset}); - element->set_parent_id(main_content_->id()); - element->set_visible(false); - exit_prompt_ = element.get(); - scene_->AddUiElement(std::move(element)); - // Limit reticle distance to a sphere based on content distance. scene_->SetBackgroundDistance(main_content_->translation().z() * -kBackgroundDistanceMultiplier); @@ -332,6 +318,38 @@ scene_->AddUiElement(std::move(element)); } +void UiSceneManager::CreateExitPrompt() { + std::unique_ptr<UiElement> element = base::MakeUnique<ExitPrompt>( + 512, + base::Bind(&UiSceneManager::OnExitPromptPrimaryButtonClicked, + base::Unretained(this)), + base::Bind(&UiSceneManager::OnExitPromptSecondaryButtonClicked, + base::Unretained(this))); + element->set_debug_id(kExitPrompt); + element->set_id(AllocateId()); + element->set_fill(vr_shell::Fill::NONE); + element->set_size({kExitPromptWidth, kExitPromptHeight, 1}); + element->set_translation({0.0, kExitPromptVerticalOffset, kTextureOffset}); + element->set_parent_id(main_content_->id()); + element->set_visible(false); + exit_prompt_ = element.get(); + scene_->AddUiElement(std::move(element)); + + // Place an invisible but hittable plane behind the exit prompt, to keep the + // reticle roughly planar with the content if near content. + element = base::MakeUnique<ExitPromptBackplane>(base::Bind( + &UiSceneManager::OnExitPromptBackplaneClicked, base::Unretained(this))); + element->set_debug_id(kExitPromptBackplane); + element->set_id(AllocateId()); + element->set_fill(vr_shell::Fill::NONE); + element->set_size({kExitPromptBackplaneSize, kExitPromptBackplaneSize, 1.0}); + element->set_translation({0.0, 0.0, -kTextureOffset}); + element->set_parent_id(exit_prompt_->id()); + exit_prompt_backplane_ = element.get(); + content_elements_.push_back(element.get()); + scene_->AddUiElement(std::move(element)); +} + base::WeakPtr<UiSceneManager> UiSceneManager::GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -349,7 +367,6 @@ void UiSceneManager::ConfigureScene() { exit_warning_->SetEnabled(scene_->is_exiting()); - exit_prompt_->SetEnabled(scene_->is_prompting_to_exit()); screen_dimmer_->SetEnabled(scene_->is_exiting()); // Controls (URL bar, loading progress, etc). @@ -363,13 +380,20 @@ close_button_->SetEnabled(!web_vr_mode_ && (fullscreen_ || in_cct_)); // Content elements. - main_content_->SetEnabled(!web_vr_mode_ && !scene_->is_prompting_to_exit()); - main_content_backplane_->SetEnabled(!web_vr_mode_); + for (UiElement* element : content_elements_) { + element->SetEnabled(!web_vr_mode_ && !scene_->is_prompting_to_exit()); + } + // Background elements. for (UiElement* element : background_elements_) { element->SetEnabled(!web_vr_mode_); } + // Exit prompt. + bool showExitPrompt = !web_vr_mode_ && scene_->is_prompting_to_exit(); + exit_prompt_->SetEnabled(showExitPrompt); + exit_prompt_backplane_->SetEnabled(showExitPrompt); + // Update content quad parameters depending on fullscreen. // TODO(http://crbug.com/642937): Animate fullscreen transitions. if (fullscreen_) { @@ -475,6 +499,14 @@ browser_->NavigateBack(); } +void UiSceneManager::OnSecurityIconClickedForTesting() { + OnSecurityIconClicked(); +} + +void UiSceneManager::OnExitPromptPrimaryButtonClickedForTesting() { + OnExitPromptPrimaryButtonClicked(); +} + void UiSceneManager::OnSecurityIconClicked() { if (scene_->is_prompting_to_exit()) return; @@ -482,13 +514,21 @@ ConfigureScene(); } -void UiSceneManager::OnExitPromptPrimaryButtonClicked() { +void UiSceneManager::OnExitPromptBackplaneClicked() { + CloseExitPrompt(); +} + +void UiSceneManager::CloseExitPrompt() { if (!scene_->is_prompting_to_exit()) return; scene_->set_is_prompting_to_exit(false); ConfigureScene(); } +void UiSceneManager::OnExitPromptPrimaryButtonClicked() { + CloseExitPrompt(); +} + void UiSceneManager::OnExitPromptSecondaryButtonClicked() { OnUnsupportedMode(UiUnsupportedMode::kUnhandledPageInfo); }
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager.h b/chrome/browser/android/vr_shell/ui_scene_manager.h index c870835b..94630e3 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager.h +++ b/chrome/browser/android/vr_shell/ui_scene_manager.h
@@ -52,9 +52,10 @@ void OnAppButtonClicked(); void OnAppButtonGesturePerformed(UiInterface::Direction direction); - private: - FRIEND_TEST_ALL_PREFIXES(UiSceneManagerTest, UiUpdatesExitPrompt); + void OnSecurityIconClickedForTesting(); + void OnExitPromptPrimaryButtonClickedForTesting(); + private: void CreateScreenDimmer(); void CreateSecurityWarnings(); void CreateSystemIndicators(); @@ -62,15 +63,18 @@ void CreateBackground(); void CreateUrlBar(); void CreateCloseButton(); + void CreateExitPrompt(); void ConfigureScene(); void ConfigureSecurityWarnings(); void UpdateBackgroundColor(); + void CloseExitPrompt(); void OnSecurityWarningTimer(); void OnBackButtonClicked(); void OnSecurityIconClicked(); void OnExitPromptPrimaryButtonClicked(); void OnExitPromptSecondaryButtonClicked(); + void OnExitPromptBackplaneClicked(); void OnCloseButtonClicked(); void OnUnsupportedMode(UiUnsupportedMode mode); int AllocateId(); @@ -84,9 +88,9 @@ UiElement* permanent_security_warning_ = nullptr; UiElement* transient_security_warning_ = nullptr; UiElement* exit_prompt_ = nullptr; + UiElement* exit_prompt_backplane_ = nullptr; UiElement* exit_warning_ = nullptr; UiElement* main_content_ = nullptr; - UiElement* main_content_backplane_ = nullptr; UiElement* audio_capture_indicator_ = nullptr; UiElement* video_capture_indicator_ = nullptr; UiElement* screen_capture_indicator_ = nullptr;
diff --git a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc index 5744214..a58041d 100644 --- a/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc +++ b/chrome/browser/android/vr_shell/ui_scene_manager_unittest.cc
@@ -34,7 +34,9 @@ }; std::set<UiElementDebugId> kElementsVisibleInBrowsing = { - kContentQuad, kBackplane, kCeiling, kFloor, kUrlBar, kLoadingIndicator}; + kContentQuad, kBackplane, kCeiling, kFloor, kUrlBar}; +std::set<UiElementDebugId> kElementsVisibleWithExitPrompt = { + kExitPrompt, kExitPromptBackplane, kCeiling, kFloor}; } // namespace @@ -64,6 +66,17 @@ return element ? element->visible() : false; } + void VerifyElementsVisible(const std::string& debug_name, + const std::set<UiElementDebugId>& elements) { + SCOPED_TRACE(debug_name); + for (const auto& element : scene_->GetUiElements()) { + SCOPED_TRACE(element->debug_id()); + bool should_be_visible = + elements.find(element->debug_id()) != elements.end(); + EXPECT_EQ(should_be_visible, element->visible()); + } + } + base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<MockBrowserInterface> browser_; std::unique_ptr<UiScene> scene_; @@ -203,43 +216,21 @@ // Hold onto the background color to make sure it changes. SkColor initial_background = scene_->GetWorldBackgroundColor(); + VerifyElementsVisible("Initial", kElementsVisibleInBrowsing); - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = - kElementsVisibleInBrowsing.find(element->debug_id()) != - kElementsVisibleInBrowsing.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } - - // Transistion to fullscreen. + // In fullscreen mode, content elements should be visible, control elements + // should be hidden. manager_->SetFullscreen(true); - - // Content elements should be visible, control elements should be hidden. - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = visible_in_fullscreen.find(element->debug_id()) != - visible_in_fullscreen.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } - + VerifyElementsVisible("In fullscreen", visible_in_fullscreen); { SCOPED_TRACE("Entered Fullsceen"); // Make sure background has changed for fullscreen. EXPECT_NE(initial_background, scene_->GetWorldBackgroundColor()); } - // Exit fullscreen. - manager_->SetFullscreen(false); - // Everything should return to original state after leaving fullscreen. - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = - kElementsVisibleInBrowsing.find(element->debug_id()) != - kElementsVisibleInBrowsing.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } + manager_->SetFullscreen(false); + VerifyElementsVisible("Restore initial", kElementsVisibleInBrowsing); { SCOPED_TRACE("Exited Fullsceen"); EXPECT_EQ(initial_background, scene_->GetWorldBackgroundColor()); @@ -247,39 +238,38 @@ } TEST_F(UiSceneManagerTest, UiUpdatesExitPrompt) { - std::set<UiElementDebugId> visible_when_prompting = {kExitPrompt, kBackplane, - kCeiling, kFloor}; MakeManager(kNotInCct, kNotInWebVr); manager_->SetWebVrSecureOrigin(true); // Initial state. - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = - kElementsVisibleInBrowsing.find(element->debug_id()) != - kElementsVisibleInBrowsing.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } + VerifyElementsVisible("Initial", kElementsVisibleInBrowsing); // Exit prompt visible state. - manager_->OnSecurityIconClicked(); - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = visible_when_prompting.find(element->debug_id()) != - visible_when_prompting.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } + manager_->OnSecurityIconClickedForTesting(); + VerifyElementsVisible("Prompt visible", kElementsVisibleWithExitPrompt); // Back to initial state. - manager_->OnExitPromptPrimaryButtonClicked(); - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - bool should_be_visible = - kElementsVisibleInBrowsing.find(element->debug_id()) != - kElementsVisibleInBrowsing.end(); - EXPECT_EQ(should_be_visible, element->visible()); - } + manager_->OnExitPromptPrimaryButtonClickedForTesting(); + VerifyElementsVisible("Restore initial", kElementsVisibleInBrowsing); +} + +TEST_F(UiSceneManagerTest, BackplaneClickClosesExitPrompt) { + MakeManager(kNotInCct, kNotInWebVr); + + manager_->SetWebVrSecureOrigin(true); + + // Initial state. + VerifyElementsVisible("Initial", kElementsVisibleInBrowsing); + + // Exit prompt visible state. + manager_->OnSecurityIconClickedForTesting(); + VerifyElementsVisible("Prompt visble", kElementsVisibleWithExitPrompt); + + // Back to initial state. + scene_->GetUiElementByDebugId(kExitPromptBackplane) + ->OnButtonUp(gfx::PointF()); + VerifyElementsVisible("Restore initial", kElementsVisibleInBrowsing); } TEST_F(UiSceneManagerTest, UiUpdatesForWebVR) { @@ -291,10 +281,7 @@ manager_->SetScreenCapturingIndicator(true); // All elements should be hidden. - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - EXPECT_FALSE(element->visible()); - } + VerifyElementsVisible("Elements hidden", std::set<UiElementDebugId>{}); } TEST_F(UiSceneManagerTest, UiUpdateTransitionToWebVR) { @@ -308,10 +295,7 @@ manager_->SetWebVrSecureOrigin(true); // All elements should be hidden. - for (const auto& element : scene_->GetUiElements()) { - SCOPED_TRACE(element->debug_id()); - EXPECT_FALSE(element->visible()); - } + VerifyElementsVisible("Elements hidden", std::set<UiElementDebugId>{}); } TEST_F(UiSceneManagerTest, CaptureIndicatorsVisibility) {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 7e3eb5f0..031d14c8 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1262,6 +1262,7 @@ "printing/printer_configurer.h", "printing/printer_discoverer.cc", "printing/printer_discoverer.h", + "printing/printer_info.h", "printing/printers_manager.cc", "printing/printers_manager.h", "printing/printers_manager_factory.cc", @@ -1502,11 +1503,13 @@ sources += [ "printing/cups_print_job_manager_impl.cc", "printing/cups_print_job_manager_impl.h", + "printing/printer_info_cups.cc", ] } else { sources += [ "printing/fake_cups_print_job_manager.cc", "printing/fake_cups_print_job_manager.h", + "printing/printer_info_stub.cc", ] }
diff --git a/chrome/browser/chromeos/printing/printer_info.h b/chrome/browser/chromeos/printing/printer_info.h new file mode 100644 index 0000000..f295ef52 --- /dev/null +++ b/chrome/browser/chromeos/printing/printer_info.h
@@ -0,0 +1,32 @@ +// 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_CHROMEOS_PRINTING_PRINTER_INFO_H_ +#define CHROME_BROWSER_CHROMEOS_PRINTING_PRINTER_INFO_H_ + +#include <string> + +#include "base/callback_forward.h" + +namespace chromeos { + +// Callback for basic printer information. |success| indicates if the request +// succeeded at all. |make| represents the printer manufacturer. |model| is +// the printer model. |autoconf| indicates if we think we can compute the +// printer capabilites without a PPD. +using PrinterInfoCallback = base::Callback<void(bool success, + const std::string& make, + const std::string& model, + bool autoconf)>; + +// Dispatch an IPP request to |host| on |port| for |path| to obtain +// basic printer information. +void QueryIppPrinter(const std::string& host, + const int port, + const std::string& path, + const PrinterInfoCallback& callback); + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_PRINTING_PRINTER_INFO_H_
diff --git a/chrome/browser/chromeos/printing/printer_info_cups.cc b/chrome/browser/chromeos/printing/printer_info_cups.cc new file mode 100644 index 0000000..e11db5adc --- /dev/null +++ b/chrome/browser/chromeos/printing/printer_info_cups.cc
@@ -0,0 +1,140 @@ +// 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/chromeos/printing/printer_info.h" + +#include <algorithm> +#include <array> +#include <string> + +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_piece.h" +#include "base/strings/string_util.h" +#include "base/task_runner_util.h" +#include "base/task_scheduler/post_task.h" +#include "base/task_scheduler/task_traits.h" +#include "base/version.h" +#include "printing/backend/cups_jobs.h" + +namespace { + +const char kPdfMimeType[] = "application/pdf"; +const char kPwgRasterMimeType[] = "image/pwg-raster"; + +// List of known multi-word printer manufacturers to help with make-and-model +// string parsing. Keep in UPPER CASE as that's how matches are performed. +const std::array<const char* const, 4> kMultiWordManufacturers{ + {"FUJI XEROX", "KODAK FUNAI", "KONICA MINOLTA", "TEXAS INSTRUMENTS"}}; + +// Returns the length of the portion of |make_and_model| representing the +// manufacturer. This is either a value from kMultiWordManufacaturers or the +// first token. If there is only one token or less, we assume that it does not +// represent the manufacturer and return 0. +size_t ManufacturerLength(base::StringPiece make_and_model) { + // TODO(crbug.com/729245): Update when better data is available. + for (base::StringPiece multi_word_manufacturer : kMultiWordManufacturers) { + if (base::StartsWith(make_and_model, multi_word_manufacturer, + base::CompareCase::INSENSITIVE_ASCII)) { + return multi_word_manufacturer.size(); + } + } + + // The position of the first space is equal to the length of the first token. + size_t first_space = make_and_model.find(" "); + return first_space != base::StringPiece::npos ? first_space : 0; +} + +// Returns true if any of the |ipp_versions| are greater than or equal to 2.0. +bool AllowedIpp(const std::vector<base::Version>& ipp_versions) { + auto found = + std::find_if(ipp_versions.begin(), ipp_versions.end(), + [](const base::Version& version) { + return version.IsValid() && version.components()[0] >= 2; + }); + + return found != ipp_versions.end(); +} + +// Returns true if |mime_type| is one of the supported types. +bool SupportedMime(const std::string& mime_type) { + return mime_type == kPwgRasterMimeType || mime_type == kPdfMimeType; +} + +// Returns true if |formats| contains one of the supported printer description +// languages for an autoconf printer identified by MIME type. +bool SupportsRequiredPDLS(const std::vector<std::string>& formats) { + auto found = std::find_if(formats.begin(), formats.end(), &SupportedMime); + return found != formats.end(); +} + +// Returns true if |info| describes a printer for which we want to attempt +// automatic configuration. +bool IsAutoconf(const ::printing::PrinterInfo& info) { + return info.ipp_everywhere || (AllowedIpp(info.ipp_versions) && + SupportsRequiredPDLS(info.document_formats)); +} + +// Dispatches an IPP request to |host| to retrieve printer information. Returns +// a nullptr if the request fails. +std::unique_ptr<::printing::PrinterInfo> QueryPrinterImpl( + const std::string& host, + const int port, + const std::string& path) { + auto info = base::MakeUnique<::printing::PrinterInfo>(); + if (!::printing::GetPrinterInfo(host, port, path, info.get())) { + LOG(ERROR) << "Could not retrieve printer info"; + return nullptr; + } + + return info; +} + +// Handles the request for |info|. Parses make and model information before +// calling |callback|. +void OnPrinterQueried(const chromeos::PrinterInfoCallback& callback, + std::unique_ptr<::printing::PrinterInfo> info) { + if (!info) { + VLOG(1) << "Could not reach printer"; + callback.Run(false, std::string(), std::string(), false); + return; + } + + base::StringPiece make_and_model(info->make_and_model); + base::StringPiece make; + base::StringPiece model; + + size_t split = ManufacturerLength(make_and_model); + if (split != 0) { + make = make_and_model.substr(0, split); + model = make_and_model.substr(split + 1); + } else { + // If there's only one word or an empty string, use it. + model = make_and_model; + } + + callback.Run(true, make.as_string(), model.as_string(), IsAutoconf(*info)); +} + +} // namespace + +namespace chromeos { + +void QueryIppPrinter(const std::string& host, + const int port, + const std::string& path, + const PrinterInfoCallback& callback) { + DCHECK(!host.empty()); + + // QueryPrinterImpl could block on a network call for a noticable amount of + // time (100s of ms). Also the user is waiting on this result. Thus, run at + // USER_VISIBLE with MayBlock. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, + base::TaskTraits(base::TaskPriority::USER_VISIBLE, base::MayBlock()), + base::Bind(&QueryPrinterImpl, host, port, path), + base::Bind(&OnPrinterQueried, callback)); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/printer_info_stub.cc b/chrome/browser/chromeos/printing/printer_info_stub.cc new file mode 100644 index 0000000..fd12c1d7 --- /dev/null +++ b/chrome/browser/chromeos/printing/printer_info_stub.cc
@@ -0,0 +1,21 @@ +// 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/chromeos/printing/printer_info.h" + +#include "base/logging.h" +#include "base/task_scheduler/post_task.h" + +namespace chromeos { + +void QueryIppPrinter(const std::string& host, + const int port, + const std::string& path, + const PrinterInfoCallback& callback) { + DCHECK(!host.empty()); + + base::PostTask(FROM_HERE, base::Bind(callback, false, "Foo", "Bar", false)); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/system_logs/touch_log_source_ozone.cc b/chrome/browser/chromeos/system_logs/touch_log_source_ozone.cc index d7897db..f7df5f54 100644 --- a/chrome/browser/chromeos/system_logs/touch_log_source_ozone.cc +++ b/chrome/browser/chromeos/system_logs/touch_log_source_ozone.cc
@@ -51,9 +51,9 @@ const int kMaxDeviceTouchEventLogs = 7; // Clean up intermediate log files dumped during feedback creation. -void CleanupEventLog(std::unique_ptr<std::vector<base::FilePath>> log_paths) { - for (size_t i = 0; i < log_paths->size(); ++i) - base::DeleteFile((*log_paths)[i], false); +void CleanupEventLog(const std::vector<base::FilePath>& log_paths) { + for (const base::FilePath& path : log_paths) + base::DeleteFile(path, false); } // Check for all known log paths and find the ones whose filenames match a @@ -85,7 +85,7 @@ // Pack the collected event logs in a way that is compatible with the log // analysis tools. void PackEventLog(system_logs::SystemLogsResponse* response, - std::unique_ptr<std::vector<base::FilePath>> log_paths) { + const std::vector<base::FilePath>& log_paths) { // Combine logs with a command line call that tars them up and uuencode the // result in one string. This is to be compatible with the X11 behavior. std::vector<std::pair<std::string, base::CommandLine>> commands; @@ -94,9 +94,9 @@ // Make a list that contains touchpad (and mouse) event logs only. const std::string touchpad_log_list = - GetEventLogListOfOnePrefix(*log_paths, kTouchpadGestureLogPrefix, + GetEventLogListOfOnePrefix(log_paths, kTouchpadGestureLogPrefix, kMaxDeviceTouchEventLogs) + - GetEventLogListOfOnePrefix(*log_paths, kTouchpadEvdevLogPrefix, + GetEventLogListOfOnePrefix(log_paths, kTouchpadEvdevLogPrefix, kMaxDeviceTouchEventLogs); command.AppendArg(std::string(kTarCommand) + touchpad_log_list + " 2>/dev/null | " + kUuencodeCommand + @@ -110,7 +110,7 @@ // Make a list that contains touchscreen event logs only. const std::string touchscreen_log_list = GetEventLogListOfOnePrefix( - *log_paths, kTouchscreenLogPrefix, kMaxDeviceTouchEventLogs); + log_paths, kTouchscreenLogPrefix, kMaxDeviceTouchEventLogs); ts_command.AppendArg(std::string(kTarCommand) + touchscreen_log_list + " 2>/dev/null | " + kUuencodeCommand + " -m touchscreen_activity_log.tar"); @@ -125,9 +125,9 @@ } // Cleanup these temporary log files. - base::PostTaskWithTraits( - FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, - base::Bind(CleanupEventLog, base::Passed(&log_paths))); + base::PostTaskWithTraits(FROM_HERE, + {base::MayBlock(), base::TaskPriority::BACKGROUND}, + base::Bind(CleanupEventLog, log_paths)); } // Callback for handing the outcome of GetTouchEventLog(). @@ -136,14 +136,13 @@ void OnEventLogCollected( std::unique_ptr<system_logs::SystemLogsResponse> response, const system_logs::SysLogsSourceCallback& callback, - std::unique_ptr<std::vector<base::FilePath>> log_paths) { + const std::vector<base::FilePath>& log_paths) { DCHECK_CURRENTLY_ON(BrowserThread::UI); // We cannot eliminate these temporaries and inline these closures because the // compiler may call release() before get(). const base::Closure pack_closure = - base::Bind(&PackEventLog, base::Unretained(response.get()), - base::Passed(&log_paths)); + base::Bind(&PackEventLog, base::Unretained(response.get()), log_paths); const base::Closure callback_closure = base::Bind(callback, base::Owned(response.release())); base::PostTaskWithTraitsAndReply( @@ -158,15 +157,15 @@ void OnStatusLogCollected( std::unique_ptr<system_logs::SystemLogsResponse> response, const system_logs::SysLogsSourceCallback& callback, - std::unique_ptr<std::string> log) { + const std::string& log) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - (*response)[kDeviceStatusLogDataKey] = *log; + (*response)[kDeviceStatusLogDataKey] = log; // Collect touch event logs. const base::FilePath kBaseLogPath(kTouchEventLogDir); ui::OzonePlatform::GetInstance()->GetInputController()->GetTouchEventLog( kBaseLogPath, - base::Bind(&OnEventLogCollected, base::Passed(&response), callback)); + base::BindOnce(&OnEventLogCollected, base::Passed(&response), callback)); } // Collect touch HUD debug logs. This needs to be done on the UI thread. @@ -195,7 +194,7 @@ // Collect touch device status logs. ui::OzonePlatform::GetInstance()->GetInputController()->GetTouchDeviceStatus( - base::Bind(&OnStatusLogCollected, base::Passed(&response), callback)); + base::BindOnce(&OnStatusLogCollected, base::Passed(&response), callback)); } } // namespace system_logs
diff --git a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc index 4b87365..220ccf1 100644 --- a/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc +++ b/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -142,22 +142,20 @@ tab_list = std::move(media_lists[2]); picker_ = g_picker_factory->CreatePicker(); } else { + webrtc::DesktopCaptureOptions capture_options = + webrtc::DesktopCaptureOptions::CreateDefault(); + capture_options.set_disable_effects(false); + // Create a screens list. if (show_screens) { #if defined(USE_ASH) screen_list = base::MakeUnique<DesktopMediaListAsh>(DesktopMediaListAsh::SCREENS); -#endif - if (!screen_list) { - webrtc::DesktopCaptureOptions options = - webrtc::DesktopCaptureOptions::CreateDefault(); - options.set_disable_effects(false); - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer( - webrtc::DesktopCapturer::CreateScreenCapturer(options)); - - screen_list = base::MakeUnique<NativeDesktopMediaList>( - std::move(screen_capturer), nullptr); - } +#else // !defined(USE_ASH) + screen_list = base::MakeUnique<NativeDesktopMediaList>( + content::DesktopMediaID::TYPE_SCREEN, + webrtc::DesktopCapturer::CreateScreenCapturer(capture_options)); +#endif // !defined(USE_ASH) } // Create a windows list. @@ -165,17 +163,11 @@ #if defined(USE_ASH) window_list = base::MakeUnique<DesktopMediaListAsh>(DesktopMediaListAsh::WINDOWS); -#endif - if (!window_list) { - webrtc::DesktopCaptureOptions options = - webrtc::DesktopCaptureOptions::CreateDefault(); - options.set_disable_effects(false); - std::unique_ptr<webrtc::DesktopCapturer> window_capturer( - webrtc::DesktopCapturer::CreateWindowCapturer(options)); - - window_list = base::MakeUnique<NativeDesktopMediaList>( - nullptr, std::move(window_capturer)); - } +#else // !defined(USE_ASH) + window_list = base::MakeUnique<NativeDesktopMediaList>( + content::DesktopMediaID::TYPE_WINDOW, + webrtc::DesktopCapturer::CreateWindowCapturer(capture_options)); +#endif // !defined(USE_ASH) } if (show_tabs)
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 7993b3a..689edf09 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/extensions/extension_action_runner.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/extensions/extension_with_management_policy_apitest.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/extensions/test_extension_dir.h" #include "chrome/browser/profiles/profile.h" @@ -47,7 +46,6 @@ #include "extensions/test/result_catcher.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "net/test/embedded_test_server/http_request.h" #include "net/test/test_data_directory.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "net/url_request/test_url_fetcher_factory.h" @@ -87,7 +85,7 @@ private: content::NotificationRegistrar registrar_; - DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog); + DISALLOW_COPY_AND_ASSIGN(CancelLoginDialog); }; // Sends an XHR request to the provided host, port, and path, and responds when @@ -956,198 +954,4 @@ } } -// Tests that the webRequest events aren't dispatched when the request initiator -// is protected by policy. -IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, - InitiatorProtectedByPolicy) { - // We expect that no request will be hidden or modification blocked. This - // means that the request to example.com will be seen by the extension. - { - ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://notexample.com"); - } - - ASSERT_TRUE(StartEmbeddedTestServer()); - - // Host navigated to. - const std::string example_com = "example.com"; - - // URL of a page that initiates a cross domain requests when navigated to. - const GURL extension_test_url = embedded_test_server()->GetURL( - example_com, - "/extensions/api_test/webrequest/policy_blocked/ref_remote_js.html"); - - LoadExtension(test_data_dir_.AppendASCII("webrequest/policy_blocked")); - - // Extension communicates back using this listener name. - const std::string listener_message = "protected_origin"; - - // Listen to verify extension sees the web request. - ExtensionTestMessageListener before_request_listener(listener_message, false); - - // Wait until all remote Javascript files have been blocked / pulled down. - ui_test_utils::NavigateToURLWithDisposition( - browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // Domain that hosts javascript file referenced by example_com. - const std::string example2_com = "example2.com"; - - // The server saw a request for the remote Javascript file. - EXPECT_TRUE(BrowsedTo(example2_com)); - - // The request was seen by the extension. - EXPECT_TRUE(before_request_listener.was_satisfied()); - - // Clear the list of domains the server has seen. - ClearRequestLog(); - - // Make sure we've cleared the embedded server history. - EXPECT_FALSE(BrowsedTo(example2_com)); - - // Set the policy to hide requests to example.com or any resource - // it includes. We expect that in this test, the request to example2.com - // will not be seen by the extension. - { - ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + example_com); - } - - // Listen in case extension sees the requst. - ExtensionTestMessageListener before_request_listener2(listener_message, - false); - - // Wait until all remote Javascript files have been pulled down. - ui_test_utils::NavigateToURLWithDisposition( - browser(), extension_test_url, WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // The server saw a request for the remote Javascript file. - EXPECT_TRUE(BrowsedTo(example2_com)); - - // The request was hidden from the extension. - EXPECT_FALSE(before_request_listener2.was_satisfied()); -} - -// Tests that the webRequest events aren't dispatched when the URL of the -// request is protected by policy. -IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, - UrlProtectedByPolicy) { - // Host protected by policy. - const std::string protected_domain = "example.com"; - - { - ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); - } - - ASSERT_TRUE(StartEmbeddedTestServer()); - - LoadExtension(test_data_dir_.AppendASCII("webrequest/policy_blocked")); - - // Listen in case extension sees the requst. - ExtensionTestMessageListener before_request_listener("protected_url", false); - - // Path to resolve during test navigations. - const std::string test_path = "/defaultresponse?protected_url"; - - // Navigate to the protected domain and wait until page fully loads. - ui_test_utils::NavigateToURLWithDisposition( - browser(), embedded_test_server()->GetURL(protected_domain, test_path), - WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // The server saw a request for the protected site. - EXPECT_TRUE(BrowsedTo(protected_domain)); - - // The request was hidden from the extension. - EXPECT_FALSE(before_request_listener.was_satisfied()); - - // Host not protected by policy. - const std::string unprotected_domain = "notblockedexample.com"; - - // Now we'll test browsing to a non-protected website where we expect the - // extension to see the request. - ui_test_utils::NavigateToURLWithDisposition( - browser(), embedded_test_server()->GetURL(unprotected_domain, test_path), - WindowOpenDisposition::CURRENT_TAB, - ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); - - // The server saw a request for the non-protected site. - EXPECT_TRUE(BrowsedTo(unprotected_domain)); - - // The request was visible from the extension. - EXPECT_TRUE(before_request_listener.was_satisfied()); -} - -// Test that no webRequest events are seen for a protected host during normal -// navigation. This replicates most of the tests from -// WebRequestWithWithheldPermissions with a protected host. Granting a tab -// specific permission shouldn't bypass our policy. -IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, - WebRequestProtectedByPolicy) { - FeatureSwitch::ScopedOverride enable_scripts_require_action( - FeatureSwitch::scripts_require_action(), true); - - // Host protected by policy. - const std::string protected_domain = "example.com"; - - { - ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); - } - - ASSERT_TRUE(StartEmbeddedTestServer()); - - ExtensionTestMessageListener listener("ready", false); - const Extension* extension = - LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab")); - ASSERT_TRUE(extension) << message_; - EXPECT_TRUE(listener.WaitUntilSatisfied()); - - // Navigate the browser to a page in a new tab. - GURL url = embedded_test_server()->GetURL(protected_domain, "/empty.html"); - chrome::NavigateParams params(browser(), url, ui::PAGE_TRANSITION_LINK); - params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB; - ui_test_utils::NavigateToURL(¶ms); - - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - ASSERT_TRUE(web_contents); - ExtensionActionRunner* runner = - ExtensionActionRunner::GetForWebContents(web_contents); - ASSERT_TRUE(runner); - - int port = embedded_test_server()->port(); - const std::string kXhrPath = "simple.html"; - - // The extension shouldn't have currently received any webRequest events, - // since it doesn't have permission (and shouldn't receive any from an XHR). - EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); - PerformXhrInFrame(web_contents->GetMainFrame(), protected_domain, port, - kXhrPath); - EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); - - // Grant activeTab permission, and perform another XHR. The extension should - // still be blocked due to ExtensionSettings policy on example.com. - // Only records ACCESS_WITHHELD, not ACCESS_DENIED, this is why it matches - // BLOCKED_ACTION_NONE. - EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension)); - runner->set_default_bubble_close_action_for_testing( - base::WrapUnique(new ToolbarActionsBarBubbleDelegate::CloseAction( - ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE))); - runner->RunAction(extension, true); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(content::WaitForLoadStop(web_contents)); - EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension)); - int xhr_count = GetWebRequestCountFromBackgroundPage(extension, profile()); - // ... which means that we should have a non-zero xhr count if the policy - // didn't block the events. - EXPECT_EQ(0, xhr_count); - // And the extension should also block future events. - PerformXhrInFrame(web_contents->GetMainFrame(), protected_domain, port, - kXhrPath); - EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); -} - } // namespace extensions
diff --git a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc index 0303a49..ed19ffd 100644 --- a/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc
@@ -181,35 +181,32 @@ context.CreateRequest(GURL("http://example.com"), net::DEFAULT_PRIORITY, NULL, TRAFFIC_ANNOTATION_FOR_TESTS)); - EXPECT_EQ( - PermissionsData::ACCESS_ALLOWED, - WebRequestPermissions::CanExtensionAccessURL( - extension_info_map_.get(), permissionless_extension_->id(), - request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::DO_NOT_CHECK_HOST, request->initiator())); + EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + WebRequestPermissions::CanExtensionAccessURL( + extension_info_map_.get(), permissionless_extension_->id(), + request->url(), + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::DO_NOT_CHECK_HOST)); EXPECT_EQ(PermissionsData::ACCESS_DENIED, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), permissionless_extension_->id(), request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_HOST_PERMISSION)); EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_HOST_PERMISSION)); EXPECT_EQ(PermissionsData::ACCESS_DENIED, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_ALL_URLS, request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_ALL_URLS)); // Public Sessions tests. #if defined(OS_CHROMEOS) @@ -221,10 +218,9 @@ WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), org_request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - org_request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_HOST_PERMISSION)); chromeos::ScopedTestPublicSessionLoginState login_state; @@ -234,19 +230,17 @@ WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), org_request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - org_request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_HOST_PERMISSION)); - EXPECT_EQ( - PermissionsData::ACCESS_ALLOWED, - WebRequestPermissions::CanExtensionAccessURL( - extension_info_map_.get(), com_policy_extension_->id(), - org_request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_ALL_URLS, org_request->initiator())); + EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + WebRequestPermissions::CanExtensionAccessURL( + extension_info_map_.get(), com_policy_extension_->id(), + org_request->url(), + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_ALL_URLS)); // Make sure that chrome:// URLs cannot be accessed. std::unique_ptr<net::URLRequest> chrome_request( @@ -257,9 +251,8 @@ WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), chrome_request->url(), - -1, // No tab id. - false, // crosses_incognito - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - chrome_request->initiator())); + -1, // No tab id. + false, // crosses_incognito + WebRequestPermissions::REQUIRE_HOST_PERMISSION)); #endif }
diff --git a/chrome/browser/extensions/extension_with_management_policy_apitest.cc b/chrome/browser/extensions/extension_with_management_policy_apitest.cc index 3b77f73d..3cce777 100644 --- a/chrome/browser/extensions/extension_with_management_policy_apitest.cc +++ b/chrome/browser/extensions/extension_with_management_policy_apitest.cc
@@ -14,9 +14,6 @@ void ExtensionApiTestWithManagementPolicy::SetUpInProcessBrowserTestFixture() { ExtensionApiTest::SetUpInProcessBrowserTestFixture(); - embedded_test_server()->RegisterRequestMonitor( - base::Bind(&ExtensionApiTestWithManagementPolicy::MonitorRequestHandler, - base::Unretained(this))); EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_)) .WillRepeatedly(testing::Return(true)); policy_provider_.SetAutoRefresh(); @@ -28,26 +25,3 @@ ExtensionApiTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); } - -void ExtensionApiTestWithManagementPolicy::MonitorRequestHandler( - const net::test_server::HttpRequest& request) { - auto host = request.headers.find("Host"); - if (host != request.headers.end()) { - ManagementPolicyRequestLog log; - size_t delimiter_pos = host->second.find(":"); - log.host = host->second.substr(0, delimiter_pos); - request_log_.push_back(log); - } -} - -bool ExtensionApiTestWithManagementPolicy::BrowsedTo( - const std::string& test_host) { - return std::find_if(request_log_.begin(), request_log_.end(), - [test_host](const ManagementPolicyRequestLog& log) { - return log.host == test_host; - }) != request_log_.end(); -} - -void ExtensionApiTestWithManagementPolicy::ClearRequestLog() { - request_log_.clear(); -}
diff --git a/chrome/browser/extensions/extension_with_management_policy_apitest.h b/chrome/browser/extensions/extension_with_management_policy_apitest.h index e57aff4..ef11374d 100644 --- a/chrome/browser/extensions/extension_with_management_policy_apitest.h +++ b/chrome/browser/extensions/extension_with_management_policy_apitest.h
@@ -9,14 +9,8 @@ #include <vector> #include "chrome/browser/extensions/extension_apitest.h" -#include "chrome/browser/extensions/extension_management_test_util.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" -struct ManagementPolicyRequestLog { - std::string all_headers; - std::string host; -}; - // The ExtensionSettings policy affects host permissions which impacts several // API integration tests. This class enables easy declaration of // ExtensionSettings policies and functions commonly used during these tests. @@ -29,12 +23,6 @@ protected: policy::MockConfigurationPolicyProvider policy_provider_; - bool BrowsedTo(const std::string& test_host); - void ClearRequestLog(); - void MonitorRequestHandler(const net::test_server::HttpRequest& request); - - private: - std::vector<ManagementPolicyRequestLog> request_log_; DISALLOW_COPY_AND_ASSIGN(ExtensionApiTestWithManagementPolicy); };
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc index bcf2eac..7206873 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.cc +++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
@@ -83,8 +83,8 @@ : public webrtc::DesktopCapturer::Callback { public: Worker(base::WeakPtr<NativeDesktopMediaList> media_list, - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer, - std::unique_ptr<webrtc::DesktopCapturer> window_capturer); + DesktopMediaID::Type type, + std::unique_ptr<webrtc::DesktopCapturer> capturer); ~Worker() override; void Refresh(const DesktopMediaID::Id& view_dialog_id); @@ -101,8 +101,8 @@ base::WeakPtr<NativeDesktopMediaList> media_list_; - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer_; - std::unique_ptr<webrtc::DesktopCapturer> window_capturer_; + DesktopMediaID::Type type_; + std::unique_ptr<webrtc::DesktopCapturer> capturer_; std::unique_ptr<webrtc::DesktopFrame> current_frame_; @@ -113,64 +113,57 @@ NativeDesktopMediaList::Worker::Worker( base::WeakPtr<NativeDesktopMediaList> media_list, - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer, - std::unique_ptr<webrtc::DesktopCapturer> window_capturer) - : media_list_(media_list), - screen_capturer_(std::move(screen_capturer)), - window_capturer_(std::move(window_capturer)) { - if (screen_capturer_) - screen_capturer_->Start(this); - if (window_capturer_) - window_capturer_->Start(this); + DesktopMediaID::Type type, + std::unique_ptr<webrtc::DesktopCapturer> capturer) + : media_list_(media_list), type_(type), capturer_(std::move(capturer)) { + capturer_->Start(this); } NativeDesktopMediaList::Worker::~Worker() {} void NativeDesktopMediaList::Worker::Refresh( const DesktopMediaID::Id& view_dialog_id) { - std::vector<SourceDescription> sources; + std::vector<SourceDescription> result; - if (screen_capturer_) { - webrtc::DesktopCapturer::SourceList screens; - if (screen_capturer_->GetSourceList(&screens)) { - bool mutiple_screens = screens.size() > 1; - base::string16 title; - for (size_t i = 0; i < screens.size(); ++i) { - if (mutiple_screens) { - // Just in case 'Screen' is inflected depending on the screen number, - // use plural formatter. - title = l10n_util::GetPluralStringFUTF16( - IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME, - static_cast<int>(i + 1)); - } else { - title = l10n_util::GetStringUTF16( - IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME); - } - sources.push_back(SourceDescription(DesktopMediaID( - DesktopMediaID::TYPE_SCREEN, screens[i].id), title)); - } - } + webrtc::DesktopCapturer::SourceList sources; + if (!capturer_->GetSourceList(&sources)) { + // Will pass empty results list to RefreshForAuraWindows(). + sources.clear(); } - if (window_capturer_) { - webrtc::DesktopCapturer::SourceList windows; - if (window_capturer_->GetSourceList(&windows)) { - for (auto it = windows.begin(); it != windows.end(); ++it) { - // Skip the picker dialog window. - if (it->id == view_dialog_id) - continue; + bool mutiple_sources = sources.size() > 1; + base::string16 title; + for (size_t i = 0; i < sources.size(); ++i) { + switch (type_) { + case DesktopMediaID::TYPE_SCREEN: + // Just in case 'Screen' is inflected depending on the screen number, + // use plural formatter. + title = mutiple_sources + ? l10n_util::GetPluralStringFUTF16( + IDS_DESKTOP_MEDIA_PICKER_MULTIPLE_SCREEN_NAME, + static_cast<int>(i + 1)) + : l10n_util::GetStringUTF16( + IDS_DESKTOP_MEDIA_PICKER_SINGLE_SCREEN_NAME); + break; - DesktopMediaID media_id(DesktopMediaID::TYPE_WINDOW, it->id); - sources.push_back( - SourceDescription(media_id, base::UTF8ToUTF16(it->title))); - } + case DesktopMediaID::TYPE_WINDOW: + // Skip the picker dialog window. + if (sources[i].id == view_dialog_id) + continue; + title = base::UTF8ToUTF16(sources[i].title); + break; + + default: + NOTREACHED(); } + result.push_back( + SourceDescription(DesktopMediaID(type_, sources[i].id), title)); } BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&NativeDesktopMediaList::RefreshForAuraWindows, - media_list_, sources)); + media_list_, result)); } void NativeDesktopMediaList::Worker::RefreshThumbnails( @@ -180,22 +173,9 @@ // Get a thumbnail for each native source. for (const auto& id : native_ids) { - switch (id.type) { - case DesktopMediaID::TYPE_SCREEN: - if (!screen_capturer_->SelectSource(id.id)) - continue; - screen_capturer_->CaptureFrame(); - break; - - case DesktopMediaID::TYPE_WINDOW: - if (!window_capturer_->SelectSource(id.id)) - continue; - window_capturer_->CaptureFrame(); - break; - - default: - NOTREACHED(); - } + if (!capturer_->SelectSource(id.id)) + continue; + capturer_->CaptureFrame(); // Expect that DesktopCapturer to always captures frames synchronously. // |current_frame_| may be NULL if capture failed (e.g. because window has @@ -232,17 +212,16 @@ } NativeDesktopMediaList::NativeDesktopMediaList( - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer, - std::unique_ptr<webrtc::DesktopCapturer> window_capturer) + DesktopMediaID::Type type, + std::unique_ptr<webrtc::DesktopCapturer> capturer) : DesktopMediaListBase( base::TimeDelta::FromMilliseconds(kDefaultUpdatePeriod)), weak_factory_(this) { capture_task_runner_ = base::CreateSequencedTaskRunnerWithTraits( {base::MayBlock(), base::TaskPriority::USER_VISIBLE}); - worker_.reset(new Worker(weak_factory_.GetWeakPtr(), - std::move(screen_capturer), - std::move(window_capturer))); + worker_.reset( + new Worker(weak_factory_.GetWeakPtr(), type, std::move(capturer))); } NativeDesktopMediaList::~NativeDesktopMediaList() {
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.h b/chrome/browser/media/webrtc/native_desktop_media_list.h index dabab11d..08ebbb78 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list.h +++ b/chrome/browser/media/webrtc/native_desktop_media_list.h
@@ -21,12 +21,8 @@ // native windows. class NativeDesktopMediaList : public DesktopMediaListBase { public: - // Caller may pass NULL for either of the arguments in case when only some - // types of sources the model should be populated with (e.g. it will only - // contain windows, if |screen_capturer| is NULL). - NativeDesktopMediaList( - std::unique_ptr<webrtc::DesktopCapturer> screen_capturer, - std::unique_ptr<webrtc::DesktopCapturer> window_capturer); + NativeDesktopMediaList(content::DesktopMediaID::Type type, + std::unique_ptr<webrtc::DesktopCapturer> capturer); ~NativeDesktopMediaList() override; private:
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc index 42467a5a..8cd3fae 100644 --- a/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc +++ b/chrome/browser/media/webrtc/native_desktop_media_list_unittest.cc
@@ -177,24 +177,6 @@ ViewsTestBase::TearDown(); } - void CreateWithCapturers(bool screen, bool window) { - webrtc::DesktopCapturer* screen_capturer = nullptr; - if (screen) - screen_capturer = new FakeScreenCapturer(); - - if (window) - window_capturer_ = new FakeWindowCapturer(); - else - window_capturer_ = nullptr; - - model_.reset(new NativeDesktopMediaList( - std::unique_ptr<webrtc::DesktopCapturer>(screen_capturer), - std::unique_ptr<webrtc::DesktopCapturer>(window_capturer_))); - - // Set update period to reduce the time it takes to run tests. - model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(20)); - } - void AddNativeWindow(int id) { webrtc::DesktopCapturer::Source window; window.id = id; @@ -265,27 +247,19 @@ #endif // defined(USE_AURA) - void AddWindowsAndVerify(bool screen, - size_t window_count, - size_t aura_count, - bool has_view_dialog) { - // Create model_. - CreateWithCapturers(screen, window_count > 0); + void AddWindowsAndVerify(bool has_view_dialog) { + window_capturer_ = new FakeWindowCapturer(); + model_ = base::MakeUnique<NativeDesktopMediaList>( + DesktopMediaID::TYPE_WINDOW, base::WrapUnique(window_capturer_)); -#if !defined(USE_AURA) - aura_count = 0; -#endif - if (aura_count >= window_count) - aura_count = window_count - 1; - - if (window_count == 0) - has_view_dialog = false; + // Set update period to reduce the time it takes to run tests. + model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(20)); // Set up widows. - size_t aura_window_first_index = window_count - aura_count; - for (size_t i = 0; i < window_count; ++i) { + size_t aura_window_first_index = kDefaultWindowCount - kDefaultAuraCount; + for (size_t i = 0; i < kDefaultWindowCount; ++i) { if (i < aura_window_first_index) { - AddNativeWindow(i + 1); + AddNativeWindow(i); } else { #if defined(USE_AURA) AddAuraWindow(); @@ -296,6 +270,8 @@ if (window_capturer_) window_capturer_->SetWindowList(window_list_); + size_t window_count = kDefaultWindowCount; + // Set view dialog window ID as the first window id. if (has_view_dialog) { DesktopMediaID dialog_window_id(DesktopMediaID::TYPE_WINDOW, @@ -309,39 +285,30 @@ { testing::InSequence dummy; - size_t source_count = screen ? window_count + 1 : window_count; - for (size_t i = 0; i < source_count; ++i) { + for (size_t i = 0; i < window_count; ++i) { EXPECT_CALL(observer_, OnSourceAdded(model_.get(), i)) .WillOnce(CheckListSize(model_.get(), static_cast<int>(i + 1))); } - for (size_t i = 0; i < source_count - 1; ++i) { + for (size_t i = 0; i < window_count - 1; ++i) { EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), i)); } EXPECT_CALL(observer_, - OnSourceThumbnailChanged(model_.get(), source_count - 1)) + OnSourceThumbnailChanged(model_.get(), window_count - 1)) .WillOnce( QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop)); } model_->StartUpdating(&observer_); run_loop.Run(); - if (screen) { - EXPECT_EQ(model_->GetSource(0).id.type, DesktopMediaID::TYPE_SCREEN); - EXPECT_EQ(model_->GetSource(0).id.id, 0); - } - for (size_t i = 0; i < window_count; ++i) { - size_t source_index = screen ? i + 1 : i; - EXPECT_EQ(model_->GetSource(source_index).id.type, - DesktopMediaID::TYPE_WINDOW); - EXPECT_EQ(model_->GetSource(source_index).name, - base::UTF8ToUTF16("Test window")); + EXPECT_EQ(model_->GetSource(i).id.type, DesktopMediaID::TYPE_WINDOW); + EXPECT_EQ(model_->GetSource(i).name, base::UTF8ToUTF16("Test window")); int index = has_view_dialog ? i + 1 : i; int native_id = window_list_[index].id; - EXPECT_EQ(model_->GetSource(source_index).id.id, native_id); + EXPECT_EQ(model_->GetSource(i).id.id, native_id); #if defined(USE_AURA) if (i >= aura_window_first_index) - EXPECT_EQ(model_->GetSource(source_index).id.aura_id, + EXPECT_EQ(model_->GetSource(i).id.aura_id, native_aura_id_map_[native_id]); #endif } @@ -365,29 +332,48 @@ DISALLOW_COPY_AND_ASSIGN(NativeDesktopMediaListTest); }; -TEST_F(NativeDesktopMediaListTest, WindowsOnly) { - AddWindowsAndVerify(false, kDefaultWindowCount, kDefaultAuraCount, false); +TEST_F(NativeDesktopMediaListTest, Windows) { + AddWindowsAndVerify(false); } TEST_F(NativeDesktopMediaListTest, ScreenOnly) { - AddWindowsAndVerify(true, 0, 0, false); + model_ = base::MakeUnique<NativeDesktopMediaList>( + DesktopMediaID::TYPE_SCREEN, base::MakeUnique<FakeScreenCapturer>()); + + // Set update period to reduce the time it takes to run tests. + model_->SetUpdatePeriod(base::TimeDelta::FromMilliseconds(20)); + + base::RunLoop run_loop; + + { + testing::InSequence dummy; + EXPECT_CALL(observer_, OnSourceAdded(model_.get(), 0)) + .WillOnce(CheckListSize(model_.get(), 1)); + EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), 0)) + .WillOnce(QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop)); + } + model_->StartUpdating(&observer_); + run_loop.Run(); + + EXPECT_EQ(model_->GetSource(0).id.type, DesktopMediaID::TYPE_SCREEN); + EXPECT_EQ(model_->GetSource(0).id.id, 0); } // Verifies that the window specified with SetViewDialogWindowId() is filtered // from the results. -TEST_F(NativeDesktopMediaListTest, Filtering) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, true); +TEST_F(NativeDesktopMediaListTest, WindowFiltering) { + AddWindowsAndVerify(true); } TEST_F(NativeDesktopMediaListTest, AddNativeWindow) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - const int index = kDefaultWindowCount + 1; + const int index = kDefaultWindowCount; EXPECT_CALL(observer_, OnSourceAdded(model_.get(), index)) .WillOnce( - DoAll(CheckListSize(model_.get(), index + 1), + DoAll(CheckListSize(model_.get(), kDefaultWindowCount + 1), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); AddNativeWindow(index); @@ -401,14 +387,14 @@ #if defined(ENABLE_AURA_WINDOW_TESTS) TEST_F(NativeDesktopMediaListTest, AddAuraWindow) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - const int index = kDefaultWindowCount + 1; + const int index = kDefaultWindowCount; EXPECT_CALL(observer_, OnSourceAdded(model_.get(), index)) .WillOnce( - DoAll(CheckListSize(model_.get(), index + 1), + DoAll(CheckListSize(model_.get(), kDefaultWindowCount + 1), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); AddAuraWindow(); @@ -425,13 +411,13 @@ #endif // defined(ENABLE_AURA_WINDOW_TESTS) TEST_F(NativeDesktopMediaListTest, RemoveNativeWindow) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 1)) + EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 0)) .WillOnce( - DoAll(CheckListSize(model_.get(), kDefaultWindowCount), + DoAll(CheckListSize(model_.get(), kDefaultWindowCount - 1), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); window_list_.erase(window_list_.begin()); @@ -442,14 +428,14 @@ #if defined(ENABLE_AURA_WINDOW_TESTS) TEST_F(NativeDesktopMediaListTest, RemoveAuraWindow) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - int aura_window_start_index = kDefaultWindowCount - kDefaultAuraCount + 1; + int aura_window_start_index = kDefaultWindowCount - kDefaultAuraCount; EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), aura_window_start_index)) .WillOnce( - DoAll(CheckListSize(model_.get(), kDefaultWindowCount), + DoAll(CheckListSize(model_.get(), kDefaultWindowCount - 1), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); RemoveAuraWindow(0); @@ -460,18 +446,18 @@ #endif // defined(ENABLE_AURA_WINDOW_TESTS) TEST_F(NativeDesktopMediaListTest, RemoveAllWindows) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; testing::InSequence seq; for (int i = 0; i < kDefaultWindowCount - 1; i++) { - EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 1)) - .WillOnce(CheckListSize(model_.get(), kDefaultWindowCount - i)); + EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 0)) + .WillOnce(CheckListSize(model_.get(), kDefaultWindowCount - i - 1)); } - EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 1)) + EXPECT_CALL(observer_, OnSourceRemoved(model_.get(), 0)) .WillOnce( - DoAll(CheckListSize(model_.get(), 1), + DoAll(CheckListSize(model_.get(), 0), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); window_list_.clear(); @@ -481,11 +467,11 @@ } TEST_F(NativeDesktopMediaListTest, UpdateTitle) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - EXPECT_CALL(observer_, OnSourceNameChanged(model_.get(), 1)) + EXPECT_CALL(observer_, OnSourceNameChanged(model_.get(), 0)) .WillOnce(QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop)); const std::string kTestTitle = "New Title"; @@ -494,38 +480,38 @@ run_loop.Run(); - EXPECT_EQ(model_->GetSource(1).name, base::UTF8ToUTF16(kTestTitle)); + EXPECT_EQ(model_->GetSource(0).name, base::UTF8ToUTF16(kTestTitle)); } TEST_F(NativeDesktopMediaListTest, UpdateThumbnail) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); // Aura windows' thumbnails may unpredictably change over time. for (size_t i = kDefaultWindowCount - kDefaultAuraCount; i < kDefaultWindowCount; ++i) { - EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), i + 1)) + EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), i)) .Times(testing::AnyNumber()); } base::RunLoop run_loop; - EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), 1)) + EXPECT_CALL(observer_, OnSourceThumbnailChanged(model_.get(), 0)) .WillOnce(QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop)); // Update frame for the window and verify that we get notification about it. - window_capturer_->SetNextFrameValue(1, 10); + window_capturer_->SetNextFrameValue(0, 10); run_loop.Run(); } TEST_F(NativeDesktopMediaListTest, MoveWindow) { - AddWindowsAndVerify(true, kDefaultWindowCount, kDefaultAuraCount, false); + AddWindowsAndVerify(false); base::RunLoop run_loop; - EXPECT_CALL(observer_, OnSourceMoved(model_.get(), 2, 1)) + EXPECT_CALL(observer_, OnSourceMoved(model_.get(), 1, 0)) .WillOnce( - DoAll(CheckListSize(model_.get(), kDefaultWindowCount + 1), + DoAll(CheckListSize(model_.get(), kDefaultWindowCount), QuitRunLoop(base::ThreadTaskRunnerHandle::Get(), &run_loop))); std::swap(window_list_[0], window_list_[1]);
diff --git a/chrome/browser/net/nss_context.h b/chrome/browser/net/nss_context.h index ca62c4a..3c6f2b5 100644 --- a/chrome/browser/net/nss_context.h +++ b/chrome/browser/net/nss_context.h
@@ -22,20 +22,6 @@ class ResourceContext; } // namespace content -// Returns a reference to the public slot for the user associated with -// |context|. Should be called only on the IO thread. -crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext( - content::ResourceContext* context); - -// Returns a reference to the private slot for the user associated with -// |context|, if it is loaded. If it is not loaded and |callback| is non-null, -// the |callback| will be run once the slot is loaded. -// Should be called only on the IO thread. -crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext( - content::ResourceContext* context, - const base::Callback<void(crypto::ScopedPK11Slot)>& callback) - WARN_UNUSED_RESULT; - // Returns a pointer to the NSSCertDatabase for the user associated with // |context|, if it is ready. If it is not ready and |callback| is non-null, the // |callback| will be run once the DB is initialized. Ownership is not
diff --git a/chrome/browser/net/nss_context_chromeos.cc b/chrome/browser/net/nss_context_chromeos.cc index 7162668..888a3be 100644 --- a/chrome/browser/net/nss_context_chromeos.cc +++ b/chrome/browser/net/nss_context_chromeos.cc
@@ -118,19 +118,6 @@ } // namespace -crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext( - content::ResourceContext* context) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return crypto::GetPublicSlotForChromeOSUser(GetUsername(context)); -} - -crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext( - content::ResourceContext* context, - const base::Callback<void(crypto::ScopedPK11Slot)>& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return crypto::GetPrivateSlotForChromeOSUser(GetUsername(context), callback); -} - net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext( content::ResourceContext* context, const base::Callback<void(net::NSSCertDatabase*)>& callback) {
diff --git a/chrome/browser/net/nss_context_linux.cc b/chrome/browser/net/nss_context_linux.cc index 8e61715..c649bbd 100644 --- a/chrome/browser/net/nss_context_linux.cc +++ b/chrome/browser/net/nss_context_linux.cc
@@ -12,19 +12,6 @@ net::NSSCertDatabase* g_nss_cert_database = NULL; } // namespace -crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext( - content::ResourceContext* context) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return crypto::ScopedPK11Slot(crypto::GetPersistentNSSKeySlot()); -} - -crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext( - content::ResourceContext* context, - const base::Callback<void(crypto::ScopedPK11Slot)>& callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return crypto::ScopedPK11Slot(crypto::GetPersistentNSSKeySlot()); -} - net::NSSCertDatabase* GetNSSCertDatabaseForResourceContext( content::ResourceContext* context, const base::Callback<void(net::NSSCertDatabase*)>& callback) {
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.js index e4201a7..ccb3d65d 100644 --- a/chrome/browser/resources/print_preview/data/destination_store.js +++ b/chrome/browser/resources/print_preview/data/destination_store.js
@@ -20,95 +20,82 @@ /** * Used to fetch local print destinations. - * @type {!print_preview.NativeLayer} - * @private + * @private {!print_preview.NativeLayer} */ this.nativeLayer_ = nativeLayer; /** * User information repository. - * @type {!print_preview.UserInfo} - * @private + * @private {!print_preview.UserInfo} */ this.userInfo_ = userInfo; /** * Used to load and persist the selected destination. - * @type {!print_preview.AppState} - * @private + * @private {!print_preview.AppState} */ this.appState_ = appState; /** * Used to track metrics. - * @type {!print_preview.DestinationSearchMetricsContext} - * @private + * @private {!print_preview.DestinationSearchMetricsContext} */ this.metrics_ = new print_preview.DestinationSearchMetricsContext(); /** * Internal backing store for the data store. - * @type {!Array<!print_preview.Destination>} - * @private + * @private {!Array<!print_preview.Destination>} */ this.destinations_ = []; /** * Cache used for constant lookup of destinations by origin and id. - * @type {Object<!print_preview.Destination>} - * @private + * @private {Object<!print_preview.Destination>} */ this.destinationMap_ = {}; /** * Currently selected destination. - * @type {print_preview.Destination} - * @private + * @private {print_preview.Destination} */ this.selectedDestination_ = null; /** * Whether the destination store will auto select the destination that * matches this set of parameters. - * @type {print_preview.DestinationMatch} - * @private + * @private {print_preview.DestinationMatch} */ this.autoSelectMatchingDestination_ = null; /** * Event tracker used to track event listeners of the destination store. - * @type {!EventTracker} - * @private + * @private {!EventTracker} */ this.tracker_ = new EventTracker(); /** * Whether PDF printer is enabled. It's disabled, for example, in App Kiosk * mode. - * @type {boolean} - * @private + * @private {boolean} */ this.pdfPrinterEnabled_ = false; /** * ID of the system default destination. - * @type {?string} - * @private + * @private {?string} */ this.systemDefaultDestinationId_ = null; /** * Used to fetch cloud-based print destinations. - * @type {cloudprint.CloudPrintInterface} - * @private + * @private {cloudprint.CloudPrintInterface} */ this.cloudPrintInterface_ = null; /** * Maps user account to the list of origins for which destinations are * already loaded. - * @type {!Object<Array<print_preview.DestinationOrigin>>} - * @private + * @private {!Object<Array<!print_preview.DestinationOrigin>>} */ this.loadedCloudOrigins_ = {}; @@ -117,84 +104,66 @@ * destination matches the initial destination ID after the specified * timeout, the first destination in the store will be automatically * selected. - * @type {?number} - * @private + * @private {?number} */ this.autoSelectTimeout_ = null; /** * Whether a search for local destinations is in progress. - * @type {boolean} - * @private + * @private {boolean} */ this.isLocalDestinationSearchInProgress_ = false; /** * Whether the destination store has already loaded or is loading all local * destinations. - * @type {boolean} - * @private + * @private {boolean} */ this.hasLoadedAllLocalDestinations_ = false; /** * Whether a search for privet destinations is in progress. - * @type {boolean} - * @private + * @private {boolean} */ this.isPrivetDestinationSearchInProgress_ = false; /** * Whether the destination store has already loaded or is loading all privet * destinations. - * @type {boolean} - * @private + * @private {boolean} */ this.hasLoadedAllPrivetDestinations_ = false; /** - * ID of a timeout after the start of a privet search to end that privet - * search. - * @type {?number} - * @private - */ - this.privetSearchTimeout_ = null; - - /** * Whether a search for extension destinations is in progress. - * @type {boolean} - * @private + * @private {boolean} */ this.isExtensionDestinationSearchInProgress_ = false; /** * Whether the destination store has already loaded all extension * destinations. - * @type {boolean} - * @private + * @private {boolean} */ this.hasLoadedAllExtensionDestinations_ = false; /** * ID of a timeout set at the start of an extension destination search. The * timeout ends the search. - * @type {?number} - * @private + * @private {?number} */ this.extensionSearchTimeout_ = null; /** * MDNS service name of destination that we are waiting to register. - * @type {?string} - * @private + * @private {?string} */ this.waitForRegisterDestination_ = null; /** * Local destinations are CROS destinations on ChromeOS because they require * extra setup. - * @type {!print_preview.DestinationOrigin} - * @private + * @private {!print_preview.DestinationOrigin} */ this.platformOrigin_ = cr.isChromeOS ? print_preview.DestinationOrigin.CROS : @@ -235,13 +204,6 @@ DestinationStore.AUTO_SELECT_TIMEOUT_ = 15000; /** - * Amount of time spent searching for privet destination, in milliseconds. - * @private {number} - * @const - */ - DestinationStore.PRIVET_SEARCH_DURATION_ = 5000; - - /** * Maximum amount of time spent searching for extension destinations, in * milliseconds. * @private {number} @@ -595,6 +557,8 @@ this.pdfPrinterEnabled_ = !isInAppKioskMode; this.systemDefaultDestinationId_ = systemDefaultDestinationId; this.createLocalPdfPrintDestination_(); + cr.addWebUIListener('privet-printer-added', + this.onPrivetPrinterAdded_.bind(this)); cr.addWebUIListener('extension-printers-added', this.onExtensionPrintersAdded_.bind(this)); @@ -725,7 +689,8 @@ if (origin == print_preview.DestinationOrigin.PRIVET) { // TODO(noamsml): Resolve a specific printer instead of listing all // privet printers in this case. - this.nativeLayer_.startGetPrivetDestinations(); + this.nativeLayer_.getPrivetPrinters().then( + this.endPrivetPrinterSearch_.bind(this)); // Create a fake selectedDestination_ that is not actually in the // destination store. When the real destination is created, this @@ -1090,17 +1055,18 @@ /** Initiates loading of privet print destinations. */ startLoadPrivetDestinations: function() { - if (!this.hasLoadedAllPrivetDestinations_) { - if (this.privetDestinationSearchInProgress_) - clearTimeout(this.privetSearchTimeout_); - this.isPrivetDestinationSearchInProgress_ = true; - this.nativeLayer_.startGetPrivetDestinations(); - cr.dispatchSimpleEvent( - this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED); - this.privetSearchTimeout_ = setTimeout( - this.endPrivetPrinterSearch_.bind(this), - DestinationStore.PRIVET_SEARCH_DURATION_); - } + if (this.hasLoadedAllPrivetDestinations_) + return; + this.isPrivetDestinationSearchInProgress_ = true; + this.nativeLayer_.getPrivetPrinters().then( + this.endPrivetPrinterSearch_.bind(this), + function() { + // Rejected by C++, indicating privet printing is disabled. + this.hasLoadedAllPrivetDestinations_ = true; + this.isPrivetDestinationSearchInProgress_ = false; + }.bind(this)); + cr.dispatchSimpleEvent( + this, DestinationStore.EventType.DESTINATION_SEARCH_STARTED); }, /** Initializes loading of extension managed print destinations. */ @@ -1163,7 +1129,8 @@ * Wait for a privet device to be registered. */ waitForRegister: function(id) { - this.nativeLayer_.startGetPrivetDestinations(); + this.nativeLayer_.getPrivetPrinters().then( + this.endPrivetPrinterSearch_.bind(this)); this.waitForRegisterDestination_ = id; }, @@ -1302,7 +1269,6 @@ * @private */ endPrivetPrinterSearch_: function() { - this.nativeLayer_.stopGetPrivetDestinations(); this.isPrivetDestinationSearchInProgress_ = false; this.hasLoadedAllPrivetDestinations_ = true; cr.dispatchSimpleEvent( @@ -1378,10 +1344,6 @@ this.onDestinationsReload_.bind(this)); this.tracker_.add( nativeLayerEventTarget, - print_preview.NativeLayer.EventType.PRIVET_PRINTER_CHANGED, - this.onPrivetPrinterAdded_.bind(this)); - this.tracker_.add( - nativeLayerEventTarget, print_preview.NativeLayer.EventType.PRIVET_CAPABILITIES_SET, this.onPrivetCapabilitiesSet_.bind(this)); this.tracker_.add( @@ -1588,22 +1550,21 @@ /** * Called when a Privet printer is added to the local network. - * @param {{printer: {serviceName: string, - * name: string, - * hasLocalPrinting: boolean, - * isUnregistered: boolean, - * cloudID: string}}} event Contains information about - * the added printer. + * @param {!{serviceName: string, + * name: string, + * hasLocalPrinting: boolean, + * isUnregistered: boolean, + * cloudID: string}} printer Information about the added printer. * @private */ - onPrivetPrinterAdded_: function(event) { - if (event.printer.serviceName == this.waitForRegisterDestination_ && - !event.printer.isUnregistered) { + onPrivetPrinterAdded_: function(printer) { + if (printer.serviceName == this.waitForRegisterDestination_ && + !printer.isUnregistered) { this.waitForRegisterDestination_ = null; this.onDestinationsReload_(); } else { this.insertDestinations_( - print_preview.PrivetDestinationParser.parse(event.printer)); + print_preview.PrivetDestinationParser.parse(printer)); } },
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js index 6897affa..f259e5e 100644 --- a/chrome/browser/resources/print_preview/native_layer.js +++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -69,7 +69,6 @@ global.onDidPreviewPage = this.onDidPreviewPage_.bind(this); global.updatePrintPreview = this.onUpdatePrintPreview_.bind(this); global.onDidGetAccessToken = this.onDidGetAccessToken_.bind(this); - global.onPrivetPrinterChanged = this.onPrivetPrinterChanged_.bind(this); global.onPrivetCapabilitiesSet = this.onPrivetCapabilitiesSet_.bind(this); global.onPrivetPrintFailed = this.onPrivetPrintFailed_.bind(this); @@ -232,20 +231,13 @@ }, /** - * Requests the network's privet print destinations. A number of - * PRIVET_PRINTER_CHANGED events will be fired in response, followed by a - * PRIVET_SEARCH_ENDED. + * Requests the network's privet print destinations. After this is called, + * a number of privet-printer-changed events may be fired. + * @return {!Promise} Resolves when privet printer search is completed. + * Rejected if privet printers are not enabled. */ - startGetPrivetDestinations: function() { - chrome.send('getPrivetPrinters'); - }, - - /** - * Requests that the privet print stack stop searching for privet print - * destinations. - */ - stopGetPrivetDestinations: function() { - chrome.send('stopGetPrivetPrinters'); + getPrivetPrinters: function() { + return cr.sendWithPromise('getPrivetPrinters'); }, /** @@ -782,18 +774,6 @@ }, /** - * @param {{serviceName: string, name: string}} printer Specifies - * information about the printer that was added. - * @private - */ - onPrivetPrinterChanged_: function(printer) { - var privetPrinterChangedEvent = - new Event(NativeLayer.EventType.PRIVET_PRINTER_CHANGED); - privetPrinterChangedEvent.printer = printer; - this.eventTarget_.dispatchEvent(privetPrinterChangedEvent); - }, - - /** * @param {Object} printer Specifies information about the printer that was * added. * @private
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 9dff41e..11a6a60 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -486,6 +486,7 @@ "//chrome/common:instant_mojom", "//chrome/common/net", "//chrome/installer/util:with_no_strings", + "//components/about_ui", "//components/app_modal", "//components/autofill/content/browser:risk_proto", "//components/autofill/core/browser",
diff --git a/chrome/browser/ui/browser_dialogs.h b/chrome/browser/ui/browser_dialogs.h index 6445c77..2ab0399 100644 --- a/chrome/browser/ui/browser_dialogs.h +++ b/chrome/browser/ui/browser_dialogs.h
@@ -37,10 +37,6 @@ class Extension; } -namespace gfx { -class Point; -} - namespace net { class AuthChallengeInfo; class URLRequest; @@ -124,23 +120,6 @@ #if defined(OS_MACOSX) -// Shows a views zoom bubble at the |anchor_point|. This occurs when the zoom -// icon is clicked or when a shortcut key is pressed or whenever |web_contents| -// zoom factor changes. |user_action| is used to determine if the bubble will -// auto-close. -void ShowZoomBubbleViewsAtPoint(content::WebContents* web_contents, - const gfx::Point& anchor_point, - bool user_action); - -// Closes a views zoom bubble if currently shown. -void CloseZoomBubbleViews(); - -// Refreshes views zoom bubble if currently shown. -void RefreshZoomBubbleViews(); - -// Returns true if views zoom bubble is currently shown. -bool IsZoomBubbleViewsShown(); - // Bridging methods that show/hide the toolkit-views based Task Manager on Mac. task_manager::TaskManagerTableModel* ShowTaskManagerViews(Browser* browser); void HideTaskManagerViews();
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h index 7293b4b..474e0fe 100644 --- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h +++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h
@@ -7,7 +7,7 @@ #include "base/mac/scoped_block.h" #include "base/mac/scoped_nsobject.h" -#import "chrome/browser/ui/cocoa/base_bubble_controller.h" +#import "chrome/browser/ui/cocoa/omnibox_decoration_bubble_controller.h" #import "ui/base/cocoa/tracking_area.h" namespace content { @@ -30,7 +30,7 @@ // The ZoomBubbleController is used to display the current page zoom percent // when not at the user's default. It is opened by the ZoomDecoration in the // location bar. -@interface ZoomBubbleController : BaseBubbleController { +@interface ZoomBubbleController : OmniboxDecorationBubbleController { @private ZoomBubbleControllerDelegate* delegate_;
diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm index 0f9c199..24624dd3 100644 --- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm +++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm
@@ -8,8 +8,11 @@ #include "base/mac/foundation_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/sys_string_conversions.h" +#import "chrome/browser/ui/cocoa/browser_window_controller.h" #import "chrome/browser/ui/cocoa/info_bubble_view.h" #import "chrome/browser/ui/cocoa/info_bubble_window.h" +#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" +#import "chrome/browser/ui/cocoa/location_bar/zoom_decoration.h" #include "chrome/grit/generated_resources.h" #include "components/zoom/page_zoom.h" #include "components/zoom/zoom_controller.h" @@ -175,6 +178,15 @@ [self close]; } +// OmniboxDecorationBubbleController implementation. +- (LocationBarDecoration*)decorationForBubble { + BrowserWindowController* controller = [BrowserWindowController + browserWindowControllerForWindow:[self parentWindow]]; + LocationBarViewMac* locationBar = [controller locationBarBridge]; + return locationBar ? locationBar->zoom_decoration() : nullptr; +} + +// NSWindowController implementation. - (void)windowWillClose:(NSNotification*)notification { // |delegate_| may be set null by this object's owner. if (delegate_) {
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc index f04072b..1494ed4 100644 --- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc +++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.cc
@@ -72,13 +72,14 @@ void ShowZoomBubbleViewsAtPoint(content::WebContents* web_contents, const gfx::Point& anchor_point, - bool user_action) { + bool user_action, + LocationBarDecoration* decoration) { ZoomBubbleView::ShowBubble(web_contents, anchor_point, user_action ? LocationBarBubbleDelegateView::USER_GESTURE : LocationBarBubbleDelegateView::AUTOMATIC); if (ZoomBubbleView::GetZoomBubble()) - KeepBubbleAnchored(ZoomBubbleView::GetZoomBubble()); + KeepBubbleAnchored(ZoomBubbleView::GetZoomBubble(), decoration); } void CloseZoomBubbleViews() {
diff --git a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h index bdc1fb5..15f5cfe 100644 --- a/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h +++ b/chrome/browser/ui/cocoa/browser_dialogs_views_mac.h
@@ -51,6 +51,24 @@ bool newly_bookmarked, LocationBarDecoration* decoration); +// Shows a views zoom bubble at the |anchor_point|. This occurs when the zoom +// icon is clicked or when a shortcut key is pressed or whenever |web_contents| +// zoom factor changes. |user_action| is used to determine if the bubble will +// auto-close. +void ShowZoomBubbleViewsAtPoint(content::WebContents* web_contents, + const gfx::Point& anchor_point, + bool user_action, + LocationBarDecoration* decoration); + +// Closes a views zoom bubble if currently shown. +void CloseZoomBubbleViews(); + +// Refreshes views zoom bubble if currently shown. +void RefreshZoomBubbleViews(); + +// Returns true if views zoom bubble is currently shown. +bool IsZoomBubbleViewsShown(); + // This is a class so that it can be friended from ContentSettingBubbleContents, // which allows it to call SetAnchorRect(). class ContentSettingBubbleViewsBridge {
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h index 77599e10..fdcbcec 100644 --- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h +++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -193,6 +193,8 @@ return translate_decoration_.get(); } + ZoomDecoration* zoom_decoration() const { return zoom_decoration_.get(); } + Browser* browser() const { return browser_; } // ZoomManagerObserver:
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm index 807dc21..9d615ab 100644 --- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm +++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.mm
@@ -9,7 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/cocoa/browser_dialogs_views_mac.h" #import "chrome/browser/ui/cocoa/browser_window_controller.h" #import "chrome/browser/ui/cocoa/l10n_util.h" #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h" @@ -95,8 +95,8 @@ NSPoint anchor = [browser_window_controller bookmarkBubblePoint]; gfx::Point anchor_point = gfx::ScreenPointFromNSPoint( ui::ConvertPointFromWindowToScreen(window, anchor)); - chrome::ShowZoomBubbleViewsAtPoint(web_contents, anchor_point, - auto_close == NO /* user_action */); + chrome::ShowZoomBubbleViewsAtPoint( + web_contents, anchor_point, auto_close == NO /* user_action */, this); return; }
diff --git a/chrome/browser/ui/crypto_module_delegate_nss.cc b/chrome/browser/ui/crypto_module_delegate_nss.cc index 7211e8a..a296380 100644 --- a/chrome/browser/ui/crypto_module_delegate_nss.cc +++ b/chrome/browser/ui/crypto_module_delegate_nss.cc
@@ -7,66 +7,21 @@ #include <utility> #include "base/bind.h" -#include "chrome/browser/net/nss_context.h" #include "content/public/browser/browser_thread.h" using content::BrowserThread; -namespace { - -void CreateWithSlot( - chrome::CryptoModulePasswordReason reason, - const net::HostPortPair& server, - const base::Callback<void(std::unique_ptr<ChromeNSSCryptoModuleDelegate>)>& - callback, - crypto::ScopedPK11Slot slot) { - if (!slot) { - callback.Run(std::unique_ptr<ChromeNSSCryptoModuleDelegate>()); - return; - } - callback.Run(std::unique_ptr<ChromeNSSCryptoModuleDelegate>( - new ChromeNSSCryptoModuleDelegate(reason, server, std::move(slot)))); -} - -} // namespace - ChromeNSSCryptoModuleDelegate::ChromeNSSCryptoModuleDelegate( chrome::CryptoModulePasswordReason reason, - const net::HostPortPair& server, - crypto::ScopedPK11Slot slot) + const net::HostPortPair& server) : reason_(reason), server_(server), event_(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED), - cancelled_(false), - slot_(std::move(slot)) {} + cancelled_(false) {} ChromeNSSCryptoModuleDelegate::~ChromeNSSCryptoModuleDelegate() {} -// static -void ChromeNSSCryptoModuleDelegate::CreateForResourceContext( - chrome::CryptoModulePasswordReason reason, - const net::HostPortPair& server, - content::ResourceContext* context, - const base::Callback<void(std::unique_ptr<ChromeNSSCryptoModuleDelegate>)>& - callback) { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - DCHECK(!callback.is_null()); - - base::Callback<void(crypto::ScopedPK11Slot)> get_slot_callback = - base::Bind(&CreateWithSlot, reason, server, callback); - - crypto::ScopedPK11Slot slot = - GetPrivateNSSKeySlotForResourceContext(context, get_slot_callback); - if (slot) - get_slot_callback.Run(std::move(slot)); -} - -// TODO(mattm): allow choosing which slot to generate and store the key. -crypto::ScopedPK11Slot ChromeNSSCryptoModuleDelegate::RequestSlot() { - return std::move(slot_); -} - std::string ChromeNSSCryptoModuleDelegate::RequestPassword( const std::string& slot_name, bool retry, @@ -114,9 +69,5 @@ CreateCryptoModuleBlockingPasswordDelegate( chrome::CryptoModulePasswordReason reason, const net::HostPortPair& server) { - // Returns a ChromeNSSCryptoModuleDelegate without Pk11Slot. Since it is only - // being used as a CryptoModuleBlockingDialogDelegate, using a slot handle is - // unnecessary. - return new ChromeNSSCryptoModuleDelegate( - reason, server, crypto::ScopedPK11Slot()); + return new ChromeNSSCryptoModuleDelegate(reason, server); }
diff --git a/chrome/browser/ui/crypto_module_delegate_nss.h b/chrome/browser/ui/crypto_module_delegate_nss.h index 45029f8..3af79b9 100644 --- a/chrome/browser/ui/crypto_module_delegate_nss.h +++ b/chrome/browser/ui/crypto_module_delegate_nss.h
@@ -7,45 +7,26 @@ #include <string> -#include "base/compiler_specific.h" #include "base/macros.h" #include "base/synchronization/waitable_event.h" #include "chrome/browser/ui/crypto_module_password_dialog.h" #include "crypto/nss_crypto_module_delegate.h" #include "net/base/host_port_pair.h" -namespace content { -class ResourceContext; -} - // Delegate to handle unlocking a slot or indicating which slot to store a key // in. When passing to NSS functions which take a wincx argument, use the value // returned from the wincx() method. class ChromeNSSCryptoModuleDelegate - : public crypto::NSSCryptoModuleDelegate { + : public crypto::CryptoModuleBlockingPasswordDelegate { public: // Create a ChromeNSSCryptoModuleDelegate. |reason| is used to select what // string to show the user, |server| is displayed to indicate which connection // is causing the dialog to appear. |slot| can be NULL. ChromeNSSCryptoModuleDelegate(chrome::CryptoModulePasswordReason reason, - const net::HostPortPair& server, - crypto::ScopedPK11Slot slot); + const net::HostPortPair& server); ~ChromeNSSCryptoModuleDelegate() override; - // Must be called on IO thread. Creates a delegate and returns it - // synchronously or asynchronously to |callback|. If the delegate could not be - // created, |callback| is called with NULL. - static void CreateForResourceContext( - chrome::CryptoModulePasswordReason reason, - const net::HostPortPair& server, - content::ResourceContext* context, - const base::Callback< - void(std::unique_ptr<ChromeNSSCryptoModuleDelegate>)>& callback); - - // crypto::NSSCryptoModuleDelegate implementation. - crypto::ScopedPK11Slot RequestSlot() override; - // crypto::CryptoModuleBlockingPasswordDelegate implementation. std::string RequestPassword(const std::string& slot_name, bool retry, @@ -67,9 +48,6 @@ std::string password_; bool cancelled_; - // The slot which will be returned by RequestSlot. - crypto::ScopedPK11Slot slot_; - DISALLOW_COPY_AND_ASSIGN(ChromeNSSCryptoModuleDelegate); };
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 38aeef5..babe43fc 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -118,8 +118,8 @@ const SkColor colors[2] = { color, SkColorSetA(color, 0) }; cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setShader(cc::WrapSkShader(SkGradientShader::MakeRadial( - p, radius, colors, nullptr, 2, SkShader::kClamp_TileMode))); + flags.setShader(cc::PaintShader::MakeRadialGradient( + p, radius, colors, nullptr, 2, SkShader::kClamp_TileMode)); canvas->sk_canvas()->drawRect( SkRect::MakeXYWH(p.x() - radius, p.y() - radius, radius * 2, radius * 2), flags);
diff --git a/chrome/browser/ui/webui/DEPS b/chrome/browser/ui/webui/DEPS index e54b94ad..f866a1e 100644 --- a/chrome/browser/ui/webui/DEPS +++ b/chrome/browser/ui/webui/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+components/about_ui" "+components/invalidation", "+components/onc", "+components/proximity_auth",
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc index 67182676..1216a073 100644 --- a/chrome/browser/ui/webui/about_ui.cc +++ b/chrome/browser/ui/webui/about_ui.cc
@@ -49,6 +49,7 @@ #include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" +#include "components/about_ui/credit_utils.h" #include "components/grit/components_resources.h" #include "components/strings/grit/components_locale_settings.h" #include "content/public/browser/browser_thread.h" @@ -691,32 +692,14 @@ idr = IDR_KEYBOARD_UTILS_JS; #endif - base::StringPiece raw_response = - ResourceBundle::GetSharedInstance().GetRawDataResource(idr); if (idr == IDR_ABOUT_UI_CREDITS_HTML) { - const uint8_t* next_encoded_byte = - reinterpret_cast<const uint8_t*>(raw_response.data()); - size_t input_size_remaining = raw_response.size(); - BrotliDecoderState* decoder = - BrotliDecoderCreateInstance(nullptr /* no custom allocator */, - nullptr /* no custom deallocator */, - nullptr /* no custom memory handle */); - CHECK(!!decoder); - while (!BrotliDecoderIsFinished(decoder)) { - size_t output_size_remaining = 0; - CHECK(BrotliDecoderDecompressStream( - decoder, &input_size_remaining, &next_encoded_byte, - &output_size_remaining, nullptr, - nullptr) != BROTLI_DECODER_RESULT_ERROR); - const uint8_t* output_buffer = - BrotliDecoderTakeOutput(decoder, &output_size_remaining); - response.insert(response.end(), output_buffer, - output_buffer + output_size_remaining); - } - BrotliDecoderDestroyInstance(decoder); + response = about_ui::GetCredits(true /*include_scripts*/); } else { - response = raw_response.as_string(); + response = ResourceBundle::GetSharedInstance() + .GetRawDataResource(idr) + .as_string(); } + #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) } else if (source_name_ == chrome::kChromeUIDiscardsHost) { response = AboutDiscards(path);
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 9edc6249..e0a11e502 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -199,6 +199,9 @@ // Id of the predefined PDF printer. const char kLocalPdfPrinterId[] = "Save as PDF"; +// Timeout for searching for privet printers, in seconds. +const int kPrivetTimeoutSec = 5; + // Get the print job settings dictionary from |args|. The caller takes // ownership of the returned DictionaryValue. Returns NULL on failure. std::unique_ptr<base::DictionaryValue> GetSettingsDictionary( @@ -615,9 +618,6 @@ web_ui()->RegisterMessageCallback("getPrivetPrinters", base::Bind(&PrintPreviewHandler::HandleGetPrivetPrinters, base::Unretained(this))); - web_ui()->RegisterMessageCallback("stopGetPrivetPrinters", - base::Bind(&PrintPreviewHandler::HandleStopGetPrivetPrinters, - base::Unretained(this))); web_ui()->RegisterMessageCallback("getPrivetPrinterCapabilities", base::Bind(&PrintPreviewHandler::HandleGetPrivetPrinterCapabilities, base::Unretained(this))); @@ -675,22 +675,32 @@ } void PrintPreviewHandler::HandleGetPrivetPrinters(const base::ListValue* args) { - if (!PrivetPrintingEnabled()) - return web_ui()->CallJavascriptFunctionUnsafe("onPrivetPrinterSearchDone"); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + CHECK(!callback_id.empty()); + + AllowJavascript(); + + if (!PrivetPrintingEnabled()) { + RejectJavascriptCallback(base::Value(callback_id), base::Value(false)); + } #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) using local_discovery::ServiceDiscoverySharedClient; scoped_refptr<ServiceDiscoverySharedClient> service_discovery = ServiceDiscoverySharedClient::GetInstance(); + DCHECK(privet_callback_id_.empty()); + privet_callback_id_ = callback_id; StartPrivetLister(service_discovery); #endif } -void PrintPreviewHandler::HandleStopGetPrivetPrinters( - const base::ListValue* args) { +void PrintPreviewHandler::StopPrivetLister() { #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) + privet_lister_timer_.reset(); if (PrivetPrintingEnabled() && printer_lister_) { printer_lister_->Stop(); } + ResolveJavascriptCallback(base::Value(privet_callback_id_), base::Value()); #endif } @@ -1527,15 +1537,16 @@ #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) void PrintPreviewHandler::StartPrivetLister(const scoped_refptr< local_discovery::ServiceDiscoverySharedClient>& client) { - if (!PrivetPrintingEnabled()) - return web_ui()->CallJavascriptFunctionUnsafe("onPrivetPrinterSearchDone"); - Profile* profile = Profile::FromWebUI(web_ui()); DCHECK(!service_discovery_client_.get() || service_discovery_client_.get() == client.get()); service_discovery_client_ = client; printer_lister_ = base::MakeUnique<cloud_print::PrivetLocalPrinterLister>( service_discovery_client_.get(), profile->GetRequestContext(), this); + privet_lister_timer_.reset(new base::OneShotTimer()); + privet_lister_timer_->Start(FROM_HERE, + base::TimeDelta::FromSeconds(kPrivetTimeoutSec), + this, &PrintPreviewHandler::StopPrivetLister); printer_lister_->Start(); } @@ -1548,7 +1559,7 @@ command_line->HasSwitch(switches::kEnablePrintPreviewRegisterPromos)) { base::DictionaryValue info; FillPrinterDescription(name, description, has_local_printing, &info); - web_ui()->CallJavascriptFunctionUnsafe("onPrivetPrinterChanged", info); + FireWebUIListener("privet-printer-added", info); } }
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 a6c69fa..61133eb6 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/timer/timer.h" #include "chrome/common/features.h" #include "components/signin/core/browser/gaia_cookie_manager_service.h" #include "content/public/browser/web_ui_message_handler.h" @@ -142,9 +143,6 @@ // |args| is the provisional printer ID. void HandleGrantExtensionPrinterAccess(const base::ListValue* args); - // Stops getting all local privet printers. |arg| is unused. - void HandleStopGetPrivetPrinters(const base::ListValue* args); - // Asks the initiator renderer to generate a preview. First element of |args| // is a job settings JSON string. void HandleGetPreview(const base::ListValue* args); @@ -286,6 +284,7 @@ #if BUILDFLAG(ENABLE_SERVICE_DISCOVERY) void StartPrivetLister(const scoped_refptr< local_discovery::ServiceDiscoverySharedClient>& client); + void StopPrivetLister(); void OnPrivetCapabilities(const base::DictionaryValue* capabilities); void PrivetCapabilitiesUpdateClient( std::unique_ptr<cloud_print::PrivetHTTPClient> http_client); @@ -384,7 +383,7 @@ scoped_refptr<local_discovery::ServiceDiscoverySharedClient> service_discovery_client_; std::unique_ptr<cloud_print::PrivetLocalPrinterLister> printer_lister_; - + std::unique_ptr<base::OneShotTimer> privet_lister_timer_; std::unique_ptr<cloud_print::PrivetHTTPAsynchronousFactory> privet_http_factory_; std::unique_ptr<cloud_print::PrivetHTTPResolution> privet_http_resolution_; @@ -403,6 +402,9 @@ // notify the test if it was a successful save, only that it was attempted. base::Closure pdf_file_saved_closure_; + // Callback ID to be used to notify UI that privet search is finished. + std::string privet_callback_id_ = ""; + // Proxy for calls to the print backend. Lazily initialized since web_ui() is // not available at construction time. std::unique_ptr<printing::PrinterBackendProxy> printer_backend_proxy_;
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index e9578be..17791d72 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -218,10 +218,6 @@ {"engine_params", crash_keys::kMediumSize}, {"engine1_params", crash_keys::kMediumSize}, {"engine2_params", crash_keys::kMediumSize}, - - // Temporary for http://crbug.com/703649. - {"field_trial_shmem_create_error", crash_keys::kSmallSize}, - {"field_trial_shmem_map_error", crash_keys::kSmallSize}, }; // This dynamic set of keys is used for sets of key value pairs when gathering
diff --git a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/background.js b/chrome/test/data/extensions/api_test/webrequest/policy_blocked/background.js deleted file mode 100644 index 546ba78..0000000 --- a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/background.js +++ /dev/null
@@ -1,13 +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. - -// Return messages to tell which URL requests are visible to the extension. -chrome.webRequest.onBeforeRequest.addListener(function(details) { - if (details.url.indexOf('example2') != -1) { - chrome.test.sendMessage('protected_origin'); - } - if (details.url.indexOf('protected_url') != -1) { - chrome.test.sendMessage('protected_url'); - } -}, {urls: ['<all_urls>']}, []);
diff --git a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/manifest.json b/chrome/test/data/extensions/api_test/webrequest/policy_blocked/manifest.json deleted file mode 100644 index c414d5e..0000000 --- a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/manifest.json +++ /dev/null
@@ -1,9 +0,0 @@ -{ - "name": "Web Request Policy Tests", - "version": "1", - "manifest_version": 2, - "permissions": ["webRequest", "<all_urls>"], - "background" : { - "scripts": ["background.js"] - } -}
diff --git a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.html b/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.html deleted file mode 100644 index 8271dc01..0000000 --- a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.html +++ /dev/null
@@ -1,9 +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. ---> -<html> - <body></body> - <script src="ref_remote_js.js"></script> -</html>
diff --git a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.js b/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.js deleted file mode 100644 index 600d094..0000000 --- a/chrome/test/data/extensions/api_test/webrequest/policy_blocked/ref_remote_js.js +++ /dev/null
@@ -1,11 +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. - -// Injects a script tag with a source based on the current URL. The script -// however will be served from a different domain (example2.com) and target a -// different file which is blank. This lets us make a request with an initiator -// of example.com and a URL of example2.com. -var script = document.createElement('script'); -script.src = 'http://example2.com:' + location.port + '/empty.html'; -document.body.appendChild(script);
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 4e35e6b..51f80161 100644 --- a/chrome/test/data/webui/print_preview/native_layer_stub.js +++ b/chrome/test/data/webui/print_preview/native_layer_stub.js
@@ -13,6 +13,7 @@ 'getInitialSettings', 'getPrinters', 'getExtensionPrinters', + 'getPrivetPrinters', 'setupPrinter' ]); @@ -90,6 +91,12 @@ }, /** @override */ + getPrivetPrinters: function() { + this.methodCalled('getPrivetPrinters'); + return Promise.resolve(true); + }, + + /** @override */ setupPrinter: function(printerId) { this.methodCalled('setupPrinter', printerId); return this.shouldRejectPrinterSetup_ ? @@ -99,8 +106,6 @@ /** Stubs for |print_preview.NativeLayer| methods that call C++ handlers. */ previewReadyForTest: function() {}, - startGetLocalDestinations: function() {}, - startGetPrivetDestinations: function() {}, startGetLocalDestinationCapabilities: function(destinationId) { if (destinationId == this.destinationToWatch_) this.getLocalDestinationCapabilitiesCallCount_++;
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc index 65c4b31..4f308fc7 100644 --- a/chrome/utility/chrome_content_utility_client.cc +++ b/chrome/utility/chrome_content_utility_client.cc
@@ -34,7 +34,7 @@ #include "chrome/common/resource_usage_reporter.mojom.h" #include "chrome/utility/media_router/dial_device_description_parser_impl.h" #include "chrome/utility/profile_import_handler.h" -#include "net/proxy/mojo_proxy_resolver_factory_impl.h" +#include "net/proxy/mojo_proxy_resolver_factory_impl.h" // nogncheck #include "net/proxy/proxy_resolver_v8.h" #endif // !defined(OS_ANDROID)
diff --git a/components/about_ui/BUILD.gn b/components/about_ui/BUILD.gn new file mode 100644 index 0000000..b1b5949 --- /dev/null +++ b/components/about_ui/BUILD.gn
@@ -0,0 +1,21 @@ +# 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. + +static_library("about_ui") { + sources = [ + "credit_utils.cc", + "credit_utils.h", + ] + deps = [ + "//base", + "//components/resources:components_resources", + "//third_party/brotli:dec", + "//ui/base", + "//ui/resources", + ] + + if (is_android) { + deps += [ "//components/about_ui/android:about_ui_jni_headers" ] + } +}
diff --git a/components/about_ui/DEPS b/components/about_ui/DEPS new file mode 100644 index 0000000..72b42ddc --- /dev/null +++ b/components/about_ui/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+components/grit/components_resources.h", + "+jni", + "+third_party/brotli", + "+ui/base", +]
diff --git a/components/about_ui/android/BUILD.gn b/components/about_ui/android/BUILD.gn new file mode 100644 index 0000000..7e825471 --- /dev/null +++ b/components/about_ui/android/BUILD.gn
@@ -0,0 +1,18 @@ +# 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. +import("//build/config/android/rules.gni") + +generate_jni("about_ui_jni_headers") { + sources = [ + "java/src/org/chromium/components/aboutui/CreditUtils.java", + ] + jni_package = "components/about_ui" +} + +android_library("aboutui_java") { + java_files = [ "java/src/org/chromium/components/aboutui/CreditUtils.java" ] + deps = [ + "//base:base_java", + ] +}
diff --git a/components/about_ui/android/OWNERS b/components/about_ui/android/OWNERS new file mode 100644 index 0000000..d99c934 --- /dev/null +++ b/components/about_ui/android/OWNERS
@@ -0,0 +1,2 @@ +agrieve@chromium.org +torne@chromium.org
diff --git a/components/about_ui/android/java/src/org/chromium/components/aboutui/CreditUtils.java b/components/about_ui/android/java/src/org/chromium/components/aboutui/CreditUtils.java new file mode 100644 index 0000000..b2be4ad --- /dev/null +++ b/components/about_ui/android/java/src/org/chromium/components/aboutui/CreditUtils.java
@@ -0,0 +1,16 @@ +// 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. + +package org.chromium.components.aboutui; + +import org.chromium.base.annotations.JNINamespace; + +/** Credits-related utilities. */ +@JNINamespace("about_ui") +public class CreditUtils { + private CreditUtils() {} + + /** Returns a string containing the content of about_credits.html. */ + public static native byte[] nativeGetJavaWrapperCredits(); +}
diff --git a/components/about_ui/credit_utils.cc b/components/about_ui/credit_utils.cc new file mode 100644 index 0000000..238512d6 --- /dev/null +++ b/components/about_ui/credit_utils.cc
@@ -0,0 +1,71 @@ +// 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/about_ui/credit_utils.h" + +#include <stdint.h> + +#include "base/strings/string_piece.h" +#include "components/grit/components_resources.h" +#include "third_party/brotli/include/brotli/decode.h" +#include "ui/base/resource/resource_bundle.h" + +#if defined(OS_ANDROID) +#include "base/android/jni_array.h" +#include "jni/CreditUtils_jni.h" +#endif + +namespace about_ui { + +std::string GetCredits(bool include_scripts) { + std::string response; + base::StringPiece raw_response = + ResourceBundle::GetSharedInstance().GetRawDataResource( + IDR_ABOUT_UI_CREDITS_HTML); + const uint8_t* next_encoded_byte = + reinterpret_cast<const uint8_t*>(raw_response.data()); + size_t input_size_remaining = raw_response.size(); + BrotliDecoderState* decoder = BrotliDecoderCreateInstance( + nullptr /* no custom allocator */, nullptr /* no custom deallocator */, + nullptr /* no custom memory handle */); + CHECK(!!decoder); + while (!BrotliDecoderIsFinished(decoder)) { + size_t output_size_remaining = 0; + CHECK(BrotliDecoderDecompressStream( + decoder, &input_size_remaining, &next_encoded_byte, + &output_size_remaining, nullptr, + nullptr) != BROTLI_DECODER_RESULT_ERROR); + const uint8_t* output_buffer = + BrotliDecoderTakeOutput(decoder, &output_size_remaining); + response.insert(response.end(), output_buffer, + output_buffer + output_size_remaining); + } + BrotliDecoderDestroyInstance(decoder); + if (include_scripts) { + response += + "\n<script src=\"chrome://resources/js/cr.js\"></script>\n" + "<script src=\"chrome://credits/credits.js\"></script>\n"; + } + response += "</body>\n</html>"; + return response; +} + +#if defined(OS_ANDROID) +static base::android::ScopedJavaLocalRef<jbyteArray> GetJavaWrapperCredits( + JNIEnv* env, + const base::android::JavaParamRef<jclass>& clazz) { + std::string html_content = GetCredits(false); + const char* html_content_arr = html_content.c_str(); + return base::android::ToJavaByteArray( + env, reinterpret_cast<const uint8_t*>(html_content_arr), + html_content.size()); +} + +// The RegisterNativesImpl is a static function, so has to be called somewhere. +bool RegisterAboutUIUtils(JNIEnv* env) { + return RegisterNativesImpl(env); +} +#endif + +} // namespace about_ui
diff --git a/components/about_ui/credit_utils.h b/components/about_ui/credit_utils.h new file mode 100644 index 0000000..2bc9345 --- /dev/null +++ b/components/about_ui/credit_utils.h
@@ -0,0 +1,17 @@ +// 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_ABOUT_UI_CREDIT_UTILS_H_ +#define COMPONENTS_ABOUT_UI_CREDIT_UTILS_H_ + +#include <string> + +namespace about_ui { + +// Decode a Brotli compressed HTML license file and attach .js files. +std::string GetCredits(bool include_scripts); + +} // namespace about_ui + +#endif // COMPONENTS_ABOUT_UI_CREDIT_UTILS_H_
diff --git a/components/about_ui/resources/about_credits.js b/components/about_ui/resources/about_credits.js index d01ffb6..3339a7e 100644 --- a/components/about_ui/resources/about_credits.js +++ b/components/about_ui/resources/about_credits.js
@@ -2,56 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +/* eslint-disable no-restricted-properties */ function $(id) { return document.getElementById(id); } - -function toggle(o) { - var licence = o.nextSibling; - - while (licence.className != 'licence') { - if (!licence) return false; - licence = licence.nextSibling; - } - - if (licence.style && licence.style.display == 'block') { - licence.style.display = 'none'; - o.textContent = 'show license'; - } else { - licence.style.display = 'block'; - o.textContent = 'hide license'; - } - return false; -} +/* eslint-enable no-restricted-properties */ document.addEventListener('DOMContentLoaded', function() { - var licenseEls = [].slice.call(document.getElementsByClassName('product')); - - licenseEls.sort(function(a, b) { - var nameA = a.getElementsByClassName('title')[0].textContent; - var nameB = b.getElementsByClassName('title')[0].textContent; - if (nameA < nameB) return -1; - if (nameA > nameB) return 1; - return 0; - }); - - var parentEl = licenseEls[0].parentNode; - parentEl.innerHTML = ''; - for (var i = 0; i < licenseEls.length; i++) { - parentEl.appendChild(licenseEls[i]); - } - - document.body.hidden = false; - if (cr.isChromeOS) { var keyboardUtils = document.createElement('script'); keyboardUtils.src = 'chrome://credits/keyboard_utils.js'; document.body.appendChild(keyboardUtils); } - var links = document.querySelectorAll('a.show'); - for (var i = 0; i < links.length; ++i) { - links[i].onclick = function() { return toggle(this); }; - } - + $('print-link').hidden = false; $('print-link').onclick = function() { window.print(); return false;
diff --git a/components/about_ui/resources/about_credits.tmpl b/components/about_ui/resources/about_credits.tmpl index fc4fc965..5aa5c9b 100644 --- a/components/about_ui/resources/about_credits.tmpl +++ b/components/about_ui/resources/about_credits.tmpl
@@ -2,6 +2,7 @@ <html> <head> <meta charset="utf-8"> +<meta name="viewport" content="width=device-width"> <title>Credits</title> <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <style> @@ -28,17 +29,20 @@ margin: 3px; } .product .homepage { + color: blue; float: right; margin: 3px; text-align: right; } -.product .homepage::after { +.product .homepage::before { content: " - "; } .product .show { + color: blue; float: right; margin: 3px; text-align: right; + text-decoration: underline; } .licence { background-color: #e8eef7; @@ -57,15 +61,23 @@ .dialog .homepage { display: none; } +input + label + div { + display: none; +} +input + label::after { + content: "show license"; +} +input:checked + label + div { + display: block; +} +input:checked + label::after { + content: "hide license"; +} </style> </head> -<body hidden> +<body> <span class="page-title" style="float:left;">Credits</span> -<a id="print-link" href="#" style="float:right;">Print</a> +<a id="print-link" href="#" style="float:right;" hidden>Print</a> <div style="clear:both; overflow:auto;"><!-- Chromium <3s the following projects --> {{entries}} </div> -<script src="chrome://resources/js/cr.js"></script> -<script src="chrome://credits/credits.js"></script> -</body> -</html> \ No newline at end of file
diff --git a/components/about_ui/resources/about_credits_entry.tmpl b/components/about_ui/resources/about_credits_entry.tmpl index d1810cd..51aa468 100644 --- a/components/about_ui/resources/about_credits_entry.tmpl +++ b/components/about_ui/resources/about_credits_entry.tmpl
@@ -1,9 +1,9 @@ <div class="product"> <span class="title">{{name}}</span> -<a class="show" href="#">show license</a> <span class="homepage"><a href="{{url}}">homepage</a></span> +<input type="checkbox" hidden id="{{id}}"> +<label class="show" for="{{id}}"></label> <div class="licence"> <pre>{{license}}</pre> </div> </div> -
diff --git a/components/cronet/android/api/src/org/chromium/net/QuicException.java b/components/cronet/android/api/src/org/chromium/net/QuicException.java index b302cee..e3754afd 100644 --- a/components/cronet/android/api/src/org/chromium/net/QuicException.java +++ b/components/cronet/android/api/src/org/chromium/net/QuicException.java
@@ -28,7 +28,7 @@ /** * Returns the <a href="https://www.chromium.org/quic">QUIC</a> error code, which is a value * from <a - * href=https://cs.chromium.org/chromium/src/net/quic/quic_protocol.h?type=cs&q=%22enum+QuicErrorCode+%7B%22+file:src/net/quic/quic_protocol.h> + * href=https://cs.chromium.org/chromium/src/net/quic/core/quic_error_codes.h?type=cs&q=%22enum+QuicErrorCode+%7B%22> * QuicErrorCode</a>. */ public abstract int getQuicDetailedErrorCode();
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc index d9d959ae..8915fbe 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.cc
@@ -35,6 +35,10 @@ // each message gets 3 attempts: the first one, and 2 retries. const int kMaxNumberOfRetryAttempts = 2; +// The time to wait in seconds for the server to send its connection response. +// If not received within this time, the connection will fail. +const int kConnectionResponseTimeoutSeconds = 2; + } // namespace // static @@ -76,7 +80,12 @@ BluetoothThrottler* bluetooth_throttler) { return base::MakeUnique<BluetoothLowEnergyWeaveClientConnection>( remote_device, device_address, adapter, remote_service_uuid, - bluetooth_throttler); + bluetooth_throttler, base::MakeUnique<TimerFactory>()); +} + +std::unique_ptr<base::Timer> +BluetoothLowEnergyWeaveClientConnection::TimerFactory::CreateTimer() { + return base::MakeUnique<base::OneShotTimer>(); } BluetoothLowEnergyWeaveClientConnection:: @@ -85,7 +94,8 @@ const std::string& device_address, scoped_refptr<device::BluetoothAdapter> adapter, const device::BluetoothUUID remote_service_uuid, - BluetoothThrottler* bluetooth_throttler) + BluetoothThrottler* bluetooth_throttler, + std::unique_ptr<TimerFactory> timer_factory) : Connection(device), device_address_(device_address), adapter_(adapter), @@ -98,6 +108,7 @@ tx_characteristic_({device::BluetoothUUID(kTXCharacteristicUUID), ""}), rx_characteristic_({device::BluetoothUUID(kRXCharacteristicUUID), ""}), bluetooth_throttler_(bluetooth_throttler), + timer_factory_(std::move(timer_factory)), task_runner_(base::ThreadTaskRunnerHandle::Get()), sub_status_(SubStatus::DISCONNECTED), write_remote_characteristic_pending_(false), @@ -346,6 +357,7 @@ void BluetoothLowEnergyWeaveClientConnection::CompleteConnection() { PA_LOG(INFO) << "Connection completed. Time elapsed: " << base::TimeTicks::Now() - start_time_; + connection_response_timer_->Stop(); SetSubStatus(SubStatus::CONNECTED); } @@ -489,6 +501,13 @@ if (sub_status() == SubStatus::NOTIFY_SESSION_READY) { PA_LOG(INFO) << "Sending connection request to the server"; SetSubStatus(SubStatus::WAITING_CONNECTION_RESPONSE); + connection_response_timer_ = timer_factory_->CreateTimer(); + connection_response_timer_->Start( + FROM_HERE, + base::TimeDelta::FromSeconds(kConnectionResponseTimeoutSeconds), + base::Bind(&BluetoothLowEnergyWeaveClientConnection:: + OnConnectionResponseTimeout, + weak_ptr_factory_.GetWeakPtr())); WriteRequest write_request(packet_generator_->CreateConnectionRequest(), WriteRequestType::CONNECTION_REQUEST); @@ -615,6 +634,13 @@ PA_LOG(INFO) << "Time elapsed: " << base::TimeTicks::Now() - start_time_; } +void BluetoothLowEnergyWeaveClientConnection::OnConnectionResponseTimeout() { + DCHECK(sub_status() == SubStatus::WAITING_CONNECTION_RESPONSE); + PA_LOG(ERROR) << "Timed out waiting for connection response. Closing " + << "connection."; + DestroyConnection(); +} + std::string BluetoothLowEnergyWeaveClientConnection::GetDeviceAddress() { // When the remote device is connected we should rely on the address given by // |gatt_connection_|. As the device address may change if the device is
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h index e86990c4..1ce1474 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection.h
@@ -17,6 +17,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "base/timer/timer.h" #include "components/cryptauth/ble/bluetooth_low_energy_characteristics_finder.h" #include "components/cryptauth/ble/bluetooth_low_energy_weave_packet_generator.h" #include "components/cryptauth/ble/bluetooth_low_energy_weave_packet_receiver.h" @@ -78,6 +79,11 @@ static Factory* factory_instance_; }; + class TimerFactory { + public: + virtual std::unique_ptr<base::Timer> CreateTimer(); + }; + // The sub-state of a BluetoothLowEnergyWeaveClientConnection // extends the IN_PROGRESS state of Connection::Status. enum SubStatus { @@ -94,7 +100,7 @@ // Constructs a Bluetooth low energy connection to the service with // |remote_service_| on the |remote_device|. The |adapter| must be already - // initialized and ready. The GATT connection may alreaady be established and + // initialized and ready. The GATT connection may already be established and // pass through |gatt_connection|. A subsequent call to Connect() must be // made. BluetoothLowEnergyWeaveClientConnection( @@ -102,7 +108,8 @@ const std::string& device_address, scoped_refptr<device::BluetoothAdapter> adapter, const device::BluetoothUUID remote_service_uuid, - BluetoothThrottler* bluetooth_throttler); + BluetoothThrottler* bluetooth_throttler, + std::unique_ptr<TimerFactory> timer_factory); ~BluetoothLowEnergyWeaveClientConnection() override; @@ -252,6 +259,9 @@ // Prints the time elapsed since |Connect()| was called. void PrintTimeElapsed(); + // Called when waiting for connection response from server times out. + void OnConnectionResponseTimeout(); + // Returns the service corresponding to |remote_service_| in the current // device. device::BluetoothRemoteGattService* GetRemoteService(); @@ -294,6 +304,9 @@ // workaround for crbug.com/508919. Not owned, must outlive this instance. BluetoothThrottler* bluetooth_throttler_; + // Used for timing out when waiting for connection response from the server. + std::unique_ptr<TimerFactory> timer_factory_; + scoped_refptr<base::TaskRunner> task_runner_; // The GATT connection with the remote device. @@ -319,9 +332,12 @@ std::queue<WriteRequest> write_requests_queue_; - // Stores when the instace was created. + // Stores when the instance was created. base::TimeTicks start_time_; + // Used for timing out when waiting for connection response from the server. + std::unique_ptr<base::Timer> connection_response_timer_; + base::WeakPtrFactory<BluetoothLowEnergyWeaveClientConnection> weak_ptr_factory_;
diff --git a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc index 894860c..fe23252 100644 --- a/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc +++ b/components/cryptauth/ble/bluetooth_low_energy_weave_client_connection_unittest.cc
@@ -14,6 +14,8 @@ #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/test_simple_task_runner.h" +#include "base/timer/mock_timer.h" +#include "base/timer/timer.h" #include "components/cryptauth/bluetooth_throttler.h" #include "components/cryptauth/connection_finder.h" #include "components/cryptauth/connection_observer.h" @@ -311,6 +313,21 @@ MockBluetoothLowEnergyWeavePacketReceiver* most_recent_instance_; }; +class TestTimerFactory + : public BluetoothLowEnergyWeaveClientConnection::TimerFactory { + public: + std::unique_ptr<base::Timer> CreateTimer() override { + last_created_timer_ = new base::MockTimer(false /* retains_user_task */, + false /* is_repeating */); + return base::WrapUnique(last_created_timer_); + } + + base::MockTimer* last_created_timer() { return last_created_timer_; } + + private: + base::MockTimer* last_created_timer_; +}; + class TestBluetoothLowEnergyWeaveClientConnection : public BluetoothLowEnergyWeaveClientConnection { public: @@ -319,12 +336,15 @@ const std::string& device_address, scoped_refptr<device::BluetoothAdapter> adapter, const device::BluetoothUUID remote_service_uuid, - BluetoothThrottler* bluetooth_throttler) + BluetoothThrottler* bluetooth_throttler, + std::unique_ptr<BluetoothLowEnergyWeaveClientConnection::TimerFactory> + timer_factory) : BluetoothLowEnergyWeaveClientConnection(remote_device, device_address, adapter, remote_service_uuid, - bluetooth_throttler) {} + bluetooth_throttler, + std::move(timer_factory)) {} ~TestBluetoothLowEnergyWeaveClientConnection() override {} @@ -363,6 +383,7 @@ rx_characteristic_uuid_(device::BluetoothUUID(kRXCharacteristicUUID)), notify_session_alias_(NULL), bluetooth_throttler_(new NiceMock<MockBluetoothThrottler>), + test_timer_factory_(new TestTimerFactory()), task_runner_(new base::TestSimpleTaskRunner), generator_factory_( new MockBluetoothLowEnergyWeavePacketGeneratorFactory()), @@ -426,7 +447,8 @@ std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection( new TestBluetoothLowEnergyWeaveClientConnection( remote_device_, kTestRemoteDeviceBluetoothAddress, adapter_, - service_uuid_, bluetooth_throttler_.get())); + service_uuid_, bluetooth_throttler_.get(), + base::WrapUnique(test_timer_factory_))); EXPECT_EQ(connection->sub_status(), SubStatus::DISCONNECTED); EXPECT_EQ(connection->status(), Connection::DISCONNECTED); @@ -624,6 +646,7 @@ std::vector<uint8_t> last_value_written_on_tx_characteristic_; device::MockBluetoothGattNotifySession* notify_session_alias_; std::unique_ptr<MockBluetoothThrottler> bluetooth_throttler_; + TestTimerFactory* test_timer_factory_; scoped_refptr<base::TestSimpleTaskRunner> task_runner_; base::MessageLoop message_loop_; bool last_wire_message_success_; @@ -662,7 +685,8 @@ CreateAndDestroyWithoutConnectCallDoesntCrash) { BluetoothLowEnergyWeaveClientConnection connection( remote_device_, kTestRemoteDeviceBluetoothAddress, adapter_, - service_uuid_, bluetooth_throttler_.get()); + service_uuid_, bluetooth_throttler_.get(), + base::WrapUnique(test_timer_factory_)); } TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, @@ -1162,6 +1186,20 @@ ConnectionResponseReceived(connection.get(), kDefaultMaxPacketSize); } +TEST_F(CryptAuthBluetoothLowEnergyWeaveClientConnectionTest, + ConnectionResponseTimeout) { + std::unique_ptr<TestBluetoothLowEnergyWeaveClientConnection> connection( + CreateConnection()); + ConnectGatt(connection.get()); + CharacteristicsFound(connection.get()); + NotifySessionStarted(connection.get()); + + test_timer_factory_->last_created_timer()->Fire(); + + EXPECT_EQ(connection->sub_status(), SubStatus::DISCONNECTED); + EXPECT_EQ(connection->status(), Connection::DISCONNECTED); +} + } // namespace weave } // namespace cryptauth
diff --git a/components/neterror/resources/neterror.html b/components/neterror/resources/neterror.html index 3851e4fe..3038e717 100644 --- a/components/neterror/resources/neterror.html +++ b/components/neterror/resources/neterror.html
@@ -6,9 +6,9 @@ maximum-scale=1.0, user-scalable=no"> <title i18n-content="title"></title> <link rel="stylesheet" href="../../../components/security_interstitials/core/browser/resources/interstitial_common.css"> - <link rel="stylesheet" href="../../../components/security_interstitials/core/browser/resources/interstitial_v2.css"> + <link rel="stylesheet" href="../../../components/security_interstitials/core/browser/resources/interstitial_large.css"> <link rel="stylesheet" href="neterror.css"> - <script src="../../../components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js"></script> + <script src="../../../components/security_interstitials/core/browser/resources/interstitial_mobile_nav.js"></script> <script src="neterror.js"></script> <script src="offline.js"></script> </head>
diff --git a/components/offline_pages/core/offline_page_feature.cc b/components/offline_pages/core/offline_page_feature.cc index 9dfab58bf..d3eeb441 100644 --- a/components/offline_pages/core/offline_page_feature.cc +++ b/components/offline_pages/core/offline_page_feature.cc
@@ -22,10 +22,10 @@ namespace offline_pages { const base::Feature kOfflineBookmarksFeature{"OfflineBookmarks", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kOffliningRecentPagesFeature{ - "OfflineRecentPages", base::FEATURE_DISABLED_BY_DEFAULT}; + "OfflineRecentPages", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kOfflinePagesCTFeature{"OfflinePagesCT", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/components/offline_pages/core/offline_page_model_impl_unittest.cc b/components/offline_pages/core/offline_page_model_impl_unittest.cc index 5e70978..c50c7db 100644 --- a/components/offline_pages/core/offline_page_model_impl_unittest.cc +++ b/components/offline_pages/core/offline_page_model_impl_unittest.cc
@@ -1297,50 +1297,32 @@ } TEST(CommandLineFlagsTest, OfflineBookmarks) { - // Disabled by default. - EXPECT_FALSE(offline_pages::IsOfflineBookmarksEnabled()); - - // Check if feature is correctly enabled by command-line flag. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(kOfflineBookmarksFeature); + // Enabled by default. EXPECT_TRUE(offline_pages::IsOfflineBookmarksEnabled()); + + // Check if feature is correctly disabled by command-line flag. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(kOfflineBookmarksFeature); + EXPECT_FALSE(offline_pages::IsOfflineBookmarksEnabled()); } TEST(CommandLineFlagsTest, OffliningRecentPages) { - // Enable offline bookmarks feature first. - // TODO(dimich): once offline pages are enabled by default, remove this. - std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list( - new base::test::ScopedFeatureList); - scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature); - - // This feature is still disabled by default. - EXPECT_FALSE(offline_pages::IsOffliningRecentPagesEnabled()); - - // Check if feature is correctly enabled by command-line flag. - scoped_feature_list.reset(new base::test::ScopedFeatureList); - scoped_feature_list->InitFromCommandLine( - std::string(kOfflineBookmarksFeature.name) + "," + - kOffliningRecentPagesFeature.name, - ""); + // Enabled by default. EXPECT_TRUE(offline_pages::IsOffliningRecentPagesEnabled()); + + // Check if feature is correctly disabled by command-line flag. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(kOffliningRecentPagesFeature); + EXPECT_FALSE(offline_pages::IsOffliningRecentPagesEnabled()); } TEST(CommandLineFlagsTest, OfflinePagesSharing) { - // Enable offline bookmarks feature first. - // TODO(dimich): once offline pages are enabled by default, remove this. - std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list( - new base::test::ScopedFeatureList); - scoped_feature_list->InitAndEnableFeature(kOfflineBookmarksFeature); - - // This feature is still disabled by default. + // This feature is disabled by default. EXPECT_FALSE(offline_pages::IsOfflinePagesSharingEnabled()); - // Check if feature is correctly enabled by command-line flag. - scoped_feature_list.reset(new base::test::ScopedFeatureList); - scoped_feature_list->InitFromCommandLine( - std::string(kOfflineBookmarksFeature.name) + "," + - kOfflinePagesSharingFeature.name, - ""); + // Check if feature is correctly disabled by command-line flag. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(kOfflinePagesSharingFeature); EXPECT_TRUE(offline_pages::IsOfflinePagesSharingEnabled()); }
diff --git a/components/resources/security_interstitials_resources.grdp b/components/resources/security_interstitials_resources.grdp index 2fb0f05c..4d72526b 100644 --- a/components/resources/security_interstitials_resources.grdp +++ b/components/resources/security_interstitials_resources.grdp
@@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> - <include name="IDR_SECURITY_INTERSTITIAL_UI_HTML" file="../security_interstitials/core/browser/resources/interstitial_ui.html" flattenhtml="true" type="BINDATA" /> - <include name="IDR_SECURITY_INTERSTITIAL_HTML" file="../security_interstitials/core/browser/resources/interstitial_v2.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_SECURITY_INTERSTITIAL_UI_HTML" file="../security_interstitials/core/browser/resources/list_of_interstitials.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_SECURITY_INTERSTITIAL_HTML" file="../security_interstitials/core/browser/resources/interstitial_large.html" flattenhtml="true" type="BINDATA" /> <include name="IDR_SECURITY_INTERSTITIAL_QUIET_HTML" file="../security_interstitials/core/browser/resources/interstitial_webview_quiet.html" flattenhtml="true" type="BINDATA" /> -</grit-part> \ No newline at end of file +</grit-part>
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2.css b/components/security_interstitials/core/browser/resources/interstitial_large.css similarity index 99% rename from components/security_interstitials/core/browser/resources/interstitial_v2.css rename to components/security_interstitials/core/browser/resources/interstitial_large.css index fdda65d..6ca9c0c 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_v2.css +++ b/components/security_interstitials/core/browser/resources/interstitial_large.css
@@ -14,7 +14,6 @@ } button { - -webkit-user-select: none; background: rgb(66, 133, 244); border: 0; border-radius: 2px; @@ -26,6 +25,7 @@ margin: 0; padding: 10px 24px; transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1); + user-select: none; } [dir='rtl'] button {
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2.html b/components/security_interstitials/core/browser/resources/interstitial_large.html similarity index 91% rename from components/security_interstitials/core/browser/resources/interstitial_v2.html rename to components/security_interstitials/core/browser/resources/interstitial_large.html index f382689f..bcb762a 100644 --- a/components/security_interstitials/core/browser/resources/interstitial_v2.html +++ b/components/security_interstitials/core/browser/resources/interstitial_large.html
@@ -6,14 +6,14 @@ content="initial-scale=1, minimum-scale=1, width=device-width"> <title i18n-content="tabTitle"></title> <link rel="stylesheet" href="interstitial_common.css"> - <link rel="stylesheet" href="interstitial_v2.css"> + <link rel="stylesheet" href="interstitial_large.css"> <script src="../../../../../ui/webui/resources/js/util.js"></script> <script src="captive_portal.js"></script> <script src="ssl.js"></script> <script src="extended_reporting.js"></script> - <script src="interstitial_v2_mobile.js"></script> + <script src="interstitial_mobile_nav.js"></script> <script src="interstitial_common.js"></script> - <script src="interstitial_v2.js"></script> + <script src="interstitial_large.js"></script> </head> <body id="body"> <div class="interstitial-wrapper">
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2.js b/components/security_interstitials/core/browser/resources/interstitial_large.js similarity index 100% rename from components/security_interstitials/core/browser/resources/interstitial_v2.js rename to components/security_interstitials/core/browser/resources/interstitial_large.js
diff --git a/components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js b/components/security_interstitials/core/browser/resources/interstitial_mobile_nav.js similarity index 100% rename from components/security_interstitials/core/browser/resources/interstitial_v2_mobile.js rename to components/security_interstitials/core/browser/resources/interstitial_mobile_nav.js
diff --git a/components/security_interstitials/core/browser/resources/interstitial_ui.html b/components/security_interstitials/core/browser/resources/list_of_interstitials.html similarity index 100% rename from components/security_interstitials/core/browser/resources/interstitial_ui.html rename to components/security_interstitials/core/browser/resources/list_of_interstitials.html
diff --git a/content/browser/appcache/appcache_manifest_parser.cc b/content/browser/appcache/appcache_manifest_parser.cc index 8189858a..ca4cb7a 100644 --- a/content/browser/appcache/appcache_manifest_parser.cc +++ b/content/browser/appcache/appcache_manifest_parser.cc
@@ -37,6 +37,7 @@ #include "base/i18n/icu_string_conversions.h" #include "base/logging.h" #include "base/macros.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "url/gurl.h" @@ -57,8 +58,14 @@ return annotation == L"isPattern"; } +bool ScopeMatches(const GURL& manifest_url, const GURL& namespace_url) { + return base::StartsWith(namespace_url.spec(), + manifest_url.Resolve(".").spec(), + base::CompareCase::SENSITIVE); } +} // namespace + enum Mode { EXPLICIT, INTERCEPT, @@ -73,10 +80,7 @@ UNKNOWN_VERB, }; -AppCacheManifest::AppCacheManifest() - : online_whitelist_all(false), - did_ignore_intercept_namespaces(false) { -} +AppCacheManifest::AppCacheManifest() {} AppCacheManifest::~AppCacheManifest() {} @@ -99,6 +103,7 @@ DCHECK(manifest.online_whitelist_namespaces.empty()); DCHECK(!manifest.online_whitelist_all); DCHECK(!manifest.did_ignore_intercept_namespaces); + DCHECK(!manifest.did_ignore_fallback_namespaces); Mode mode = EXPLICIT; @@ -223,7 +228,7 @@ is_pattern)); } } else if (mode == INTERCEPT) { - if (parse_mode != PARSE_MANIFEST_ALLOWING_INTERCEPTS) { + if (parse_mode != PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES) { manifest.did_ignore_intercept_namespaces = true; continue; } @@ -337,6 +342,13 @@ continue; } + if (parse_mode != PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES) { + if (!ScopeMatches(manifest_url, namespace_url)) { + manifest.did_ignore_fallback_namespaces = true; + continue; + } + } + // Skip whitespace separating fallback namespace from URL. while (line_p < line_end && (*line_p == '\t' || *line_p == ' ')) ++line_p;
diff --git a/content/browser/appcache/appcache_manifest_parser.h b/content/browser/appcache/appcache_manifest_parser.h index 19685f8..75f7fe8 100644 --- a/content/browser/appcache/appcache_manifest_parser.h +++ b/content/browser/appcache/appcache_manifest_parser.h
@@ -51,13 +51,14 @@ AppCacheNamespaceVector intercept_namespaces; AppCacheNamespaceVector fallback_namespaces; AppCacheNamespaceVector online_whitelist_namespaces; - bool online_whitelist_all; - bool did_ignore_intercept_namespaces; + bool online_whitelist_all = false; + bool did_ignore_intercept_namespaces = false; + bool did_ignore_fallback_namespaces = false; }; enum ParseMode { PARSE_MANIFEST_PER_STANDARD, - PARSE_MANIFEST_ALLOWING_INTERCEPTS + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES }; CONTENT_EXPORT bool ParseManifest(
diff --git a/content/browser/appcache/appcache_manifest_parser_unittest.cc b/content/browser/appcache/appcache_manifest_parser_unittest.cc index 4f3d2f4c..bd34ef19 100644 --- a/content/browser/appcache/appcache_manifest_parser_unittest.cc +++ b/content/browser/appcache/appcache_manifest_parser_unittest.cc
@@ -19,10 +19,11 @@ TEST(AppCacheManifestParserTest, NoData) { GURL url; AppCacheManifest manifest; - EXPECT_FALSE(ParseManifest(url, "", 0, - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + EXPECT_FALSE(ParseManifest( + url, "", 0, PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest)); EXPECT_FALSE(ParseManifest(url, "CACHE MANIFEST\r", 0, // Len is 0. - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); } TEST(AppCacheManifestParserTest, CheckSignature) { @@ -43,7 +44,8 @@ for (size_t i = 0; i < arraysize(kBadSignatures); ++i) { const std::string bad = kBadSignatures[i]; EXPECT_FALSE(ParseManifest(url, bad.c_str(), bad.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); } const std::string kGoodSignatures[] = { @@ -61,7 +63,8 @@ for (size_t i = 0; i < arraysize(kGoodSignatures); ++i) { const std::string good = kGoodSignatures[i]; EXPECT_TRUE(ParseManifest(url, good.c_str(), good.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); } } @@ -72,7 +75,8 @@ "http://absolute.com/addme.com"); const GURL kUrl; EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.explicit_urls.empty()); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); @@ -100,10 +104,13 @@ "*\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); base::hash_set<std::string> urls = manifest.explicit_urls; const size_t kExpected = 5; @@ -116,13 +123,15 @@ // Wildcard is treated as a relative URL in explicit section. EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end()); - // We should get the same results with intercepts disallowed. + // We should get the same results with dangerous features disallowed. manifest = AppCacheManifest(); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), PARSE_MANIFEST_PER_STANDARD, manifest)); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); urls = manifest.explicit_urls; ASSERT_EQ(kExpected, urls.size()); @@ -156,11 +165,14 @@ "*foo\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.explicit_urls.empty()); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.intercept_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); const AppCacheNamespaceVector& online = manifest.online_whitelist_namespaces; const size_t kExpected = 6; @@ -203,10 +215,13 @@ "http://www.glorp.com/notsame relative/skipped\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.explicit_urls.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); const AppCacheNamespaceVector& fallbacks = manifest.fallback_namespaces; const size_t kExpected = 5; @@ -236,8 +251,14 @@ fallbacks[4].namespace_url); EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"), fallbacks[4].target_url); - EXPECT_TRUE(manifest.intercept_namespaces.empty()); + + // Nothing should be ignored since all namespaces are in scope. + manifest = AppCacheManifest(); + EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), + PARSE_MANIFEST_PER_STANDARD, manifest)); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); } TEST(AppCacheManifestParserTest, FallbackUrlsWithPort) { @@ -254,7 +275,8 @@ "http://www.portme.com:1234/skipme http://www.portme.com/noport\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.explicit_urls.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); @@ -277,8 +299,14 @@ fallbacks[2].namespace_url); EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"), fallbacks[2].target_url); - EXPECT_TRUE(manifest.intercept_namespaces.empty()); + + // Nothing should be ignored since all namespaces are in scope. + manifest = AppCacheManifest(); + EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), + PARSE_MANIFEST_PER_STANDARD, manifest)); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); } TEST(AppCacheManifestParserTest, InterceptUrls) { @@ -297,11 +325,14 @@ "relative/wrong/again missing/intercept_type\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.explicit_urls.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); const AppCacheNamespaceVector& intercepts = manifest.intercept_namespaces; const size_t kExpected = 3; @@ -322,7 +353,7 @@ EXPECT_EQ(GURL("http://www.portme.com:1234/int3"), intercepts[2].target_url); - // Disallow intercepts ths time. + // Disallow intercepts this time. manifest = AppCacheManifest(); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), PARSE_MANIFEST_PER_STANDARD, manifest)); @@ -331,6 +362,8 @@ EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); EXPECT_TRUE(manifest.intercept_namespaces.empty()); EXPECT_FALSE(manifest.online_whitelist_all); + EXPECT_TRUE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); } TEST(AppCacheManifestParserTest, ComboUrls) { @@ -356,7 +389,8 @@ "relative/whitelist-3#strip\r" "http://combo.com:99/whitelist-4\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.online_whitelist_all); base::hash_set<std::string> urls = manifest.explicit_urls; @@ -403,7 +437,8 @@ "\xC0" "invalidutf8\r" "nonbmp" "\xF1\x84\xAB\xBC\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); base::hash_set<std::string> urls = manifest.explicit_urls; EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end()); EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end()); @@ -416,7 +451,8 @@ "CACHE MANIFEST\r" "resource.txt this stuff after the white space should be ignored\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); base::hash_set<std::string> urls = manifest.explicit_urls; EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end()); @@ -433,7 +469,8 @@ "https://www.xyz.com/secureschemedifforigin\r"); EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.fallback_namespaces.empty()); EXPECT_TRUE(manifest.online_whitelist_namespaces.empty()); @@ -470,10 +507,12 @@ AppCacheManifest manifest; - EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(), - kManifestBody.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + EXPECT_TRUE(ParseManifest(kUrl, kManifestBody.c_str(), kManifestBody.length(), + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); EXPECT_TRUE(manifest.online_whitelist_all); + EXPECT_FALSE(manifest.did_ignore_intercept_namespaces); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); EXPECT_EQ(1u, manifest.explicit_urls.size()); EXPECT_EQ(3u, manifest.intercept_namespaces.size()); EXPECT_EQ(2u, manifest.fallback_namespaces.size()); @@ -516,4 +555,31 @@ manifest.online_whitelist_namespaces[1].target_url); } +TEST(AppCacheManifestParserTest, IgnoreDangerousFallbacks) { + const GURL kUrl("http://foo.com/scope/manifest?with_query_args"); + const std::string kData( + "CACHE MANIFEST\r" + "FALLBACK:\r" + "http://foo.com/scope/ fallback_url\r" + "http://foo.com/out_of_scope/ fallback_url\r"); + + // Scope matching depends on resolving "." as a relative url. + EXPECT_EQ(kUrl.Resolve(".").spec(), std::string("http://foo.com/scope/")); + + AppCacheManifest manifest; + EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); + EXPECT_FALSE(manifest.did_ignore_fallback_namespaces); + EXPECT_EQ(2u, manifest.fallback_namespaces.size()); + + manifest = AppCacheManifest(); + EXPECT_TRUE(ParseManifest(kUrl, kData.c_str(), kData.length(), + PARSE_MANIFEST_PER_STANDARD, manifest)); + EXPECT_TRUE(manifest.did_ignore_fallback_namespaces); + EXPECT_EQ(1u, manifest.fallback_namespaces.size()); + EXPECT_EQ(GURL("http://foo.com/scope/"), + manifest.fallback_namespaces[0].namespace_url); +} + } // namespace content
diff --git a/content/browser/appcache/appcache_unittest.cc b/content/browser/appcache/appcache_unittest.cc index 6bf5d79..42bf790 100644 --- a/content/browser/appcache/appcache_unittest.cc +++ b/content/browser/appcache/appcache_unittest.cc
@@ -565,7 +565,8 @@ scoped_refptr<AppCache> cache(new AppCache(service.storage(), kCacheId)); AppCacheManifest manifest; EXPECT_TRUE(ParseManifest(kManifestUrl, kData.c_str(), kData.length(), - PARSE_MANIFEST_ALLOWING_INTERCEPTS, manifest)); + PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, + manifest)); cache->InitializeWithManifest(&manifest); EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, cache->online_whitelist_namespaces_[0].type);
diff --git a/content/browser/appcache/appcache_update_job.cc b/content/browser/appcache/appcache_update_job.cc index e4f50ea2..ec16a5a 100644 --- a/content/browser/appcache/appcache_update_job.cc +++ b/content/browser/appcache/appcache_update_job.cc
@@ -712,9 +712,9 @@ AppCacheManifest manifest; if (!ParseManifest(manifest_url_, manifest_data_.data(), manifest_data_.length(), - manifest_has_valid_mime_type_ ? - PARSE_MANIFEST_ALLOWING_INTERCEPTS : - PARSE_MANIFEST_PER_STANDARD, + manifest_has_valid_mime_type_ + ? PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES + : PARSE_MANIFEST_PER_STANDARD, manifest)) { const char kFormatString[] = "Failed to parse manifest %s"; const std::string message = base::StringPrintf(kFormatString, @@ -746,13 +746,20 @@ } } + // Warn about dangerous features being ignored due to the wrong content-type + // Must be done after associating all pending master hosts. if (manifest.did_ignore_intercept_namespaces) { - // Must be done after associating all pending master hosts. std::string message( "Ignoring the INTERCEPT section of the application cache manifest " "because the content type is not text/cache-manifest"); LogConsoleMessageToAll(message); } + if (manifest.did_ignore_fallback_namespaces) { + std::string message( + "Ignoring out of scope FALLBACK entries of the application cache " + "manifest because the content-type is not text/cache-manifest"); + LogConsoleMessageToAll(message); + } group_->SetUpdateAppCacheStatus(AppCacheGroup::DOWNLOADING); NotifyAllAssociatedHosts(APPCACHE_DOWNLOADING_EVENT);
diff --git a/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/content/browser/frame_host/navigation_handle_impl_browsertest.cc index 4bd9d50..d8ffc005 100644 --- a/content/browser/frame_host/navigation_handle_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -1079,6 +1079,31 @@ } } +// Checks that there's no UAF if NavigationHandleImpl::WillStartRequest cancels +// the navigation. +IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, + CancelNavigationInWillStartRequest) { + const GURL kUrl1 = embedded_test_server()->GetURL("/title1.html"); + const GURL kUrl2 = embedded_test_server()->GetURL("/title2.html"); + // First make a successful commit, as this issue only reproduces when there + // are existing entries (i.e. when NavigationControllerImpl::GetVisibleEntry + // has safe_to_show_pending=false). + EXPECT_TRUE(NavigateToURL(shell(), kUrl1)); + + // To take the path that doesn't run beforeunload, so that + // NavigationControllerImpl::NavigateToPendingEntry is on the botttom of the + // stack when NavigationHandleImpl::WillStartRequest is called. + CrashTab(shell()->web_contents()); + + // Set up a NavigationThrottle that will cancel the navigation in + // WillStartRequest. + TestNavigationThrottleInstaller installer( + shell()->web_contents(), NavigationThrottle::CANCEL_AND_IGNORE, + NavigationThrottle::PROCEED, NavigationThrottle::PROCEED); + + EXPECT_FALSE(NavigateToURL(shell(), kUrl2)); +} + // Specialized test that verifies the NavigationHandle gets the HTTPS upgraded // URL from the very beginning of the navigation. class NavigationHandleImplHttpsUpgradeBrowserTest
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index dee3a58..521b288 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -28,6 +28,7 @@ #include "content/common/appcache_interfaces.h" #include "content/common/resource_request_body_impl.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/navigation_controller.h" @@ -322,7 +323,8 @@ bindings_(NavigationEntryImpl::kInvalidBindings), response_should_be_rendered_(true), associated_site_instance_type_(AssociatedSiteInstanceType::NONE), - may_transfer_(may_transfer) { + may_transfer_(may_transfer), + weak_factory_(this) { DCHECK(!browser_initiated || (entry != nullptr && frame_entry != nullptr)); TRACE_EVENT_ASYNC_BEGIN2("navigation", "NavigationRequest", this, "frame_tree_node", @@ -738,21 +740,26 @@ if (on_start_checks_complete_closure_) on_start_checks_complete_closure_.Run(); - // Abort the request if needed. This will destroy the NavigationRequest. if (result == NavigationThrottle::CANCEL_AND_IGNORE || - result == NavigationThrottle::CANCEL) { - // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE. - OnRequestFailed(false, net::ERR_ABORTED); - - // DO NOT ADD CODE after this. The previous call to OnRequestFailed has - // destroyed the NavigationRequest. - return; - } - - if (result == NavigationThrottle::BLOCK_REQUEST || + result == NavigationThrottle::CANCEL || + result == NavigationThrottle::BLOCK_REQUEST || result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { - OnRequestFailed(false, net::ERR_BLOCKED_BY_CLIENT); + // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE. + int error_code = net::ERR_ABORTED; + if (result == NavigationThrottle::BLOCK_REQUEST || + result == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) { + error_code = net::ERR_BLOCKED_BY_CLIENT; + } + + // If the start checks completed synchronously, which could happen if there + // is no onbeforeunload handler or if a NavigationThrottle cancelled it, + // then this could cause reentrancy into NavigationController. So use a + // PostTask to avoid that. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::Bind(&NavigationRequest::OnRequestFailed, + weak_factory_.GetWeakPtr(), false, error_code)); // DO NOT ADD CODE after this. The previous call to OnRequestFailed has // destroyed the NavigationRequest.
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 9024de2..7e90d70 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -10,6 +10,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "content/browser/frame_host/navigation_entry_impl.h" #include "content/browser/loader/navigation_url_loader_delegate.h" #include "content/common/content_export.h" @@ -285,6 +286,8 @@ base::Closure on_start_checks_complete_closure_; + base::WeakPtrFactory<NavigationRequest> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(NavigationRequest); };
diff --git a/content/browser/web_contents/aura/shadow_layer_delegate.cc b/content/browser/web_contents/aura/shadow_layer_delegate.cc index 84ef3f68..07be1c2 100644 --- a/content/browser/web_contents/aura/shadow_layer_delegate.cc +++ b/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -45,9 +45,9 @@ gfx::Rect paint_rect = gfx::Rect(0, 0, kShadowThick, layer_->bounds().height()); cc::PaintFlags flags; - flags.setShader(cc::WrapSkShader(SkGradientShader::MakeLinear( - points, kShadowColors, NULL, arraysize(points), - SkShader::kRepeat_TileMode))); + flags.setShader(cc::PaintShader::MakeLinearGradient( + points, kShadowColors, nullptr, arraysize(points), + SkShader::kRepeat_TileMode)); ui::PaintRecorder recorder(context, layer_->size()); recorder.canvas()->DrawRect(paint_rect, flags); }
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc index 16abd8c9..5a261cae 100644 --- a/content/child/blink_platform_impl.cc +++ b/content/child/blink_platform_impl.cc
@@ -606,6 +606,7 @@ {"colorSuggestionPicker.css", IDR_COLOR_SUGGESTION_PICKER_CSS, ui::SCALE_FACTOR_NONE, true}, #endif + {"placeholderIcon", IDR_PLACEHOLDER_ICON, ui::SCALE_FACTOR_100P, false}, }; } // namespace
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index a349241..90e1e69 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -80,6 +80,8 @@ #if defined(OS_MACOSX) #include "base/allocator/allocator_interception_mac.h" +#include "base/process/process.h" +#include "content/common/mac/app_nap_activity.h" #endif using tracked_objects::ThreadData; @@ -563,6 +565,10 @@ switches::kEnableHeapProfiling)) { base::allocator::PeriodicallyShimNewMallocZones(); } + if (base::Process::IsAppNapEnabled()) { + app_nap_activity_.reset(new AppNapActivity()); + app_nap_activity_->Begin(); + }; #endif message_loop_->task_runner()->PostDelayedTask( @@ -757,6 +763,15 @@ if (backgrounded) timer_slack = base::TIMER_SLACK_MAXIMUM; base::MessageLoop::current()->SetTimerSlack(timer_slack); +#if defined(OS_MACOSX) + if (base::Process::IsAppNapEnabled()) { + if (backgrounded) { + app_nap_activity_->End(); + } else { + app_nap_activity_->Begin(); + } + } +#endif // defined(OS_MACOSX) } void ChildThreadImpl::OnProcessPurgeAndSuspend() {
diff --git a/content/child/child_thread_impl.h b/content/child/child_thread_impl.h index a7e2cd2..ab9a4ec 100644 --- a/content/child/child_thread_impl.h +++ b/content/child/child_thread_impl.h
@@ -59,6 +59,10 @@ class ResourceDispatcher; class ThreadSafeSender; +#if defined(OS_MACOSX) +class AppNapActivity; +#endif + // The main thread of a child process derives from this class. class CONTENT_EXPORT ChildThreadImpl : public IPC::Listener, @@ -281,6 +285,10 @@ scoped_refptr<base::SingleThreadTaskRunner> browser_process_io_runner_; +#if defined(OS_MACOSX) + std::unique_ptr<AppNapActivity> app_nap_activity_; +#endif // defined(OS_MACOSX) + std::unique_ptr<base::WeakPtrFactory<ChildThreadImpl>> channel_connected_factory_;
diff --git a/content/common/mac/app_nap_activity.h b/content/common/mac/app_nap_activity.h index c07f9ee8..c2896e8 100644 --- a/content/common/mac/app_nap_activity.h +++ b/content/common/mac/app_nap_activity.h
@@ -27,6 +27,10 @@ AppNapActivity(); ~AppNapActivity(); + // Because there's no NSApplication in renderers, do some housekeeping + // to become eligible for App Nap. + static void InitializeAppNapSupport(); + // Begin an activity and store the provided token. void Begin();
diff --git a/content/common/mac/app_nap_activity.mm b/content/common/mac/app_nap_activity.mm index d2c82e8..4fa7b58 100644 --- a/content/common/mac/app_nap_activity.mm +++ b/content/common/mac/app_nap_activity.mm
@@ -8,6 +8,12 @@ #include "base/mac/scoped_nsobject.h" +extern "C" { +void __CFRunLoopSetOptionsReason(uint64_t options, + NSString* reason, + int unused); +} + namespace content { namespace { @@ -33,6 +39,21 @@ DCHECK(!assertion_->obj.get()); }; +void AppNapActivity::InitializeAppNapSupport() { + // Reason strings are the same as + // what macOS sends in the corresponding call. + // |options| (argument 1) are magic numbers as found in the + // callsites mentioned above. + // + // Normally happens during launch services check-in. (HIToolbox) + __CFRunLoopSetOptionsReason( + 1, @"Finished checking in as application - waiting for events", 0); + // Normally happens in a dispatch_once in the NSApplication event loop. + // (CoreFoundation). + __CFRunLoopSetOptionsReason( + 0x3b000000, @"Finished delay after app launch and bundle check", 0); +} + void AppNapActivity::Begin() { DCHECK(!assertion_->obj.get()); id assertion =
diff --git a/content/public/browser/browser_thread.h b/content/public/browser/browser_thread.h index 77b2f00a..47bcbfc8 100644 --- a/content/public/browser/browser_thread.h +++ b/content/public/browser/browser_thread.h
@@ -316,7 +316,8 @@ // std::unique_ptr<Foo, BrowserThread::DeleteOnIOThread> ptr; // // Note: when migrating BrowserThreads to TaskScheduler based - // SequencedTaskRunners these map to base::OnTaskRunnerDeleter. + // SequencedTaskRunners these map to base::OnTaskRunnerDeleter and + // base::RefCountedDeleteOnSequence. struct DeleteOnUIThread : public DeleteOnThread<UI> { }; struct DeleteOnIOThread : public DeleteOnThread<IO> { }; struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
diff --git a/content/public/test/navigation_simulator.cc b/content/public/test/navigation_simulator.cc index fa2bc91f..8a7db8a 100644 --- a/content/public/test/navigation_simulator.cc +++ b/content/public/test/navigation_simulator.cc
@@ -556,13 +556,18 @@ void NavigationSimulator::WaitForThrottleChecksComplete() { // If last_throttle_check_result_ is set, then throttle checks completed // synchronously. - if (last_throttle_check_result_) - return; + if (!last_throttle_check_result_) { + base::RunLoop run_loop; + throttle_checks_wait_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + throttle_checks_wait_closure_.Reset(); + } - base::RunLoop run_loop; - throttle_checks_wait_closure_ = run_loop.QuitClosure(); - run_loop.Run(); - throttle_checks_wait_closure_.Reset(); + if (IsBrowserSideNavigationEnabled()) { + // Run message loop once since NavigationRequest::OnStartChecksComplete + // posted a task. + base::RunLoop().RunUntilIdle(); + } } void NavigationSimulator::OnThrottleChecksComplete(
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 3c12a32..46e340a 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -189,6 +189,8 @@ #if defined(OS_MACOSX) #include "base/mac/mac_util.h" +#include "base/process/process.h" +#include "content/common/mac/app_nap_activity.h" #include "content/renderer/theme_helper_mac.h" #include "content/renderer/webscrollbarbehavior_impl_mac.h" #endif @@ -809,6 +811,10 @@ Boolean value = CFPreferencesGetAppBooleanValue( key, kCFPreferencesCurrentApplication, &key_exists); is_elastic_overscroll_enabled_ = !key_exists || value; + + if (base::Process::IsAppNapEnabled()) { + AppNapActivity::InitializeAppNapSupport(); + } #else is_elastic_overscroll_enabled_ = false; #endif
diff --git a/content/test/gpu/gpu_tests/gpu_process_integration_test.py b/content/test/gpu/gpu_tests/gpu_process_integration_test.py index fc29dfc3..b2be86f 100644 --- a/content/test/gpu/gpu_tests/gpu_process_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_process_integration_test.py
@@ -559,6 +559,7 @@ 'WEBGL_debug_shaders', 'WEBGL_depth_texture', 'WEBKIT_WEBGL_depth_texture', + 'WEBGL_draw_buffers', 'WEBGL_lose_context', 'WEBKIT_WEBGL_lose_context', ]
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index a7b4c5c..ce36682 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -109,34 +109,14 @@ bug=1966) # angle bug ID # Passthrough command decoder - self.Fail('conformance/extensions/ext-sRGB.html', - ['passthrough'], bug=679696) self.Fail('conformance/extensions/webgl-draw-buffers.html', ['passthrough'], bug=1523) # angle bug ID self.Fail('conformance/glsl/misc/shaders-with-name-conflicts.html', ['passthrough'], bug=1639) # angle bug ID - self.Fail('conformance/misc/invalid-passed-params.html', - ['passthrough'], bug=1639) # angle bug ID self.Fail('conformance/misc/uninitialized-test.html', ['passthrough'], bug=1635) # angle bug ID self.Fail('conformance/reading/read-pixels-test.html', ['passthrough'], bug=1639) # angle bug ID - self.Fail('conformance/renderbuffers/renderbuffer-initialization.html', - ['passthrough'], bug=1635) # angle bug ID - self.Fail('conformance/textures/misc/texture-mips.html', - ['passthrough'], bug=665518) - self.Skip('conformance/textures/canvas/*', - ['passthrough'], bug=1932) # angle bug ID - self.Skip('conformance/textures/video/*', - ['passthrough'], bug=1932) # angle bug ID - self.Skip('conformance/textures/image_bitmap_from_canvas/*', - ['passthrough'], bug=1932) # angle bug ID - self.Skip('conformance/textures/webgl_canvas/*', - ['passthrough'], bug=1932) # angle bug ID - self.Skip('conformance/extensions/oes-texture-float-with-canvas.html', - ['passthrough'], bug=1932) # angle bug ID - self.Skip('conformance/extensions/oes-texture-float-with-video.html', - ['passthrough'], bug=1932) # angle bug ID # Passthrough command decoder / OpenGL self.Fail('conformance/buffers/buffer-uninitialized.html', @@ -148,6 +128,12 @@ ['passthrough', 'opengl'], bug=665521) self.Fail('conformance/renderbuffers/framebuffer-test.html', ['passthrough', 'opengl'], bug=665521) + self.Fail('conformance/textures/canvas/*', + ['passthrough', 'opengl'], bug=1932) # angle bug ID + self.Fail('conformance/textures/image_bitmap_from_canvas/*', + ['passthrough', 'opengl'], bug=1932) # angle bug ID + self.Fail('conformance/textures/webgl_canvas/*', + ['passthrough', 'opengl'], bug=1932) # angle bug ID self.Fail('conformance/textures/misc/copy-tex-image-and-sub-image-2d.html', ['passthrough', 'opengl'], bug=665521) self.Fail('conformance/textures/misc/copytexsubimage2d-subrects.html', @@ -158,6 +144,10 @@ ['passthrough', 'opengl'], bug=665521) self.Fail('conformance/textures/misc/texture-fakeblack.html', ['passthrough', 'opengl'], bug=665521) + self.Fail('conformance/textures/misc/texture-mips.html', + ['passthrough', 'opengl'], bug=665518) + self.Fail('conformance/extensions/oes-texture-float-with-canvas.html', + ['passthrough', 'opengl'], bug=1932) # angle bug ID # Passthrough command decoder / OpenGL / Intel self.Fail('conformance/renderbuffers/framebuffer-object-attachment.html', @@ -192,12 +182,18 @@ # Passthrough command decoder / D3D11 self.Fail('conformance/glsl/misc/shaders-with-uniform-structs.html', ['passthrough', 'd3d11'], bug=1639) # angle bug ID - self.Fail('conformance/renderbuffers/framebuffer-object-attachment.html', - ['passthrough', 'd3d11'], bug=602688) self.Fail('conformance/textures/misc/copy-tex-image-and-sub-image-2d.html', ['passthrough', 'd3d11'], bug=1639) # angle bug ID - self.Fail('conformance/textures/misc/texture-attachment-formats.html', - ['passthrough', 'd3d11'], bug=602688) + self.Fail('conformance/textures/canvas/' + + 'tex-2d-rgb-rgb-unsigned_short_5_6_5.html', + ['passthrough', 'd3d11'], bug=1635) # angle bug ID + self.Fail('conformance/textures/canvas/' + + 'tex-2d-rgb-rgb-unsigned_byte.html', + ['passthrough', 'd3d11'], bug=1635) # angle bug ID + self.Fail('conformance/textures/misc/gl-teximage.html', + ['passthrough', 'd3d11'], bug=1635) # angle bug ID + self.Fail('conformance/textures/misc/texture-mips.html', + ['passthrough', 'd3d11'], bug=1635) # angle bug ID # Win / AMD / Passthrough command decoder / D3D11 self.Flaky('conformance/textures/misc/copytexsubimage2d-subrects.html',
diff --git a/crypto/apple_keychain.h b/crypto/apple_keychain.h index 1037b7e..ca681df 100644 --- a/crypto/apple_keychain.h +++ b/crypto/apple_keychain.h
@@ -54,50 +54,7 @@ SecKeychainItemRef* itemRef) const; #if !defined(OS_IOS) - virtual OSStatus ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const; - - virtual OSStatus ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const; - - virtual OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, - void* data) const; - virtual OSStatus ItemDelete(SecKeychainItemRef itemRef) const; - - virtual OSStatus SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const; - - virtual OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const; - - virtual OSStatus AddInternetPassword(SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, const char* path, - UInt16 port, SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const; - - // Calls CFRelease on the given ref, after checking that |ref| is non-NULL. - virtual void Free(CFTypeRef ref) const; #endif // !defined(OS_IOS) private:
diff --git a/crypto/apple_keychain_mac.mm b/crypto/apple_keychain_mac.mm index ff5fa3a..a3620485 100644 --- a/crypto/apple_keychain_mac.mm +++ b/crypto/apple_keychain_mac.mm
@@ -15,93 +15,11 @@ AppleKeychain::~AppleKeychain() {} -OSStatus AppleKeychain::ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemCopyAttributesAndData(itemRef, info, itemClass, - attrList, length, outData); -} - -OSStatus AppleKeychain::ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemModifyAttributesAndData(itemRef, attrList, length, - data); -} - -OSStatus AppleKeychain::ItemFreeAttributesAndData( - SecKeychainAttributeList* attrList, - void* data) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainItemFreeAttributesAndData(attrList, data); -} - OSStatus AppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { base::AutoLock lock(GetMacSecurityServicesLock()); return SecKeychainItemDelete(itemRef); } -OSStatus AppleKeychain::SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); -// Eventually, this deprecated method should be removed entirely. -// https://crbug.com/595468 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - return SecKeychainSearchCreateFromAttributes(keychainOrArray, itemClass, - attrList, searchRef); -#pragma clang diagnostic pop -} - -OSStatus AppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); -// Eventually, this deprecated method should be removed entirely. -// https://crbug.com/595468 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - return SecKeychainSearchCopyNext(searchRef, itemRef); -#pragma clang diagnostic pop -} - -OSStatus AppleKeychain::AddInternetPassword( - SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - base::AutoLock lock(GetMacSecurityServicesLock()); - return SecKeychainAddInternetPassword(keychain, - serverNameLength, serverName, - securityDomainLength, securityDomain, - accountNameLength, accountName, - pathLength, path, - port, protocol, authenticationType, - passwordLength, passwordData, - itemRef); -} - OSStatus AppleKeychain::FindGenericPassword(CFTypeRef keychainOrArray, UInt32 serviceNameLength, const char* serviceName, @@ -146,9 +64,4 @@ itemRef); } -void AppleKeychain::Free(CFTypeRef ref) const { - if (ref) - CFRelease(ref); -} - } // namespace crypto
diff --git a/crypto/mock_apple_keychain.cc b/crypto/mock_apple_keychain.cc index f73ba24..173cfa7 100644 --- a/crypto/mock_apple_keychain.cc +++ b/crypto/mock_apple_keychain.cc
@@ -72,9 +72,6 @@ DCHECK_GT(passwordLength, 0U); DCHECK(passwordData); - add_generic_password_ = - std::string(const_cast<char*>(static_cast<const char*>(passwordData)), - passwordLength); return noErr; }
diff --git a/crypto/mock_apple_keychain.h b/crypto/mock_apple_keychain.h index 38e69f2..b256a22 100644 --- a/crypto/mock_apple_keychain.h +++ b/crypto/mock_apple_keychain.h
@@ -19,9 +19,7 @@ namespace crypto { // Mock Keychain wrapper for testing code that interacts with the OS X -// Keychain. Implemented by storing SecKeychainAttributeList and -// KeychainPasswordData values in separate mutable containers and -// mapping them to integer keys. +// Keychain. // // Note that "const" is pretty much meaningless for this class; the const-ness // of AppleKeychain doesn't apply to the actual keychain data, so all of the @@ -56,71 +54,7 @@ std::string GetEncryptionPassword() const; #if !defined(OS_IOS) - OSStatus ItemCopyAttributesAndData(SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const override; - // Pass "fail_me" as the data to get errSecAuthFailed. - OSStatus ItemModifyAttributesAndData(SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const override; - OSStatus ItemFreeAttributesAndData(SecKeychainAttributeList* attrList, - void* data) const override; OSStatus ItemDelete(SecKeychainItemRef itemRef) const override; - OSStatus SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const override; - OSStatus SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const override; - // Pass "some.domain.com" as the serverName to get errSecDuplicateItem. - OSStatus AddInternetPassword(SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const override; - void Free(CFTypeRef ref) const override; - - // Return the counts of objects returned by Create/Copy functions but never - // Free'd as they should have been. - int UnfreedSearchCount() const; - int UnfreedKeychainItemCount() const; - int UnfreedAttributeDataCount() const; - - // Returns true if all items added with AddInternetPassword have a creator - // code set. - bool CreatorCodesSetForAddedItems() const; - - struct KeychainTestData { - const SecAuthenticationType auth_type; - const char* server; - const SecProtocolType protocol; - const char* path; - const UInt32 port; - const char* security_domain; - const char* creation_date; - const char* username; - const char* password; - const bool negative_item; - }; - // Adds a keychain item with the given info to the test set. - void AddTestItem(const KeychainTestData& item_data); - - void set_locked(bool locked) { locked_ = locked; } #endif // !defined(OS_IOS) // |FindGenericPassword()| can return different results depending on user @@ -135,109 +69,10 @@ // Returns the true if |AddGenericPassword()| was called. bool called_add_generic() const { return called_add_generic_; } - // Returns the value of the password set when |AddGenericPassword()| was - // called. - std::string add_generic_password() const { return add_generic_password_; } - // Returns the number of allocations - deallocations for password data. int password_data_count() const { return password_data_count_; } private: - // Type used for the keys in the std::map(s) and MockAppleKeychain items. - typedef uintptr_t MockKeychainItemType; - - // Type of the map holding the mock keychain attributes. - typedef std::map<MockKeychainItemType, SecKeychainAttributeList> - MockKeychainAttributesMap; - -#if !defined(OS_IOS) - // Returns true if the keychain already contains a password that matches the - // attributes provided. - bool AlreadyContainsInternetPassword( - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType) const; - // Initializes storage for keychain data at |key|. - void InitializeKeychainData(MockKeychainItemType key) const; - // Sets the data and length of |tag| in the item-th test item. - void SetTestDataBytes( - MockKeychainItemType item, - UInt32 tag, - const void* data, - size_t length); - // Sets the data and length of |tag| in the item-th test item based on - // |value|. The null-terminator will not be included; the Keychain Services - // docs don't indicate whether it is or not, so clients should not assume - // that it will be. - void SetTestDataString(MockKeychainItemType item, - UInt32 tag, - const char* value); - // Sets the data of the corresponding attribute of the item-th test item to - // |value|. Assumes that the space has alread been allocated, and the length - // set. - void SetTestDataPort(MockKeychainItemType item, UInt32 value); - void SetTestDataProtocol(MockKeychainItemType item, SecProtocolType value); - void SetTestDataAuthType(MockKeychainItemType item, - SecAuthenticationType value); - void SetTestDataNegativeItem(MockKeychainItemType item, Boolean value); - void SetTestDataCreator(MockKeychainItemType item, OSType value); - // Sets the password data and length for the item-th test item. - void SetTestDataPasswordBytes(MockKeychainItemType item, - const void* data, - size_t length); - // Sets the password for the item-th test item. As with SetTestDataString, - // the data will not be null-terminated. - void SetTestDataPasswordString(MockKeychainItemType item, const char* value); - - // Returns the address of the attribute in attribute_list with tag |tag|. - static SecKeychainAttribute* AttributeWithTag( - const SecKeychainAttributeList& attribute_list, - UInt32 tag); - - static const SecKeychainSearchRef kDummySearchRef; - - // Simulates the state when the user refuses to unclock the Keychain. - // If true, reading and modifying a password value result in errSecAuthFailed. - bool locked_; - - typedef struct KeychainPasswordData { - KeychainPasswordData() : data(nullptr), length(0) {} - void* data; - UInt32 length; - } KeychainPasswordData; - - // Mutable because the MockAppleKeychain API requires its internal keychain - // storage to be modifiable by users of this class. - mutable MockKeychainAttributesMap keychain_attr_list_; - mutable std::map<MockKeychainItemType, - KeychainPasswordData> keychain_data_; - mutable MockKeychainItemType next_item_key_; - - // Tracks the items that should be returned in subsequent calls to - // SearchCopyNext, based on the last call to SearchCreateFromAttributes. - // We can't handle multiple active searches, since we don't track the search - // ref we return, but we don't need to for our mocking. - mutable std::vector<MockKeychainItemType> remaining_search_results_; - - // Track copies and releases to make sure they balance. Really these should - // be maps to track per item, but this should be good enough to catch - // real mistakes. - mutable int search_copy_count_; - mutable int keychain_item_copy_count_; - mutable int attribute_data_copy_count_; - - // Tracks which items (by key) were added with AddInternetPassword. - mutable std::set<MockKeychainItemType> added_via_api_; -#endif // !defined(OS_IOS) - // Result code for the |FindGenericPassword()| method. OSStatus find_generic_result_; @@ -248,8 +83,7 @@ // and |ItemFreeContent|. mutable int password_data_count_; - // Records the password being set when |AddGenericPassword()| gets called. - mutable std::string add_generic_password_; + DISALLOW_COPY_AND_ASSIGN(MockAppleKeychain); }; } // namespace crypto
diff --git a/crypto/mock_apple_keychain_mac.cc b/crypto/mock_apple_keychain_mac.cc index e4bc30c..43a3410b3 100644 --- a/crypto/mock_apple_keychain_mac.cc +++ b/crypto/mock_apple_keychain_mac.cc
@@ -11,512 +11,15 @@ namespace crypto { -// static -const SecKeychainSearchRef MockAppleKeychain::kDummySearchRef = - reinterpret_cast<SecKeychainSearchRef>(1000); - MockAppleKeychain::MockAppleKeychain() - : locked_(false), - next_item_key_(0), - search_copy_count_(0), - keychain_item_copy_count_(0), - attribute_data_copy_count_(0), - find_generic_result_(noErr), + : find_generic_result_(noErr), called_add_generic_(false), password_data_count_(0) {} -void MockAppleKeychain::InitializeKeychainData(MockKeychainItemType key) const { - UInt32 tags[] = { kSecAccountItemAttr, - kSecServerItemAttr, - kSecPortItemAttr, - kSecPathItemAttr, - kSecProtocolItemAttr, - kSecAuthenticationTypeItemAttr, - kSecSecurityDomainItemAttr, - kSecCreationDateItemAttr, - kSecNegativeItemAttr, - kSecCreatorItemAttr }; - keychain_attr_list_[key] = SecKeychainAttributeList(); - keychain_data_[key] = KeychainPasswordData(); - keychain_attr_list_[key].count = arraysize(tags); - keychain_attr_list_[key].attr = static_cast<SecKeychainAttribute*>( - calloc(keychain_attr_list_[key].count, sizeof(SecKeychainAttribute))); - for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { - keychain_attr_list_[key].attr[i].tag = tags[i]; - size_t data_size = 0; - switch (tags[i]) { - case kSecPortItemAttr: - data_size = sizeof(UInt32); - break; - case kSecProtocolItemAttr: - data_size = sizeof(SecProtocolType); - break; - case kSecAuthenticationTypeItemAttr: - data_size = sizeof(SecAuthenticationType); - break; - case kSecNegativeItemAttr: - data_size = sizeof(Boolean); - break; - case kSecCreatorItemAttr: - data_size = sizeof(OSType); - break; - } - if (data_size > 0) { - keychain_attr_list_[key].attr[i].length = data_size; - keychain_attr_list_[key].attr[i].data = calloc(1, data_size); - } - } -} - -MockAppleKeychain::~MockAppleKeychain() { - for (MockKeychainAttributesMap::iterator it = keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - for (unsigned int i = 0; i < it->second.count; ++i) { - if (it->second.attr[i].data) - free(it->second.attr[i].data); - } - free(it->second.attr); - if (keychain_data_[it->first].data) - free(keychain_data_[it->first].data); - } - keychain_attr_list_.clear(); - keychain_data_.clear(); -} - -SecKeychainAttribute* MockAppleKeychain::AttributeWithTag( - const SecKeychainAttributeList& attribute_list, - UInt32 tag) { - int attribute_index = -1; - for (unsigned int i = 0; i < attribute_list.count; ++i) { - if (attribute_list.attr[i].tag == tag) { - attribute_index = i; - break; - } - } - if (attribute_index == -1) { - NOTREACHED() << "Unsupported attribute: " << tag; - return NULL; - } - return &(attribute_list.attr[attribute_index]); -} - -void MockAppleKeychain::SetTestDataBytes(MockKeychainItemType item, - UInt32 tag, - const void* data, - size_t length) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - tag); - attribute->length = length; - if (length > 0) { - if (attribute->data) - free(attribute->data); - attribute->data = malloc(length); - CHECK(attribute->data); - memcpy(attribute->data, data, length); - } else { - attribute->data = NULL; - } -} - -void MockAppleKeychain::SetTestDataString(MockKeychainItemType item, - UInt32 tag, - const char* value) { - SetTestDataBytes(item, tag, value, value ? strlen(value) : 0); -} - -void MockAppleKeychain::SetTestDataPort(MockKeychainItemType item, - UInt32 value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecPortItemAttr); - UInt32* data = static_cast<UInt32*>(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataProtocol(MockKeychainItemType item, - SecProtocolType value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecProtocolItemAttr); - SecProtocolType* data = static_cast<SecProtocolType*>(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataAuthType(MockKeychainItemType item, - SecAuthenticationType value) { - SecKeychainAttribute* attribute = AttributeWithTag( - keychain_attr_list_[item], kSecAuthenticationTypeItemAttr); - SecAuthenticationType* data = static_cast<SecAuthenticationType*>( - attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataNegativeItem(MockKeychainItemType item, - Boolean value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecNegativeItemAttr); - Boolean* data = static_cast<Boolean*>(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataCreator(MockKeychainItemType item, - OSType value) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[item], - kSecCreatorItemAttr); - OSType* data = static_cast<OSType*>(attribute->data); - *data = value; -} - -void MockAppleKeychain::SetTestDataPasswordBytes(MockKeychainItemType item, - const void* data, - size_t length) { - keychain_data_[item].length = length; - if (length > 0) { - if (keychain_data_[item].data) - free(keychain_data_[item].data); - keychain_data_[item].data = malloc(length); - memcpy(keychain_data_[item].data, data, length); - } else { - keychain_data_[item].data = NULL; - } -} - -void MockAppleKeychain::SetTestDataPasswordString(MockKeychainItemType item, - const char* value) { - SetTestDataPasswordBytes(item, value, value ? strlen(value) : 0); -} - -OSStatus MockAppleKeychain::ItemCopyAttributesAndData( - SecKeychainItemRef itemRef, - SecKeychainAttributeInfo* info, - SecItemClass* itemClass, - SecKeychainAttributeList** attrList, - UInt32* length, - void** outData) const { - DCHECK(itemRef); - MockKeychainItemType key = - reinterpret_cast<MockKeychainItemType>(itemRef) - 1; - if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) - return errSecInvalidItemRef; - - DCHECK(!itemClass); // itemClass not implemented in the Mock. - if (locked_ && outData) - return errSecAuthFailed; - - if (attrList) - *attrList = &(keychain_attr_list_[key]); - if (outData) { - *outData = keychain_data_[key].data; - DCHECK(length); - *length = keychain_data_[key].length; - } - - ++attribute_data_copy_count_; - return noErr; -} - -OSStatus MockAppleKeychain::ItemModifyAttributesAndData( - SecKeychainItemRef itemRef, - const SecKeychainAttributeList* attrList, - UInt32 length, - const void* data) const { - DCHECK(itemRef); - if (locked_) - return errSecAuthFailed; - const char* fail_trigger = "fail_me"; - if (length == strlen(fail_trigger) && - memcmp(data, fail_trigger, length) == 0) { - return errSecAuthFailed; - } - - MockKeychainItemType key = - reinterpret_cast<MockKeychainItemType>(itemRef) - 1; - if (keychain_attr_list_.find(key) == keychain_attr_list_.end()) - return errSecInvalidItemRef; - - MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this); - if (attrList) { - for (UInt32 change_attr = 0; change_attr < attrList->count; ++change_attr) { - if (attrList->attr[change_attr].tag == kSecCreatorItemAttr) { - void* data = attrList->attr[change_attr].data; - mutable_this->SetTestDataCreator(key, *(static_cast<OSType*>(data))); - } else { - NOTIMPLEMENTED(); - } - } - } - if (data) - mutable_this->SetTestDataPasswordBytes(key, data, length); - return noErr; -} - -OSStatus MockAppleKeychain::ItemFreeAttributesAndData( - SecKeychainAttributeList* attrList, - void* data) const { - --attribute_data_copy_count_; - return noErr; -} +MockAppleKeychain::~MockAppleKeychain() {} OSStatus MockAppleKeychain::ItemDelete(SecKeychainItemRef itemRef) const { - if (locked_) - return errSecAuthFailed; - MockKeychainItemType key = - reinterpret_cast<MockKeychainItemType>(itemRef) - 1; - - for (unsigned int i = 0; i < keychain_attr_list_[key].count; ++i) { - if (keychain_attr_list_[key].attr[i].data) - free(keychain_attr_list_[key].attr[i].data); - } - free(keychain_attr_list_[key].attr); - if (keychain_data_[key].data) - free(keychain_data_[key].data); - - keychain_attr_list_.erase(key); - keychain_data_.erase(key); - added_via_api_.erase(key); return noErr; } -OSStatus MockAppleKeychain::SearchCreateFromAttributes( - CFTypeRef keychainOrArray, - SecItemClass itemClass, - const SecKeychainAttributeList* attrList, - SecKeychainSearchRef* searchRef) const { - // Figure out which of our mock items matches, and set up the array we'll use - // to generate results out of SearchCopyNext. - remaining_search_results_.clear(); - for (MockKeychainAttributesMap::const_iterator it = - keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - bool mock_item_matches = true; - for (UInt32 search_attr = 0; search_attr < attrList->count; ++search_attr) { - SecKeychainAttribute* mock_attribute = - AttributeWithTag(it->second, attrList->attr[search_attr].tag); - if (mock_attribute->length != attrList->attr[search_attr].length || - memcmp(mock_attribute->data, attrList->attr[search_attr].data, - attrList->attr[search_attr].length) != 0) { - mock_item_matches = false; - break; - } - } - if (mock_item_matches) - remaining_search_results_.push_back(it->first); - } - - DCHECK(searchRef); - *searchRef = kDummySearchRef; - ++search_copy_count_; - return noErr; -} - -bool MockAppleKeychain::AlreadyContainsInternetPassword( - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType) const { - for (MockKeychainAttributesMap::const_iterator it = - keychain_attr_list_.begin(); - it != keychain_attr_list_.end(); - ++it) { - SecKeychainAttribute* attribute; - attribute = AttributeWithTag(it->second, kSecServerItemAttr); - if ((attribute->length != serverNameLength) || - (attribute->data == NULL && *serverName != '\0') || - (attribute->data != NULL && *serverName == '\0') || - strncmp(serverName, - (const char*) attribute->data, - serverNameLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecSecurityDomainItemAttr); - if ((attribute->length != securityDomainLength) || - (attribute->data == NULL && *securityDomain != '\0') || - (attribute->data != NULL && *securityDomain == '\0') || - strncmp(securityDomain, - (const char*) attribute->data, - securityDomainLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecAccountItemAttr); - if ((attribute->length != accountNameLength) || - (attribute->data == NULL && *accountName != '\0') || - (attribute->data != NULL && *accountName == '\0') || - strncmp(accountName, - (const char*) attribute->data, - accountNameLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecPathItemAttr); - if ((attribute->length != pathLength) || - (attribute->data == NULL && *path != '\0') || - (attribute->data != NULL && *path == '\0') || - strncmp(path, - (const char*) attribute->data, - pathLength) != 0) { - continue; - } - attribute = AttributeWithTag(it->second, kSecPortItemAttr); - if ((attribute->data == NULL) || - (port != *(static_cast<UInt32*>(attribute->data)))) { - continue; - } - attribute = AttributeWithTag(it->second, kSecProtocolItemAttr); - if ((attribute->data == NULL) || - (protocol != *(static_cast<SecProtocolType*>(attribute->data)))) { - continue; - } - attribute = AttributeWithTag(it->second, kSecAuthenticationTypeItemAttr); - if ((attribute->data == NULL) || - (authenticationType != - *(static_cast<SecAuthenticationType*>(attribute->data)))) { - continue; - } - // The keychain already has this item, since all fields other than the - // password match. - return true; - } - return false; -} - -OSStatus MockAppleKeychain::AddInternetPassword( - SecKeychainRef keychain, - UInt32 serverNameLength, - const char* serverName, - UInt32 securityDomainLength, - const char* securityDomain, - UInt32 accountNameLength, - const char* accountName, - UInt32 pathLength, - const char* path, - UInt16 port, - SecProtocolType protocol, - SecAuthenticationType authenticationType, - UInt32 passwordLength, - const void* passwordData, - SecKeychainItemRef* itemRef) const { - if (locked_) - return errSecAuthFailed; - - // Check for the magic duplicate item trigger. - if (strcmp(serverName, "some.domain.com") == 0) - return errSecDuplicateItem; - - // If the account already exists in the keychain, we don't add it. - if (AlreadyContainsInternetPassword(serverNameLength, serverName, - securityDomainLength, securityDomain, - accountNameLength, accountName, - pathLength, path, - port, protocol, - authenticationType)) { - return errSecDuplicateItem; - } - - // Pick the next unused slot. - MockKeychainItemType key = next_item_key_++; - - // Initialize keychain data storage at the target location. - InitializeKeychainData(key); - - MockAppleKeychain* mutable_this = const_cast<MockAppleKeychain*>(this); - mutable_this->SetTestDataBytes(key, kSecServerItemAttr, serverName, - serverNameLength); - mutable_this->SetTestDataBytes(key, kSecSecurityDomainItemAttr, - securityDomain, securityDomainLength); - mutable_this->SetTestDataBytes(key, kSecAccountItemAttr, accountName, - accountNameLength); - mutable_this->SetTestDataBytes(key, kSecPathItemAttr, path, pathLength); - mutable_this->SetTestDataPort(key, port); - mutable_this->SetTestDataProtocol(key, protocol); - mutable_this->SetTestDataAuthType(key, authenticationType); - mutable_this->SetTestDataPasswordBytes(key, passwordData, - passwordLength); - base::Time::Exploded exploded_time; - base::Time::Now().UTCExplode(&exploded_time); - char time_string[128]; - snprintf(time_string, sizeof(time_string), "%04d%02d%02d%02d%02d%02dZ", - exploded_time.year, exploded_time.month, exploded_time.day_of_month, - exploded_time.hour, exploded_time.minute, exploded_time.second); - mutable_this->SetTestDataString(key, kSecCreationDateItemAttr, time_string); - - added_via_api_.insert(key); - - if (itemRef) { - *itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1); - ++keychain_item_copy_count_; - } - return noErr; -} - -OSStatus MockAppleKeychain::SearchCopyNext(SecKeychainSearchRef searchRef, - SecKeychainItemRef* itemRef) const { - if (remaining_search_results_.empty()) - return errSecItemNotFound; - MockKeychainItemType key = remaining_search_results_.front(); - remaining_search_results_.erase(remaining_search_results_.begin()); - *itemRef = reinterpret_cast<SecKeychainItemRef>(key + 1); - ++keychain_item_copy_count_; - return noErr; -} - -void MockAppleKeychain::Free(CFTypeRef ref) const { - if (!ref) - return; - - if (ref == kDummySearchRef) { - --search_copy_count_; - } else { - --keychain_item_copy_count_; - } -} - -int MockAppleKeychain::UnfreedSearchCount() const { - return search_copy_count_; -} - -int MockAppleKeychain::UnfreedKeychainItemCount() const { - return keychain_item_copy_count_; -} - -int MockAppleKeychain::UnfreedAttributeDataCount() const { - return attribute_data_copy_count_; -} - -bool MockAppleKeychain::CreatorCodesSetForAddedItems() const { - for (std::set<MockKeychainItemType>::const_iterator - i = added_via_api_.begin(); - i != added_via_api_.end(); - ++i) { - SecKeychainAttribute* attribute = AttributeWithTag(keychain_attr_list_[*i], - kSecCreatorItemAttr); - OSType* data = static_cast<OSType*>(attribute->data); - if (*data == 0) - return false; - } - return true; -} - -void MockAppleKeychain::AddTestItem(const KeychainTestData& item_data) { - MockKeychainItemType key = next_item_key_++; - - InitializeKeychainData(key); - SetTestDataAuthType(key, item_data.auth_type); - SetTestDataString(key, kSecServerItemAttr, item_data.server); - SetTestDataProtocol(key, item_data.protocol); - SetTestDataString(key, kSecPathItemAttr, item_data.path); - SetTestDataPort(key, item_data.port); - SetTestDataString(key, kSecSecurityDomainItemAttr, - item_data.security_domain); - SetTestDataString(key, kSecCreationDateItemAttr, item_data.creation_date); - SetTestDataString(key, kSecAccountItemAttr, item_data.username); - SetTestDataPasswordString(key, item_data.password); - SetTestDataNegativeItem(key, item_data.negative_item); -} - } // namespace crypto
diff --git a/crypto/nss_crypto_module_delegate.h b/crypto/nss_crypto_module_delegate.h index cf08f28..05be77d 100644 --- a/crypto/nss_crypto_module_delegate.h +++ b/crypto/nss_crypto_module_delegate.h
@@ -7,9 +7,6 @@ #include <string> -#include "base/callback_forward.h" -#include "crypto/scoped_nss_types.h" - namespace crypto { // PK11_SetPasswordFunc is a global setting. An implementation of @@ -37,16 +34,6 @@ bool* cancelled) = 0; }; -// Extends CryptoModuleBlockingPasswordDelegate with the ability to return a -// slot in which to act. (Eg, which slot to store a generated key in.) -class NSSCryptoModuleDelegate : public CryptoModuleBlockingPasswordDelegate { - public: - ~NSSCryptoModuleDelegate() override {} - - // Get the slot to store the generated key. - virtual ScopedPK11Slot RequestSlot() = 0; -}; - } // namespace crypto #endif // CRYPTO_NSS_CRYPTO_MODULE_DELEGATE_H_
diff --git a/device/vr/android/gvr/gvr_delegate.cc b/device/vr/android/gvr/gvr_delegate.cc index ceb673c..0230822 100644 --- a/device/vr/android/gvr/gvr_delegate.cc +++ b/device/vr/android/gvr/gvr_delegate.cc
@@ -102,10 +102,10 @@ gfx::DecomposedTransform decomposed_transform; gfx::DecomposeTransform(&decomposed_transform, transform); - pose->orientation.value()[0] = decomposed_transform.quaternion[0]; - pose->orientation.value()[1] = decomposed_transform.quaternion[1]; - pose->orientation.value()[2] = decomposed_transform.quaternion[2]; - pose->orientation.value()[3] = decomposed_transform.quaternion[3]; + pose->orientation.value()[0] = decomposed_transform.quaternion.x(); + pose->orientation.value()[1] = decomposed_transform.quaternion.y(); + pose->orientation.value()[2] = decomposed_transform.quaternion.z(); + pose->orientation.value()[3] = decomposed_transform.quaternion.w(); pose->position.emplace(3); pose->position.value()[0] = decomposed_transform.translate[0];
diff --git a/docs/task_scheduler_migration.md b/docs/task_scheduler_migration.md new file mode 100644 index 0000000..9861bde --- /dev/null +++ b/docs/task_scheduler_migration.md
@@ -0,0 +1,77 @@ +# TaskScheduler Migration + +[TOC] + +## Overview + +[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h) +was introduced to Chrome in Q1. The API is fully documented under [Threading and +Tasks in Chrome](threading_and_tasks.md). This page will go into more details +about how to migrate callers of existing APIs to TaskScheduler. + +Much of the migration has already been automated but the callers that remain +require manual intervention from the OWNERS. + +## BlockingPool (and other SequencedWorkerPools) + +The remaining callers of BrowserThread::GetBlockingPool() require manual +intervention because they're plumbing the SequencedWorkerPool multiple layers +into another component. + +The TaskScheduler API explicitly discourages this paradigm. Instead exposing a +static API from post_task.h and encouraging that individual components grab the +TaskRunner/TaskTraits they need instead of bring injected one from their owner +and hoping for the right traits. This often allows cleaning up multiple layers +of plumbing without otherwise hurting testing as documented +[here](threading_and_tasks.md#TaskRunner-ownership-encourage-no-dependency-injection). + +## BrowserThreads + +All BrowserThreads but UI/IO are being migrated to TaskScheduler +(i.e. FILE/FILE_USER_BLOCKING/DB/PROCESS_LAUNCHER/CACHE). + +This migration requires manual intervention because: + 1. Everything on BrowserThread::FOO has to be assumed to depend on being + sequenced with everything else on BrowserThread::FOO until decided otherwise + by a developer. + 2. Everything on BrowserThread::FOO has to be assumed to be thread-affine until + decided otherwise by a developer. + +As a developer your goal is to get rid of all uses of BrowserThread::FOO in your assigned files by: + 1. Splitting things into their own execution sequence (i.e. post to a TaskRunner + obtained from post_task.h -- see [Threading and Tasks in + Chrome](threading_and_tasks.md) for details). + 2. Ideally migrating from a single-threaded context to a [much preferred] + (threading_and_tasks.md#Prefer-Sequences-to-Threads) sequenced context. + * Note: if your tasks use COM APIs (Component Object Model on Windows), + you'll need to use CreateCOMSTATaskRunnerWithTraits() and sequencing will + not be an option. + +## Relevant single-thread -> sequence mappings + +* base::SingleThreadTaskRunner -> base::SequencedTaskRunner +* base::ThreadTaskRunnerHandle -> base::SequencedTaskRunnerHandle +* base::ThreadChecker -> base::SequenceChecker +* BrowserThread::DeleteOnThread -> base::DeleteOnTaskRunner / base::RefCountedDeleteOnSequence +* CreateSingleThreadTaskRunnerWithTraits() -> CreateSequencedTaskRunnerWithTraits() + * Every CreateSingleThreadTaskRunnerWithTraits() usage should be accompanied + with a comment and ideally a bug to make it sequence when the sequence-unfriendly + dependency is addressed (again [Prefer Sequences to + Threads](threading_and_tasks.md#Prefer-Sequences-to-Threads)). + +### Other relevant mappings for tests + +* base::MessageLoop -> base::test::ScopedTaskEnvironment +* content::TestBrowserThread -> content::TestBrowserThreadBundle (if you still + need other BrowserThreads and ScopedTaskEnvironment if you don't) +* base::RunLoop().Run() -(maybe)> content::RunAllBlockingPoolTasksUntilIdle() + * If test code was previously using RunLoop to execute things off the main + thread (as TestBrowserThreadBundle grouped everything under a single + MessageLoop), flushing tasks will now require asking for that explicitly. + * Or ScopedTaskEnvironment::RunUntilIdle() if you're not using + TestBrowserThreadBundle. + * If you need to control the order of execution of main thread versus + scheduler you can individually RunLoop.Run() and + TaskScheduler::FlushForTesting() + * If you need the TaskScheduler to not run anything until explicitly asked to + use ScopedTaskEnvironment::ExecutionMode::QUEUED.
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md index befa534..9b28921 100644 --- a/docs/threading_and_tasks.md +++ b/docs/threading_and_tasks.md
@@ -50,7 +50,7 @@ ### Prefer Sequences to Threads -**Sequenced execution mode is far prefered to Single Threaded** in scenarios +**Sequenced execution mode is far preferred to Single Threaded** in scenarios that require mere thread-safety as it opens up scheduling paradigms that wouldn't be possible otherwise (sequences can hop threads instead of being stuck behind unrelated work on a dedicated thread). Ability to hop threads also means @@ -633,7 +633,7 @@ // TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be // running. ``` -## TaskRunner ownership +## TaskRunner ownership (encourage no dependency injection) TaskRunners shouldn't be passed through several components. Instead, the components that uses a TaskRunner should be the one that creates it. @@ -643,3 +643,24 @@ used in an eventual leaf. The leaf can and should now obtain its TaskRunner directly from [`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h). + +Dependency injection of TaskRunners can still seldomly be useful to unit test a +component when triggering a specific race in a specific way is essential to the +test. For such cases the preferred approach is the following: + +```cpp +class FooWithCustomizableTaskRunnerForTesting { + public: + + void SetBackgroundTaskRunnerForTesting( + scoped_refptr<base::SequenceTaskRunner> background_task_runner); + + private: + scoped_refptr<base::SequenceTaskRunner> background_task_runner_ = + base::CreateSequenceTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BACKGROUND}); +} +``` + +Note that this still allows removing all layers of plumbing between //chrome and +that component since unit tests will use the leaf layer directly.
diff --git a/extensions/browser/api/declarative_webrequest/webrequest_action.cc b/extensions/browser/api/declarative_webrequest/webrequest_action.cc index 6c7589db..39f945b 100644 --- a/extensions/browser/api/declarative_webrequest/webrequest_action.cc +++ b/extensions/browser/api/declarative_webrequest/webrequest_action.cc
@@ -516,8 +516,8 @@ // TODO(devlin): Pass in the real tab id here. return WebRequestPermissions::CanExtensionAccessURL( extension_info_map, extension_id, request->url(), -1, - apply_info->crosses_incognito, permission_check, - request->initiator()) == PermissionsData::ACCESS_ALLOWED; + apply_info->crosses_incognito, + permission_check) == PermissionsData::ACCESS_ALLOWED; } // static
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc index a1b739f..ee2cf73c 100644 --- a/extensions/browser/api/web_request/web_request_api.cc +++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -1498,9 +1498,7 @@ WebRequestPermissions::CanExtensionAccessURL( extension_info_map, listener->id.extension_id, url, frame_data.tab_id, crosses_incognito, - WebRequestPermissions::REQUIRE_HOST_PERMISSION, - request->initiator()); - + WebRequestPermissions::REQUIRE_HOST_PERMISSION); if (access != PermissionsData::ACCESS_ALLOWED) { if (access == PermissionsData::ACCESS_WITHHELD && web_request_event_router_delegate_) {
diff --git a/extensions/browser/api/web_request/web_request_permissions.cc b/extensions/browser/api/web_request/web_request_permissions.cc index ccfe22b..a683ec3 100644 --- a/extensions/browser/api/web_request/web_request_permissions.cc +++ b/extensions/browser/api/web_request/web_request_permissions.cc
@@ -19,6 +19,7 @@ #include "extensions/common/permissions/permissions_data.h" #include "net/url_request/url_request.h" #include "url/gurl.h" +#include "url/origin.h" #if defined(OS_CHROMEOS) #include "chromeos/login/login_state.h" @@ -150,8 +151,7 @@ const GURL& url, int tab_id, bool crosses_incognito, - HostPermissionsCheck host_permissions_check, - const base::Optional<url::Origin>& initiator) { + HostPermissionsCheck host_permissions_check) { // extension_info_map can be NULL in testing. if (!extension_info_map) return PermissionsData::ACCESS_ALLOWED; @@ -161,12 +161,6 @@ if (!extension) return PermissionsData::ACCESS_DENIED; - // Prevent viewing / modifying requests initiated by a host protected by - // policy. - if (initiator && extension->permissions_data()->IsRuntimeBlockedHost( - initiator->GetPhysicalOrigin().GetURL())) - return PermissionsData::ACCESS_DENIED; - // When we are in a Public Session, allow all URLs for webRequests initiated // by a regular extension (but don't allow chrome:// URLs). #if defined(OS_CHROMEOS)
diff --git a/extensions/browser/api/web_request/web_request_permissions.h b/extensions/browser/api/web_request/web_request_permissions.h index 74d9475..ee6ba29 100644 --- a/extensions/browser/api/web_request/web_request_permissions.h +++ b/extensions/browser/api/web_request/web_request_permissions.h
@@ -9,9 +9,7 @@ #include <string> #include "base/macros.h" -#include "base/optional.h" #include "extensions/common/permissions/permissions_data.h" -#include "url/origin.h" class GURL; @@ -49,15 +47,14 @@ static void AllowAllExtensionLocationsInPublicSessionForTesting(bool value); // |host_permission_check| controls how permissions are checked with regard to - // |url| and |initiator| if an initiator exists. + // |url|. static extensions::PermissionsData::AccessType CanExtensionAccessURL( const extensions::InfoMap* extension_info_map, const std::string& extension_id, const GURL& url, int tab_id, bool crosses_incognito, - HostPermissionsCheck host_permissions_check, - const base::Optional<url::Origin>& initiator); + HostPermissionsCheck host_permissions_check); private: DISALLOW_IMPLICIT_CONSTRUCTORS(WebRequestPermissions);
diff --git a/extensions/common/permissions/permissions_data.cc b/extensions/common/permissions/permissions_data.cc index 96e8269..245040e 100644 --- a/extensions/common/permissions/permissions_data.cc +++ b/extensions/common/permissions/permissions_data.cc
@@ -280,7 +280,7 @@ bool PermissionsData::HasHostPermission(const GURL& url) const { base::AutoLock auto_lock(runtime_lock_); return active_permissions_unsafe_->HasExplicitAccessToOrigin(url) && - !IsRuntimeBlockedHostUnsafe(url); + !IsRuntimeBlockedHost(url); } bool PermissionsData::HasEffectiveAccessToAllHosts() const { @@ -412,7 +412,7 @@ return false; } -bool PermissionsData::IsRuntimeBlockedHostUnsafe(const GURL& url) const { +bool PermissionsData::IsRuntimeBlockedHost(const GURL& url) const { runtime_lock_.AssertAcquired(); return PolicyBlockedHostsUnsafe().MatchesURL(url) && !PolicyAllowedHostsUnsafe().MatchesURL(url); @@ -431,7 +431,7 @@ return ACCESS_DENIED; if (extension->location() != Manifest::COMPONENT && - extension->permissions_data()->IsRuntimeBlockedHostUnsafe(document_url)) { + extension->permissions_data()->IsRuntimeBlockedHost(document_url)) { if (error) *error = extension_misc::kPolicyBlockedScripting; return ACCESS_DENIED;
diff --git a/extensions/common/permissions/permissions_data.h b/extensions/common/permissions/permissions_data.h index c1c5de2..a619590a 100644 --- a/extensions/common/permissions/permissions_data.h +++ b/extensions/common/permissions/permissions_data.h
@@ -258,17 +258,16 @@ // methods instead (e.g. CanAccessPage()). const URLPatternSet policy_allowed_hosts() const; - // Check if a specific URL is blocked by policy from extension use at runtime. - bool IsRuntimeBlockedHost(const GURL& url) const { - base::AutoLock auto_lock(runtime_lock_); - return IsRuntimeBlockedHostUnsafe(url); - } - #if defined(UNIT_TEST) const PermissionSet* GetTabSpecificPermissionsForTesting(int tab_id) const { base::AutoLock auto_lock(runtime_lock_); return GetTabSpecificPermissions(tab_id); } + + bool IsRuntimeBlockedHostForTesting(const GURL& url) const { + base::AutoLock auto_lock(runtime_lock_); + return IsRuntimeBlockedHost(url); + } #endif private: @@ -297,8 +296,7 @@ std::string* error) const; // Check if a specific URL is blocked by policy from extension use at runtime. - // You must acquire the runtime_lock_ before calling. - bool IsRuntimeBlockedHostUnsafe(const GURL& url) const; + bool IsRuntimeBlockedHost(const GURL& url) const; // Same as policy_blocked_hosts but instead returns a reference. // You must acquire runtime_lock_ before calling this.
diff --git a/gpu/command_buffer/common/constants.h b/gpu/command_buffer/common/constants.h index 7b80a33..40fe3d57 100644 --- a/gpu/command_buffer/common/constants.h +++ b/gpu/command_buffer/common/constants.h
@@ -8,6 +8,8 @@ #include <stddef.h> #include <stdint.h> +#include "build/build_config.h" + namespace gpu { typedef int32_t CommandBufferOffset; @@ -68,8 +70,13 @@ // Common Command Buffer shared memory transfer buffer ID. const int32_t kCommandBufferSharedMemoryId = 4; -// The size to set for the program cache. +// The size to set for the program cache for default and low-end device cases. +#if !defined(OS_ANDROID) const size_t kDefaultMaxProgramCacheMemoryBytes = 6 * 1024 * 1024; +#else +const size_t kDefaultMaxProgramCacheMemoryBytes = 2 * 1024 * 1024; +const size_t kLowEndMaxProgramCacheMemoryBytes = 512 * 1024; +#endif // Namespace used to separate various command buffer types. enum CommandBufferNamespace : int8_t {
diff --git a/gpu/command_buffer/service/gpu_preferences.cc b/gpu/command_buffer/service/gpu_preferences.cc index 06bc6b41..1b7983d 100644 --- a/gpu/command_buffer/service/gpu_preferences.cc +++ b/gpu/command_buffer/service/gpu_preferences.cc
@@ -4,9 +4,16 @@ #include "gpu/command_buffer/service/gpu_preferences.h" +#include "base/sys_info.h" + namespace gpu { GpuPreferences::GpuPreferences() { + gpu_program_cache_size = kDefaultMaxProgramCacheMemoryBytes; +#if defined(OS_ANDROID) + if (base::SysInfo::IsLowEndDevice()) + gpu_program_cache_size = kLowEndMaxProgramCacheMemoryBytes; +#endif } GpuPreferences::GpuPreferences(const GpuPreferences& other) = default;
diff --git a/gpu/command_buffer/service/memory_program_cache.cc b/gpu/command_buffer/service/memory_program_cache.cc index 93a0b221..79839eb 100644 --- a/gpu/command_buffer/service/memory_program_cache.cc +++ b/gpu/command_buffer/service/memory_program_cache.cc
@@ -7,8 +7,10 @@ #include <stddef.h> #include "base/base64.h" +#include "base/bind.h" #include "base/callback.h" #include "base/command_line.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" @@ -220,7 +222,10 @@ disable_program_caching_for_transform_feedback), curr_size_bytes_(0), store_(ProgramMRUCache::NO_AUTO_EVICT), - activity_flags_(activity_flags) {} + activity_flags_(activity_flags), + memory_pressure_listener_( + base::Bind(&MemoryProgramCache::HandleMemoryPressure, + base::Unretained(this))) {} MemoryProgramCache::~MemoryProgramCache() {} @@ -471,6 +476,23 @@ } } +void MemoryProgramCache::HandleMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { + // Set a low limit on cache size for MEMORY_PRESSURE_LEVEL_MODERATE. + size_t limit = max_size_bytes_ / 4; + if (memory_pressure_level == + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { + limit = 0; + } + if (curr_size_bytes_ <= limit) + return; + size_t initial_size = curr_size_bytes_; + while (curr_size_bytes_ > limit && !store_.empty()) + store_.Erase(store_.rbegin()); + UMA_HISTOGRAM_COUNTS_100000("GPU.ProgramCache.MemoryReleasedOnPressure", + (initial_size - curr_size_bytes_) / 1024); +} + MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( GLsizei length, GLenum format,
diff --git a/gpu/command_buffer/service/memory_program_cache.h b/gpu/command_buffer/service/memory_program_cache.h index 5cef31f..e085ff8e 100644 --- a/gpu/command_buffer/service/memory_program_cache.h +++ b/gpu/command_buffer/service/memory_program_cache.h
@@ -14,6 +14,7 @@ #include "base/containers/hash_tables.h" #include "base/containers/mru_cache.h" #include "base/macros.h" +#include "base/memory/memory_pressure_listener.h" #include "base/memory/ref_counted.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/program_cache.h" @@ -166,6 +167,9 @@ typedef base::MRUCache<std::string, scoped_refptr<ProgramCacheValue> > ProgramMRUCache; + void HandleMemoryPressure( + base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); + const size_t max_size_bytes_; const bool disable_gpu_shader_disk_cache_; const bool disable_program_caching_for_transform_feedback_; @@ -173,6 +177,8 @@ ProgramMRUCache store_; GpuProcessActivityFlags* activity_flags_; + base::MemoryPressureListener memory_pressure_listener_; + DISALLOW_COPY_AND_ASSIGN(MemoryProgramCache); };
diff --git a/ios/chrome/browser/ui/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view_controller.mm index abbecf34..e7e1255 100644 --- a/ios/chrome/browser/ui/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view_controller.mm
@@ -572,6 +572,10 @@ // the user from interacting with the browser view. @property(nonatomic, strong) ActivityOverlayCoordinator* activityOverlayCoordinator; +// A block to be run when the |tabWasAdded:| method completes the animation +// for the presentation of a new tab. Can be used to record performance metrics. +@property(nonatomic, strong, nullable) + ProceduralBlock foregroundTabWasAddedCompletionBlock; // The user agent type used to load the currently visible page. User agent type // is NONE if there is no visible page or visible page is a native page. @@ -932,6 +936,8 @@ @synthesize hideStatusBar = _hideStatusBar; @synthesize activityOverlayCoordinator = _activityOverlayCoordinator; @synthesize presenting = _presenting; +@synthesize foregroundTabWasAddedCompletionBlock = + _foregroundTabWasAddedCompletionBlock; #pragma mark - Object lifecycle @@ -1195,6 +1201,23 @@ } - (void)newTab:(id)sender { + // Observe the timing of the new tab creation, both MainController + // and BrowserViewController call into this method on the correct BVC to + // create new tabs making it preferable to doing this in + // |chromeExecuteCommand:|. + NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]; + BOOL offTheRecord = self.isOffTheRecord; + self.foregroundTabWasAddedCompletionBlock = ^{ + double duration = [NSDate timeIntervalSinceReferenceDate] - startTime; + base::TimeDelta timeDelta = base::TimeDelta::FromSecondsD(duration); + if (offTheRecord) { + UMA_HISTOGRAM_TIMES("Toolbar.Menu.NewIncognitoTabPresentationDuration", + timeDelta); + } else { + UMA_HISTOGRAM_TIMES("Toolbar.Menu.NewTabPresentationDuration", timeDelta); + } + }; + [self setLastTapPoint:sender]; DCHECK(self.visible || self.dismissingModal); Tab* currentTab = [_model currentTab]; @@ -1622,6 +1645,10 @@ [self tabSelected:currentTab]; } startVoiceSearchIfNecessaryBlock(); + + if (self.foregroundTabWasAddedCompletionBlock) { + self.foregroundTabWasAddedCompletionBlock(); + } }); } else { // -updateSnapshotWithOverlay will force a screen redraw, so take the @@ -1660,6 +1687,9 @@ startVoiceSearchIfNecessaryBlock(); }); } + // Reset the foreground tab completion block so that it can never be + // called more than once regardless of foreground/background tab appearances. + self.foregroundTabWasAddedCompletionBlock = nil; } #pragma mark - UI Configuration and Layout
diff --git a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm index 814e302..3630dd38 100644 --- a/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm +++ b/ios/chrome/browser/ui/payments/credit_card_edit_mediator.mm
@@ -49,6 +49,14 @@ @property(nonatomic, strong) NSMutableDictionary<NSNumber*, EditorField*>* fieldsMap; +// The reference to the autofill::CREDIT_CARD_EXP_MONTH field, if any (i.e if +// we are dealing with a server card this will not exist). +@property(nonatomic, strong) EditorField* creditCardExpMonthField; + +// The reference to the autofill::CREDIT_CARD_EXP_4_DIGIT_YEAR field, if any +// (i.e. if we are dealing with a server card this will not exist). +@property(nonatomic, strong) EditorField* creditCardExpYearField; + @end @implementation CreditCardEditViewControllerMediator @@ -59,6 +67,8 @@ @synthesize paymentRequest = _paymentRequest; @synthesize creditCard = _creditCard; @synthesize fieldsMap = _fieldsMap; +@synthesize creditCardExpMonthField = _creditCardExpMonthField; +@synthesize creditCardExpYearField = _creditCardExpYearField; - (instancetype)initWithPaymentRequest:(PaymentRequest*)paymentRequest creditCard:(autofill::CreditCard*)creditCard { @@ -83,7 +93,14 @@ - (void)setConsumer:(id<PaymentRequestEditConsumer>)consumer { _consumer = consumer; + [self.consumer setEditorFields:[self createEditorFields]]; + if (self.creditCardExpMonthField) { + [self loadMonths]; + } + if (self.creditCardExpYearField) { + [self loadYears]; + } } - (void)setBillingProfile:(autofill::AutofillProfile*)billingProfile { @@ -155,6 +172,55 @@ #pragma mark - Helper methods +// Queries the month numbers. +- (void)loadMonths { + NSMutableArray<NSString*>* months = [[NSMutableArray alloc] init]; + + for (int month = 1; month <= 12; month++) { + NSString* monthString = [NSString stringWithFormat:@"%02d", month]; + [months addObject:monthString]; + } + + // Notify the view controller asynchronously to allow for the view to update. + __weak CreditCardEditViewControllerMediator* weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf.consumer setOptions:months + forEditorField:weakSelf.creditCardExpMonthField]; + }); +} + +// Queries the year numbers. +- (void)loadYears { + NSMutableArray<NSString*>* years = [[NSMutableArray alloc] init]; + + NSDateComponents* dateComponents = + [[NSCalendar currentCalendar] components:NSCalendarUnitYear + fromDate:[NSDate date]]; + + int currentYear = [dateComponents year]; + bool foundCardExpirationYear = false; + for (int year = currentYear; year < currentYear + 10; year++) { + NSString* yearString = [NSString stringWithFormat:@"%04d", year]; + if ([yearString isEqualToString:_creditCardExpYearField.value]) + foundCardExpirationYear = true; + [years addObject:yearString]; + } + + // Ensure that the expiration year on a user's saved card is + // always available as one of the options to select from. This is + // useful in the case that the user's card is expired. + if (!foundCardExpirationYear) { + [years insertObject:_creditCardExpYearField.value atIndex:0]; + } + + // Notify the view controller asynchronously to allow for the view to update. + __weak CreditCardEditViewControllerMediator* weakSelf = self; + dispatch_async(dispatch_get_main_queue(), ^{ + [weakSelf.consumer setOptions:years + forEditorField:weakSelf.creditCardExpYearField]; + }); +} + - (NSArray<EditorField*>*)createEditorFields { NSMutableArray<EditorField*>* fields = [[NSMutableArray alloc] init]; @@ -220,11 +286,18 @@ } [fields addObject:creditCardNameField]; + NSDateComponents* dateComponents = [[NSCalendar currentCalendar] + components:NSCalendarUnitMonth | NSCalendarUnitYear + fromDate:[NSDate date]]; + + int currentMonth = [dateComponents month]; + // Expiration month field. NSString* creditCardExpMonth = - _creditCard + _creditCard && (_creditCard->expiration_month() >= 1 && + _creditCard->expiration_month() <= 12) ? [NSString stringWithFormat:@"%02d", _creditCard->expiration_month()] - : nil; + : [NSString stringWithFormat:@"%02d", currentMonth]; fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardExpMonth]; EditorField* expirationMonthField = self.fieldsMap[fieldKey]; if (!expirationMonthField) { @@ -236,13 +309,15 @@ required:YES]; [self.fieldsMap setObject:expirationMonthField forKey:fieldKey]; } + self.creditCardExpMonthField = expirationMonthField; [fields addObject:expirationMonthField]; // Expiration year field. + int currentYear = [dateComponents year]; NSString* creditCardExpYear = _creditCard ? [NSString stringWithFormat:@"%04d", _creditCard->expiration_year()] - : nil; + : [NSString stringWithFormat:@"%04d", currentYear]; fieldKey = [NSNumber numberWithInt:AutofillUITypeCreditCardExpYear]; EditorField* expirationYearField = self.fieldsMap[fieldKey]; if (!expirationYearField) { @@ -254,6 +329,7 @@ required:YES]; [self.fieldsMap setObject:expirationYearField forKey:fieldKey]; } + self.creditCardExpYearField = expirationYearField; [fields addObject:expirationYearField]; // The billing address field appears after the expiration year field.
diff --git a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm index cdb4ba2b..6b2a75f6 100644 --- a/ios/chrome/browser/ui/stack_view/stack_view_controller.mm +++ b/ios/chrome/browser/ui/stack_view/stack_view_controller.mm
@@ -2025,6 +2025,10 @@ - (Tab*)dismissWithNewTabAnimation:(const GURL&)URL atIndex:(NSUInteger)position transition:(ui::PageTransition)transition { + // Record the start time for this operation so it may be reported as a metric + // in the animation completion block. + NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate]; + // This helps smooth out the animation. [[_scrollView layer] setShouldRasterize:YES]; if (_isBeingDismissed) @@ -2077,6 +2081,15 @@ [newCard removeFromSuperview]; [[_scrollView layer] setShouldRasterize:NO]; [_delegate tabSwitcherDismissTransitionDidEnd:self]; + double duration = [NSDate timeIntervalSinceReferenceDate] - startTime; + if (_activeCardSet.tabModel.isOffTheRecord) { + UMA_HISTOGRAM_TIMES( + "Toolbar.TabSwitcher.NewIncognitoTabPresentationDurationn", + base::TimeDelta::FromSecondsD(duration)); + } else { + UMA_HISTOGRAM_TIMES("Toolbar.TabSwitcher.NewTabPresentationDuration", + base::TimeDelta::FromSecondsD(duration)); + } }; CGPoint origin = _lastTapPoint;
diff --git a/media/base/BUILD.gn b/media/base/BUILD.gn index a4c5a309e..3c5689f 100644 --- a/media/base/BUILD.gn +++ b/media/base/BUILD.gn
@@ -196,6 +196,7 @@ "null_video_sink.h", "output_device_info.cc", "output_device_info.h", + "overlay_info.cc", "overlay_info.h", "pipeline.h", "pipeline_impl.cc",
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 9ab0dbc0..70ece28 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -230,7 +230,7 @@ // CanPlayThrough issued according to standard. const base::Feature kSpecCompliantCanPlayThrough{ - "SpecCompliantCanPlayThrough", base::FEATURE_DISABLED_BY_DEFAULT}; + "SpecCompliantCanPlayThrough", base::FEATURE_ENABLED_BY_DEFAULT}; // Use shared block-based buffering for media. const base::Feature kUseNewMediaCache{"use-new-media-cache",
diff --git a/media/base/overlay_info.cc b/media/base/overlay_info.cc new file mode 100644 index 0000000..1658f2a --- /dev/null +++ b/media/base/overlay_info.cc
@@ -0,0 +1,21 @@ +// 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 "media/base/overlay_info.h" +#include "media/base/surface_manager.h" + +namespace media { + +OverlayInfo::OverlayInfo() = default; +OverlayInfo::OverlayInfo(const OverlayInfo&) = default; + +bool OverlayInfo::HasValidSurfaceId() const { + return surface_id != SurfaceManager::kNoSurfaceID; +} + +bool OverlayInfo::HasValidRoutingToken() const { + return routing_token.has_value(); +} + +} // namespace media
diff --git a/media/base/overlay_info.h b/media/base/overlay_info.h index da0c387..089edca 100644 --- a/media/base/overlay_info.h +++ b/media/base/overlay_info.h
@@ -9,13 +9,38 @@ #include "base/macros.h" #include "base/optional.h" #include "base/unguessable_token.h" +#include "media/base/media_export.h" +#include "media/base/surface_manager.h" namespace media { -// Request information to construct an overlay. This can be either a surface_id -// or an AndroidOverlay routing token. -using ProvideOverlayInfoCB = - base::Callback<void(int, const base::Optional<base::UnguessableToken>&)>; +struct MEDIA_EXPORT OverlayInfo { + // An unset routing token indicates "do not use any routing token". A null + // routing token isn't serializable, else we'd probably use that instead. + using RoutingToken = base::Optional<base::UnguessableToken>; + + OverlayInfo(); + OverlayInfo(const OverlayInfo&); + + // Convenience functions to return true if and only if this specifies a + // surface ID / routing token that is not kNoSurfaceID / empty. I.e., if we + // provide enough info to create an overlay. + bool HasValidSurfaceId() const; + bool HasValidRoutingToken() const; + + // This is the SurfaceManager surface id, or SurfaceManager::kNoSurfaceID to + // indicate that no surface from SurfaceManager should be used. + int surface_id = SurfaceManager::kNoSurfaceID; + + // The routing token for AndroidOverlay, if any. + RoutingToken routing_token; + + // Is the player in fullscreen? + bool is_fullscreen = false; +}; + +// Request OverlayInformation. +using ProvideOverlayInfoCB = base::Callback<void(const OverlayInfo&)>; using RequestOverlayInfoCB = base::Callback<void(bool, const ProvideOverlayInfoCB&)>;
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc index 7f21f07..a993c41 100644 --- a/media/blink/webmediaplayer_impl.cc +++ b/media/blink/webmediaplayer_impl.cc
@@ -260,7 +260,7 @@ embedded_media_experience_enabled_( params->embedded_media_experience_enabled()), request_routing_token_cb_(params->request_routing_token_cb()), - overlay_routing_token_(base::UnguessableToken()) { + overlay_routing_token_(OverlayInfo::RoutingToken()) { DVLOG(1) << __func__; DCHECK(!adjust_allocated_memory_cb_.is_null()); DCHECK(renderer_factory_selector_); @@ -366,7 +366,7 @@ surface_created_cb_.callback()); } else if (request_routing_token_cb_ && overlay_mode_ == OverlayMode::kUseAndroidOverlay) { - overlay_routing_token_.reset(); + overlay_routing_token_is_pending_ = true; token_available_cb_.Reset( base::Bind(&WebMediaPlayerImpl::OnOverlayRoutingToken, AsWeakPtr())); request_routing_token_cb_.Run(token_available_cb_.callback()); @@ -387,7 +387,8 @@ overlay_surface_id_ = SurfaceManager::kNoSurfaceID; } else if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) { token_available_cb_.Cancel(); - overlay_routing_token_ = base::UnguessableToken(); + overlay_routing_token_is_pending_ = false; + overlay_routing_token_ = OverlayInfo::RoutingToken(); } if (decoder_requires_restart_for_overlay_) @@ -397,6 +398,8 @@ } void WebMediaPlayerImpl::EnteredFullscreen() { + overlay_info_.is_fullscreen = true; + // |force_video_overlays_| implies that we're already in overlay mode, so take // no action here. Otherwise, switch to an overlay if it's allowed and if // it will display properly. @@ -407,11 +410,20 @@ if (observer_) observer_->OnEnteredFullscreen(); - // TODO(liberato): if the decoder provided a callback for fullscreen state, - // then notify it now. + // We send this only if we can send multiple calls. Otherwise, either (a) + // we already sent it and we don't have a callback anyway (we reset it when + // it's called in restart mode), or (b) we'll send this later when the surface + // actually arrives. GVD assumes that the first overlay info will have the + // routing information. Note that we set |is_fullscreen_| earlier, so that + // if EnableOverlay() can include fullscreen info in case it sends the overlay + // info before returning. + if (!decoder_requires_restart_for_overlay_) + MaybeSendOverlayInfoToDecoder(); } void WebMediaPlayerImpl::ExitedFullscreen() { + overlay_info_.is_fullscreen = false; + // If we're in overlay mode, then exit it unless we're supposed to be in // overlay mode all the time. if (!force_video_overlays_ && overlay_enabled_) @@ -419,8 +431,9 @@ if (observer_) observer_->OnExitedFullscreen(); - // TODO(liberato): if the decoder provided a callback for fullscreen state, - // then notify it now. + // See EnteredFullscreen for why we do this. + if (!decoder_requires_restart_for_overlay_) + MaybeSendOverlayInfoToDecoder(); } void WebMediaPlayerImpl::BecameDominantVisibleContent(bool isDominant) { @@ -1747,7 +1760,9 @@ void WebMediaPlayerImpl::OnOverlayRoutingToken( const base::UnguessableToken& token) { DCHECK(overlay_mode_ == OverlayMode::kUseAndroidOverlay); - overlay_routing_token_ = token; + // TODO(liberato): |token| should already be a RoutingToken. + overlay_routing_token_is_pending_ = false; + overlay_routing_token_ = OverlayInfo::RoutingToken(token); MaybeSendOverlayInfoToDecoder(); } @@ -1795,37 +1810,27 @@ // using overlays. Assuming that the decoder has requested info, the only // case in which we don't want to send something is if we've requested the // info but not received it yet. Then, we should wait until we do. + // + // Initialization requires this; AVDA should start with enough info to make an + // overlay, so that (pre-M) the initial codec is created with the right output + // surface; it can't switch later. if (overlay_mode_ == OverlayMode::kUseContentVideoView) { if (!overlay_surface_id_.has_value()) return; + + overlay_info_.surface_id = *overlay_surface_id_; } else if (overlay_mode_ == OverlayMode::kUseAndroidOverlay) { - if (!overlay_routing_token_.has_value()) + if (overlay_routing_token_is_pending_) return; + + overlay_info_.routing_token = overlay_routing_token_; } - // Note that we're guaranteed that both |overlay_surface_id_| and - // |overlay_routing_token_| have values, since both have values unless there - // is a request pending. Nobody calls us if a request is pending. - - int surface_id = SurfaceManager::kNoSurfaceID; - if (overlay_surface_id_) - surface_id = *overlay_surface_id_; - - // Since we represent "no token" as a null UnguessableToken, we translate it - // into an optional here. Alternatively, we could represent it as a - // base::Optional in |overlay_routing_token_|, but then we'd have a - // base::Optional<base::Optional<base::UnguessableToken> >. We don't do that - // because... just because. - base::Optional<base::UnguessableToken> routing_token; - if (overlay_routing_token_.has_value() && !overlay_routing_token_->is_empty()) - routing_token = *overlay_routing_token_; - // If restart is required, the callback is one-shot only. if (decoder_requires_restart_for_overlay_) { - base::ResetAndReturn(&provide_overlay_info_cb_) - .Run(surface_id, routing_token); + base::ResetAndReturn(&provide_overlay_info_cb_).Run(overlay_info_); } else { - provide_overlay_info_cb_.Run(surface_id, routing_token); + provide_overlay_info_cb_.Run(overlay_info_); } }
diff --git a/media/blink/webmediaplayer_impl.h b/media/blink/webmediaplayer_impl.h index df65ecb..5bdf19e 100644 --- a/media/blink/webmediaplayer_impl.h +++ b/media/blink/webmediaplayer_impl.h
@@ -260,8 +260,11 @@ // AndroidOverlay, this is the routing token. bool HaveOverlayInfo(); - // Send the overlay surface ID / routing token to the decoder if we have it - // and if it has been requested. + // Send OverlayInfo to the decoder. + // + // If we've requested but not yet received the surface id or routing token, or + // if there's no decoder-provided callback to send the overlay info, then this + // call will do nothing. void MaybeSendOverlayInfoToDecoder(); void OnPipelineSuspended(); @@ -776,11 +779,15 @@ // Optional callback to request the routing token for AndroidOverlay. RequestRoutingTokenCallback request_routing_token_cb_; - // Routing token, if we have one. No value if we have a request pending to - // get it via |request_routing_token_cb_|. A has_value() is_empty() token - // indicates that we requested and received an empty token. Note that we - // can't send an empty token via IPC, so we handle that specially. - base::Optional<base::UnguessableToken> overlay_routing_token_; + // If |overlay_routing_token_is_pending_| is false, then + // |overlay_routing_token_| contains the routing token we should send, if any. + // Otherwise, |overlay_routing_token_| is undefined. We set the flag while + // we have a request for the token that hasn't been answered yet; i.e., it + // means that we don't know what, if any, token we should be using. + bool overlay_routing_token_is_pending_ = false; + OverlayInfo::RoutingToken overlay_routing_token_; + + OverlayInfo overlay_info_; DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerImpl); };
diff --git a/media/filters/gpu_video_decoder.cc b/media/filters/gpu_video_decoder.cc index c9b7fb10..308ccb7 100644 --- a/media/filters/gpu_video_decoder.cc +++ b/media/filters/gpu_video_decoder.cc
@@ -307,8 +307,7 @@ } // If external surfaces are not supported we can complete initialization now. - CompleteInitialization(SurfaceManager::kNoSurfaceID, - base::UnguessableToken()); + CompleteInitialization(OverlayInfo()); } // OnOverlayInfoAvailable() might be called at any time between Initialize() and @@ -316,9 +315,7 @@ // the current state. // At most one of |surface_id| and |token| should be provided. The other will // be kNoSurfaceID or an empty token, respectively. -void GpuVideoDecoder::OnOverlayInfoAvailable( - int surface_id, - const base::Optional<base::UnguessableToken>& token) { +void GpuVideoDecoder::OnOverlayInfoAvailable(const OverlayInfo& overlay_info) { DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); if (!vda_) @@ -329,18 +326,16 @@ // SetSurface() before initializing because there is no remote VDA to handle // the call yet. if (!vda_initialized_) { - CompleteInitialization(surface_id, token); + CompleteInitialization(overlay_info); return; } // The VDA must be already initialized (or async initialization is in // progress) so we can call SetSurface(). - vda_->SetSurface(surface_id, token); + vda_->SetOverlayInfo(overlay_info); } -void GpuVideoDecoder::CompleteInitialization( - int surface_id, - const base::Optional<base::UnguessableToken>& token) { +void GpuVideoDecoder::CompleteInitialization(const OverlayInfo& overlay_info) { DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent(); DCHECK(vda_); DCHECK(!init_cb_.is_null()); @@ -349,8 +344,7 @@ VideoDecodeAccelerator::Config vda_config; vda_config.profile = config_.profile(); vda_config.cdm_id = cdm_id_; - vda_config.surface_id = surface_id; - vda_config.overlay_routing_token = token; + vda_config.overlay_info = overlay_info; vda_config.encryption_scheme = config_.encryption_scheme(); vda_config.is_deferred_initialization_allowed = true; vda_config.initial_expected_coded_size = config_.coded_size();
diff --git a/media/filters/gpu_video_decoder.h b/media/filters/gpu_video_decoder.h index 604f6ad..634a46a 100644 --- a/media/filters/gpu_video_decoder.h +++ b/media/filters/gpu_video_decoder.h
@@ -155,17 +155,13 @@ // Provided to the |request_overlay_info_cb_| callback given during // construction. Sets or changes the output surface. - void OnOverlayInfoAvailable( - int surface_id, - const base::Optional<base::UnguessableToken>& routing_token); + void OnOverlayInfoAvailable(const OverlayInfo& overlay_info); // If the VDA supports external surfaces, we must wait for the surface before // completing initialization. This will be called by OnSurfaceAvailable() once // the surface is known or immediately by Initialize() if external surfaces // are unsupported. - void CompleteInitialization( - int surface_id, - const base::Optional<base::UnguessableToken>& token); + void CompleteInitialization(const OverlayInfo& overlay_info); bool needs_bitstream_conversion_;
diff --git a/media/gpu/android_video_decode_accelerator.cc b/media/gpu/android_video_decode_accelerator.cc index dd1061f4..fec2ce78 100644 --- a/media/gpu/android_video_decode_accelerator.cc +++ b/media/gpu/android_video_decode_accelerator.cc
@@ -113,8 +113,7 @@ // software fallback exists. bool ShouldDeferSurfaceCreation( AVDACodecAllocator* codec_allocator, - int surface_id, - base::Optional<base::UnguessableToken> overlay_routing_token, + const OverlayInfo& overlay_info, VideoCodec codec, const AndroidVideoDecodeAccelerator::PlatformConfig& platform_config) { if (platform_config.force_deferred_surface_creation) @@ -122,7 +121,7 @@ // TODO(liberato): We might still want to defer if we've got a routing // token. It depends on whether we want to use it right away or not. - if (surface_id != SurfaceManager::kNoSurfaceID || overlay_routing_token) + if (overlay_info.HasValidSurfaceId() || overlay_info.HasValidRoutingToken()) return false; return codec == kCodecH264 && codec_allocator->IsAnyRegisteredAVDA() && @@ -359,12 +358,11 @@ // If we're low on resources, we may decide to defer creation of the surface // until the codec is actually used. - if (ShouldDeferSurfaceCreation(codec_allocator_, config_.surface_id, - config_.overlay_routing_token, + if (ShouldDeferSurfaceCreation(codec_allocator_, config_.overlay_info, codec_config_->codec, platform_config_)) { // We should never be here if a SurfaceView is required. // TODO(liberato): This really isn't true with AndroidOverlay. - DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID); + DCHECK(!config_.overlay_info.HasValidSurfaceId()); defer_surface_creation_ = true; } @@ -416,18 +414,24 @@ // surface creation for other reasons, in which case the sync path with just // signal success optimistically. if (during_initialize_ && !deferred_initialization_pending_) { - DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID); - DCHECK(!config_.overlay_routing_token); + DCHECK(!config_.overlay_info.HasValidSurfaceId()); + DCHECK(!config_.overlay_info.HasValidRoutingToken()); OnSurfaceTransition(nullptr); return; } - // If we have a surface, then notify |surface_chooser_| about it. + // If we have a surface, then notify |surface_chooser_| about it. If we were + // told not to use an overlay (kNoSurfaceID or a null routing token), then we + // leave the factory blank. AndroidOverlayFactoryCB factory; - if (config_.surface_id != SurfaceManager::kNoSurfaceID) - factory = base::Bind(&CreateContentVideoViewOverlay, config_.surface_id); - else if (config_.overlay_routing_token && overlay_factory_cb_) - factory = base::Bind(overlay_factory_cb_, *config_.overlay_routing_token); + if (config_.overlay_info.HasValidSurfaceId()) { + factory = base::Bind(&CreateContentVideoViewOverlay, + config_.overlay_info.surface_id); + } else if (config_.overlay_info.HasValidRoutingToken() && + overlay_factory_cb_) { + factory = + base::Bind(overlay_factory_cb_, *config_.overlay_info.routing_token); + } // Notify |surface_chooser_| that we've started. This guarantees that we'll // get a callback. It might not be a synchronous callback, but we're not in @@ -1250,28 +1254,42 @@ StartCodecDrain(DRAIN_FOR_RESET); } -void AndroidVideoDecodeAccelerator::SetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token) { +void AndroidVideoDecodeAccelerator::SetOverlayInfo( + const OverlayInfo& overlay_info) { DVLOG(1) << __func__; DCHECK(thread_checker_.CalledOnValidThread()); - // It's possible that we'll receive a SetSurface before initializing the - // surface chooser. For example, if we defer surface creation, then we'll - // signal success to WMPI before initializing it. WMPI is free to change the - // surface. In this case, just pretend that |surface_id| is the initial one. - if (state_ == BEFORE_OVERLAY_INIT) { - config_.surface_id = surface_id; - config_.overlay_routing_token = routing_token; + // Update |config_| to contain the most recent info. Also save a copy, so + // that we can check for duplicate info later. + OverlayInfo previous_info = config_.overlay_info; + config_.overlay_info = overlay_info; + + // It's possible that we'll receive SetSurface before initializing the surface + // chooser. For example, if we defer surface creation, then we'll signal + // success to WMPI before initializing it. WMPI is then free to change + // |surface_id|. In this case, take no additional action, since |config_| is + // up to date. We'll use it later. + if (state_ == BEFORE_OVERLAY_INIT) + return; + + // Note that these might be kNoSurfaceID / empty. In that case, we will + // revoke the factory. + int32_t surface_id = overlay_info.surface_id; + OverlayInfo::RoutingToken routing_token = overlay_info.routing_token; + + // We don't want to change the factory unless this info has actually changed. + // We'll get the same info many times if some other part of the config is now + // different, such as fullscreen state. + if (surface_id == previous_info.surface_id && + routing_token == previous_info.routing_token) { return; } AndroidOverlayFactoryCB factory; - if (routing_token && overlay_factory_cb_) { + if (routing_token && overlay_factory_cb_) factory = base::Bind(overlay_factory_cb_, *routing_token); - } else if (surface_id != SurfaceManager::kNoSurfaceID) { + else if (surface_id != SurfaceManager::kNoSurfaceID) factory = base::Bind(&CreateContentVideoViewOverlay, surface_id); - } surface_chooser_->ReplaceOverlayFactory(std::move(factory)); }
diff --git a/media/gpu/android_video_decode_accelerator.h b/media/gpu/android_video_decode_accelerator.h index f1e6c15..6f1458447 100644 --- a/media/gpu/android_video_decode_accelerator.h +++ b/media/gpu/android_video_decode_accelerator.h
@@ -79,9 +79,7 @@ void ReusePictureBuffer(int32_t picture_buffer_id) override; void Flush() override; void Reset() override; - void SetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token) override; + void SetOverlayInfo(const OverlayInfo& overlay_info) override; void Destroy() override; bool TryToSetupDecodeOnSeparateThread( const base::WeakPtr<Client>& decode_client,
diff --git a/media/gpu/android_video_decode_accelerator_unittest.cc b/media/gpu/android_video_decode_accelerator_unittest.cc index b8468b40..3a8f8b82 100644 --- a/media/gpu/android_video_decode_accelerator_unittest.cc +++ b/media/gpu/android_video_decode_accelerator_unittest.cc
@@ -185,7 +185,7 @@ // Initialize |vda_|, providing a new surface for it. You may get the surface // by asking |codec_allocator_|. void InitializeAVDAWithOverlay() { - config_.surface_id = 123; + config_.overlay_info.surface_id = 123; ASSERT_TRUE(InitializeAVDA()); base::RunLoop().RunUntilIdle(); ASSERT_TRUE(chooser_->factory_); @@ -336,7 +336,7 @@ // in a state that AVDA isn't supposed to handle (e.g., if we give it a // surface, then it would never decide to defer surface creation). platform_config_.force_deferred_surface_creation = true; - config_.surface_id = SurfaceManager::kNoSurfaceID; + config_.overlay_info.surface_id = SurfaceManager::kNoSurfaceID; EXPECT_CALL(*chooser_, MockInitialize()).Times(0); EXPECT_CALL(client_, NotifyInitializationComplete(true)); @@ -493,6 +493,7 @@ // doesn't get confused about which surface is in use. So, we assume that it // doesn't signal an error, and we check that it releases the right surface // with the codec. + SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); EXPECT_CALL(client_, NotifyError(_)).Times(0); platform_config_.allow_setsurface = false; @@ -508,6 +509,7 @@ OnSurfaceDestroyedWithoutSetSurfaceFreesTheCodec) { // If AVDA receives OnSurfaceDestroyed without support for SetSurface, then it // should free the codec. + SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); platform_config_.allow_setsurface = false; InitializeAVDAWithOverlay(); EXPECT_CALL(*codec_allocator_.most_recent_codec(), SetSurface(_)).Times(0); @@ -541,4 +543,29 @@ base::RunLoop().RunUntilIdle(); } +TEST_F(AndroidVideoDecodeAcceleratorTest, + OverlayInfoWithDuplicateSurfaceIDDoesntChangeTheFactory) { + // Send OverlayInfo with duplicate info, and verify that it doesn't change + // the factory. + SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); + InitializeAVDAWithOverlay(); + + EXPECT_CALL(*chooser_, MockReplaceOverlayFactory()).Times(0); + OverlayInfo overlay_info = config_.overlay_info; + avda()->SetOverlayInfo(overlay_info); +} + +TEST_F(AndroidVideoDecodeAcceleratorTest, + OverlayInfoWithNewSurfaceIDDoesChangeTheFactory) { + // Send OverlayInfo with new surface info, and verify that it does change the + // overlay factory. + SKIP_IF_MEDIACODEC_IS_NOT_AVAILABLE(); + InitializeAVDAWithOverlay(); + + EXPECT_CALL(*chooser_, MockReplaceOverlayFactory()).Times(1); + OverlayInfo overlay_info = config_.overlay_info; + overlay_info.surface_id++; + avda()->SetOverlayInfo(overlay_info); +} + } // namespace media
diff --git a/media/gpu/dxva_video_decode_accelerator_win.cc b/media/gpu/dxva_video_decode_accelerator_win.cc index 0fdf3d6c..47b9343 100644 --- a/media/gpu/dxva_video_decode_accelerator_win.cc +++ b/media/gpu/dxva_video_decode_accelerator_win.cc
@@ -1180,12 +1180,12 @@ main_thread_task_runner_->PostTask( FROM_HERE, - base::Bind(&DXVAVideoDecodeAccelerator::NotifyResetDone, weak_ptr_)); - main_thread_task_runner_->PostTask( - FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::NotifyInputBuffersDropped, weak_ptr_, std::move(pending_input_buffers_))); pending_input_buffers_.clear(); + main_thread_task_runner_->PostTask( + FROM_HERE, + base::Bind(&DXVAVideoDecodeAccelerator::NotifyResetDone, weak_ptr_)); RETURN_AND_NOTIFY_ON_FAILURE(StartDecoderThread(), "Failed to start decoder thread.",
diff --git a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc index e0cc707e..f8c85d5 100644 --- a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc +++ b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.cc
@@ -169,14 +169,13 @@ Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_)); } -void GpuVideoDecodeAcceleratorHost::SetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token) { +void GpuVideoDecodeAcceleratorHost::SetOverlayInfo( + const OverlayInfo& overlay_info) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!channel_) return; - Send(new AcceleratedVideoDecoderMsg_SetSurface(decoder_route_id_, surface_id, - routing_token)); + Send(new AcceleratedVideoDecoderMsg_SetOverlayInfo(decoder_route_id_, + overlay_info)); } void GpuVideoDecodeAcceleratorHost::Destroy() {
diff --git a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.h b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.h index c80f4629..48351b1 100644 --- a/media/gpu/ipc/client/gpu_video_decode_accelerator_host.h +++ b/media/gpu/ipc/client/gpu_video_decode_accelerator_host.h
@@ -47,8 +47,7 @@ void ReusePictureBuffer(int32_t picture_buffer_id) override; void Flush() override; void Reset() override; - void SetSurface(int32_t surface_id, - const base::Optional<base::UnguessableToken>& token) override; + void SetOverlayInfo(const OverlayInfo&) override; void Destroy() override; // gpu::CommandBufferProxyImpl::DeletionObserver implemetnation.
diff --git a/media/gpu/ipc/common/media_messages.h b/media/gpu/ipc/common/media_messages.h index 506c391..2c56e251 100644 --- a/media/gpu/ipc/common/media_messages.h +++ b/media/gpu/ipc/common/media_messages.h
@@ -12,6 +12,7 @@ #include "gpu/ipc/common/gpu_param_traits_macros.h" #include "ipc/ipc_message_macros.h" #include "ipc/param_traits_macros.h" +#include "media/base/overlay_info.h" #include "media/gpu/ipc/common/media_param_traits.h" #include "media/video/jpeg_decode_accelerator.h" #include "media/video/video_decode_accelerator.h" @@ -92,11 +93,9 @@ // Send reset request to the decoder. IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Reset) -// Send a surface id to the decoder. -IPC_MESSAGE_ROUTED2( - AcceleratedVideoDecoderMsg_SetSurface, - int32_t, /* Surface ID */ - base::Optional<base::UnguessableToken>); /* AndroidOverlay routing token */ +// Send overlay info to the decoder. +IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_SetOverlayInfo, + media::OverlayInfo); // Send destroy request to the decoder. IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Destroy)
diff --git a/media/gpu/ipc/common/media_param_traits_macros.h b/media/gpu/ipc/common/media_param_traits_macros.h index b77189c..3fcbefd 100644 --- a/media/gpu/ipc/common/media_param_traits_macros.h +++ b/media/gpu/ipc/common/media_param_traits_macros.h
@@ -8,6 +8,7 @@ #include "gpu/config/gpu_info.h" #include "ipc/ipc_message_macros.h" #include "media/base/ipc/media_param_traits.h" +#include "media/base/overlay_info.h" #include "media/gpu/ipc/common/create_video_encoder_params.h" #include "media/video/jpeg_decode_accelerator.h" #include "media/video/video_decode_accelerator.h" @@ -25,7 +26,7 @@ IPC_STRUCT_TRAITS_MEMBER(encryption_scheme) IPC_STRUCT_TRAITS_MEMBER(cdm_id) IPC_STRUCT_TRAITS_MEMBER(is_deferred_initialization_allowed) - IPC_STRUCT_TRAITS_MEMBER(surface_id) + IPC_STRUCT_TRAITS_MEMBER(overlay_info) IPC_STRUCT_TRAITS_MEMBER(initial_expected_coded_size) IPC_STRUCT_TRAITS_MEMBER(supported_output_formats) IPC_STRUCT_TRAITS_MEMBER(sps) @@ -41,4 +42,10 @@ IPC_STRUCT_TRAITS_MEMBER(encoder_route_id) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(media::OverlayInfo) + IPC_STRUCT_TRAITS_MEMBER(surface_id) + IPC_STRUCT_TRAITS_MEMBER(routing_token) + IPC_STRUCT_TRAITS_MEMBER(is_fullscreen) +IPC_STRUCT_TRAITS_END() + #endif // MEDIA_GPU_IPC_COMMON_MEDIA_PARAM_TRAITS_MACROS_H_
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc index 192f12e..0394ce47 100644 --- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc +++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -210,7 +210,8 @@ OnReusePictureBuffer) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Flush, OnFlush) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Reset, OnReset) - IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_SetSurface, OnSetSurface) + IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_SetOverlayInfo, + OnSetOverlayInfo) IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderMsg_Destroy, OnDestroy) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -510,11 +511,10 @@ video_decode_accelerator_->Reset(); } -void GpuVideoDecodeAccelerator::OnSetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token) { +void GpuVideoDecodeAccelerator::OnSetOverlayInfo( + const OverlayInfo& overlay_info) { DCHECK(video_decode_accelerator_); - video_decode_accelerator_->SetSurface(surface_id, routing_token); + video_decode_accelerator_->SetOverlayInfo(overlay_info); } void GpuVideoDecodeAccelerator::OnDestroy() {
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.h b/media/gpu/ipc/service/gpu_video_decode_accelerator.h index db2c79d..53ce55b 100644 --- a/media/gpu/ipc/service/gpu_video_decode_accelerator.h +++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.h
@@ -98,9 +98,7 @@ void OnReusePictureBuffer(int32_t picture_buffer_id); void OnFlush(); void OnReset(); - void OnSetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token); + void OnSetOverlayInfo(const OverlayInfo& overlay_info); void OnDestroy(); // Called on IO thread when |filter_| has been removed.
diff --git a/media/video/video_decode_accelerator.cc b/media/video/video_decode_accelerator.cc index bc37cca..873e847 100644 --- a/media/video/video_decode_accelerator.cc +++ b/media/video/video_decode_accelerator.cc
@@ -45,10 +45,8 @@ NOTREACHED() << "Buffer import not supported."; } -void VideoDecodeAccelerator::SetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token) { - NOTREACHED() << "Surfaces are not supported."; +void VideoDecodeAccelerator::SetOverlayInfo(const OverlayInfo& overlay_info) { + NOTREACHED() << "Overlays are not supported."; } GLenum VideoDecodeAccelerator::GetSurfaceInternalFormat() const {
diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h index e61f6e2..b37a85e 100644 --- a/media/video/video_decode_accelerator.h +++ b/media/video/video_decode_accelerator.h
@@ -17,6 +17,7 @@ #include "media/base/bitstream_buffer.h" #include "media/base/cdm_context.h" #include "media/base/encryption_scheme.h" +#include "media/base/overlay_info.h" #include "media/base/surface_manager.h" #include "media/base/video_decoder_config.h" #include "media/video/picture.h" @@ -150,14 +151,9 @@ // Whether the client supports deferred initialization. bool is_deferred_initialization_allowed = false; - // An optional graphics surface that the VDA should render to. For setting - // an output SurfaceView on Android. It's only valid when not equal to - // |kNoSurfaceID|. - // TODO(liberato): should this be Optional<> instead? - int surface_id = SurfaceManager::kNoSurfaceID; - - // An optional routing token for AndroidOverlay. - base::Optional<base::UnguessableToken> overlay_routing_token; + // Optional overlay info available at startup, rather than waiting for the + // VDA to receive a callback. + OverlayInfo overlay_info; // Coded size of the video frame hint, subject to change. gfx::Size initial_expected_coded_size = gfx::Size(320, 240); @@ -313,9 +309,7 @@ // previously set surface in favor of an internally generated texture. // |routing_token| is an optional AndroidOverlay routing token. At most one // should be non-empty. - virtual void SetSurface( - int32_t surface_id, - const base::Optional<base::UnguessableToken>& routing_token); + virtual void SetOverlayInfo(const OverlayInfo& overlay_info); // Destroys the decoder: all pending inputs are dropped immediately and the // component is freed. This call may asynchornously free system resources,
diff --git a/net/BUILD.gn b/net/BUILD.gn index 3bfe976..3ee51c9 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -36,7 +36,7 @@ use_v8_in_net = !is_ios && !is_proto_quic enable_built_in_dns = !is_ios && !is_proto_quic -enable_net_mojo = !is_ios && !is_android && !is_proto_quic +enable_net_mojo = !is_ios && !is_proto_quic # True if certificates are represented with DER byte buffers. This can be true # in addition to use_openssl_certs or use_nss_certs, in that case byte certs @@ -2657,6 +2657,8 @@ "proxy/proxy_resolver_factory_mojo.h", "proxy/proxy_service_mojo.cc", "proxy/proxy_service_mojo.h", + "url_request/url_request_context_builder_mojo.cc", + "url_request/url_request_context_builder_mojo.h", ] public_deps = [ @@ -2691,33 +2693,6 @@ } } -if (use_v8_in_net) { - source_set("net_context_builder_with_v8") { - sources = [ - "url_request/url_request_context_builder_v8.cc", - "url_request/url_request_context_builder_v8.h", - ] - - defines = [] - - deps = [ - ":net", - ":net_with_v8", - "//base", - ] - - if (enable_net_mojo) { - deps += [ - ":net_browser_services", - "//mojo/public/cpp/bindings", - "//net/interfaces", - ] - - defines += [ "ENABLE_NET_MOJO" ] - } - } -} - if (!is_ios && !is_android) { executable("cert_verify_tool") { testonly = true @@ -5089,8 +5064,8 @@ "url_request/sdch_dictionary_fetcher_unittest.cc", "url_request/url_fetcher_impl_unittest.cc", "url_request/url_fetcher_response_writer_unittest.cc", + "url_request/url_request_context_builder_mojo_unittest.cc", "url_request/url_request_context_builder_unittest.cc", - "url_request/url_request_context_builder_v8_unittest.cc", "url_request/url_request_context_unittest.cc", "url_request/url_request_data_job_unittest.cc", "url_request/url_request_file_dir_job_unittest.cc", @@ -5329,16 +5304,12 @@ } if (use_v8_in_net) { - deps += [ - ":net_context_builder_with_v8", - ":net_with_v8", - ] + deps += [ ":net_with_v8" ] } else { sources -= [ "proxy/proxy_resolver_v8_tracing_unittest.cc", "proxy/proxy_resolver_v8_tracing_wrapper_unittest.cc", "proxy/proxy_resolver_v8_unittest.cc", - "url_request/url_request_context_builder_v8_unittest.cc", ] } @@ -5348,8 +5319,6 @@ ":net_utility_services", "//mojo/edk/system", ] - - defines += [ "ENABLE_NET_MOJO" ] } else { sources -= [ "dns/host_resolver_mojo_unittest.cc", @@ -5361,6 +5330,7 @@ "proxy/proxy_service_mojo_unittest.cc", "proxy/test_mojo_proxy_resolver_factory.cc", "proxy/test_mojo_proxy_resolver_factory.h", + "url_request/url_request_context_builder_mojo_unittest.cc", ] }
diff --git a/net/test/run_all_unittests.cc b/net/test/run_all_unittests.cc index 78307f7..becfa33 100644 --- a/net/test/run_all_unittests.cc +++ b/net/test/run_all_unittests.cc
@@ -18,7 +18,7 @@ #include "net/android/net_jni_registrar.h" #endif -#if !defined(OS_ANDROID) && !defined(OS_IOS) +#if !defined(OS_IOS) #include "mojo/edk/embedder/embedder.h" // nogncheck #endif @@ -81,7 +81,7 @@ NetTestSuite test_suite(argc, argv); ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled(false); -#if !defined(OS_ANDROID) && !defined(OS_IOS) +#if !defined(OS_IOS) mojo::edk::Init(); #endif
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc index da93630..30558b6 100644 --- a/net/url_request/url_request_context_builder.cc +++ b/net/url_request/url_request_context_builder.cc
@@ -208,6 +208,8 @@ sdch_enabled_(false), cookie_store_set_by_client_(false), net_log_(nullptr), + pac_quick_check_enabled_(true), + pac_sanitize_url_policy_(ProxyService::SanitizeUrlPolicy::SAFE), socket_performance_watcher_factory_(nullptr) { } @@ -407,6 +409,8 @@ CreateProxyService(std::move(proxy_config_service_), context.get(), context->host_resolver(), context->network_delegate(), context->net_log()); + proxy_service_->set_quick_check_enabled(pac_quick_check_enabled_); + proxy_service_->set_sanitize_url_policy(pac_sanitize_url_policy_); } storage->set_proxy_service(std::move(proxy_service_));
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h index 90ed04c..a67f6aa8 100644 --- a/net/url_request/url_request_context_builder.h +++ b/net/url_request/url_request_context_builder.h
@@ -116,6 +116,20 @@ proxy_config_service_ = std::move(proxy_config_service); } + // Sets whether quick PAC checks are enabled. Defaults to true. Ignored if + // a ProxyService is set directly. + void set_pac_quick_check_enabled(bool pac_quick_check_enabled) { + pac_quick_check_enabled_ = pac_quick_check_enabled; + } + + // Sets policy for sanitizing URLs before passing them to a PAC. Defaults to + // ProxyService::SanitizeUrlPolicy::SAFE. Ignored if + // a ProxyService is set directly. + void set_pac_sanitize_url_policy( + net::ProxyService::SanitizeUrlPolicy pac_sanitize_url_policy) { + pac_sanitize_url_policy_ = pac_sanitize_url_policy; + } + // Sets the proxy service. If one is not provided, by default, uses system // libraries to evaluate PAC scripts, if available (And if not, skips PAC // resolution). Subclasses may override CreateProxyService for different @@ -349,6 +363,8 @@ std::unique_ptr<HostResolver> host_resolver_; std::unique_ptr<ChannelIDService> channel_id_service_; std::unique_ptr<ProxyConfigService> proxy_config_service_; + bool pac_quick_check_enabled_; + ProxyService::SanitizeUrlPolicy pac_sanitize_url_policy_; std::unique_ptr<ProxyService> proxy_service_; std::unique_ptr<NetworkDelegate> network_delegate_; std::unique_ptr<ProxyDelegate> proxy_delegate_;
diff --git a/net/url_request/url_request_context_builder_mojo.cc b/net/url_request/url_request_context_builder_mojo.cc new file mode 100644 index 0000000..43a4fc2 --- /dev/null +++ b/net/url_request/url_request_context_builder_mojo.cc
@@ -0,0 +1,45 @@ +// 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 "net/url_request/url_request_context_builder_mojo.h" + +#include "base/logging.h" +#include "build/build_config.h" +#include "net/proxy/proxy_config_service.h" +#include "net/proxy/proxy_script_fetcher_impl.h" +#include "net/proxy/proxy_service_mojo.h" + +namespace net { + +URLRequestContextBuilderMojo::URLRequestContextBuilderMojo() + : dhcp_fetcher_factory_(new DhcpProxyScriptFetcherFactory()) {} + +URLRequestContextBuilderMojo::~URLRequestContextBuilderMojo() = default; + +std::unique_ptr<ProxyService> URLRequestContextBuilderMojo::CreateProxyService( + std::unique_ptr<ProxyConfigService> proxy_config_service, + URLRequestContext* url_request_context, + HostResolver* host_resolver, + NetworkDelegate* network_delegate, + NetLog* net_log) { + DCHECK(url_request_context); + DCHECK(host_resolver); + + if (!mojo_proxy_resolver_factory_) { + return URLRequestContextBuilder::CreateProxyService( + std::move(proxy_config_service), url_request_context, host_resolver, + network_delegate, net_log); + } + + std::unique_ptr<net::DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher = + dhcp_fetcher_factory_->Create(url_request_context); + std::unique_ptr<net::ProxyScriptFetcher> proxy_script_fetcher = + base::MakeUnique<ProxyScriptFetcherImpl>(url_request_context); + return CreateProxyServiceUsingMojoFactory( + mojo_proxy_resolver_factory_, std::move(proxy_config_service), + proxy_script_fetcher.release(), std::move(dhcp_proxy_script_fetcher), + host_resolver, net_log, network_delegate); +} + +} // namespace net
diff --git a/net/url_request/url_request_context_builder_mojo.h b/net/url_request/url_request_context_builder_mojo.h new file mode 100644 index 0000000..0610864c --- /dev/null +++ b/net/url_request/url_request_context_builder_mojo.h
@@ -0,0 +1,65 @@ +// 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 NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_MOJO_H_ +#define NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_MOJO_H_ + +#include <memory> + +#include "base/macros.h" +#include "build/build_config.h" +#include "net/proxy/dhcp_proxy_script_fetcher_factory.h" +#include "net/url_request/url_request_context_builder.h" + +namespace net { + +class HostResolver; +class NetLog; +class NetworkDelegate; +class MojoProxyResolverFactory; +class ProxyService; +class URLRequestContext; + +// Specialization of URLRequestContextBuilder that can create a ProxyService +// that uses a Mojo ProxyResolver. The consumer is responsible for providing +// the MojoProxyResolverFactory. If a PoxyService is set directly via the +// URLRequestContextBuilder API, it will be used instead. +class URLRequestContextBuilderMojo : public URLRequestContextBuilder { + public: + URLRequestContextBuilderMojo(); + ~URLRequestContextBuilderMojo() override; + + // Overrides default DhcpProxyScriptFetcherFactory. Ignored if no + // MojoProxyResolverFactory is provided. + void set_dhcp_fetcher_factory( + std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory) { + dhcp_fetcher_factory = std::move(dhcp_fetcher_factory_); + } + + // Sets Mojo factory used to create ProxyResolvers. If not set, falls back to + // URLRequestContext's default behavior. The passed in factory must outlive + // the URLRequestContext the builder creates. + void set_mojo_proxy_resolver_factory( + MojoProxyResolverFactory* mojo_proxy_resolver_factory) { + mojo_proxy_resolver_factory_ = mojo_proxy_resolver_factory; + } + + private: + std::unique_ptr<ProxyService> CreateProxyService( + std::unique_ptr<ProxyConfigService> proxy_config_service, + URLRequestContext* url_request_context, + HostResolver* host_resolver, + NetworkDelegate* network_delegate, + NetLog* net_log) override; + + std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory_; + + MojoProxyResolverFactory* mojo_proxy_resolver_factory_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilderMojo); +}; + +} // namespace net + +#endif // NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_MOJO_H_
diff --git a/net/url_request/url_request_context_builder_v8_unittest.cc b/net/url_request/url_request_context_builder_mojo_unittest.cc similarity index 76% rename from net/url_request/url_request_context_builder_v8_unittest.cc rename to net/url_request/url_request_context_builder_mojo_unittest.cc index f302d35..f413db7 100644 --- a/net/url_request/url_request_context_builder_v8_unittest.cc +++ b/net/url_request/url_request_context_builder_mojo_unittest.cc
@@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "net/url_request/url_request_context_builder_v8.h" +#include "net/url_request/url_request_context_builder_mojo.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "net/base/host_port_pair.h" #include "net/proxy/proxy_config.h" #include "net/proxy/proxy_config_service_fixed.h" +#include "net/proxy/test_mojo_proxy_resolver_factory.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" @@ -21,10 +22,6 @@ #include "testing/platform_test.h" #include "url/gurl.h" -#ifdef ENABLE_NET_MOJO -#include "net/proxy/test_mojo_proxy_resolver_factory.h" -#endif - namespace net { namespace { @@ -46,63 +43,19 @@ return std::move(response); } -class URLRequestContextBuilderV8Test : public PlatformTest { +class URLRequestContextBuilderMojoTest : public PlatformTest { protected: - URLRequestContextBuilderV8Test() { + URLRequestContextBuilderMojoTest() { test_server_.RegisterRequestHandler(base::Bind(&HandlePacRequest)); test_server_.AddDefaultHandlers( base::FilePath(FILE_PATH_LITERAL("net/data/url_request_unittest"))); } EmbeddedTestServer test_server_; - URLRequestContextBuilderV8 builder_; + URLRequestContextBuilderMojo builder_; }; -TEST_F(URLRequestContextBuilderV8Test, V8InProcess) { - EXPECT_TRUE(test_server_.Start()); - - builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>( - ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL(kPacPath)))); - std::unique_ptr<URLRequestContext> context(builder_.Build()); - - TestDelegate delegate; - std::unique_ptr<URLRequest> request(context->CreateRequest( - GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate, - TRAFFIC_ANNOTATION_FOR_TESTS)); - request->SetExtraRequestHeaderByName("Foo", "Bar", false); - request->Start(); - base::RunLoop().Run(); - EXPECT_EQ("Bar", delegate.data_received()); -} - -// Makes sure that pending PAC requests are correctly shutdown during teardown. -TEST_F(URLRequestContextBuilderV8Test, V8InProcessShutdownWithHungRequest) { - test_server::SimpleConnectionListener connection_listener( - 1, test_server::SimpleConnectionListener::FAIL_ON_ADDITIONAL_CONNECTIONS); - test_server_.SetConnectionListener(&connection_listener); - EXPECT_TRUE(test_server_.Start()); - - builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>( - ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL("/hung")))); - - std::unique_ptr<URLRequestContext> context(builder_.Build()); - TestDelegate delegate; - std::unique_ptr<URLRequest> request(context->CreateRequest( - GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate, - TRAFFIC_ANNOTATION_FOR_TESTS)); - request->Start(); - connection_listener.WaitForConnections(); - - // Have to shut down the test server before |connection_listener| falls out of - // scope. - EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); - - // Tearing down the URLRequestContext should not cause an AssertNoURLRequests - // failure. -} - -#ifdef ENABLE_NET_MOJO -TEST_F(URLRequestContextBuilderV8Test, MojoProxyResolver) { +TEST_F(URLRequestContextBuilderMojoTest, MojoProxyResolver) { EXPECT_TRUE(test_server_.Start()); TestMojoProxyResolverFactory::GetInstance()->set_resolver_created(false); @@ -124,7 +77,36 @@ // Make sure that the Mojo factory was used. EXPECT_TRUE(TestMojoProxyResolverFactory::GetInstance()->resolver_created()); } -#endif // ENABLE_NET_MOJO + +// Makes sure that pending PAC requests are correctly shut down during teardown. +TEST_F(URLRequestContextBuilderMojoTest, ShutdownWithHungRequest) { + test_server::SimpleConnectionListener connection_listener( + 1, test_server::SimpleConnectionListener::FAIL_ON_ADDITIONAL_CONNECTIONS); + test_server_.SetConnectionListener(&connection_listener); + EXPECT_TRUE(test_server_.Start()); + + builder_.set_proxy_config_service(base::MakeUnique<ProxyConfigServiceFixed>( + ProxyConfig::CreateFromCustomPacURL(test_server_.GetURL("/hung")))); + builder_.set_mojo_proxy_resolver_factory( + TestMojoProxyResolverFactory::GetInstance()); + + std::unique_ptr<URLRequestContext> context(builder_.Build()); + TestDelegate delegate; + std::unique_ptr<URLRequest> request(context->CreateRequest( + GURL("http://hats:12345/echoheader?Foo"), DEFAULT_PRIORITY, &delegate, + TRAFFIC_ANNOTATION_FOR_TESTS)); + request->Start(); + connection_listener.WaitForConnections(); + + // Tearing down the URLRequestContext should not cause an AssertNoURLRequests + // failure. + request.reset(); + context.reset(); + + // Have to shut down the test server before |connection_listener| falls out of + // scope. + EXPECT_TRUE(test_server_.ShutdownAndWaitUntilComplete()); +} } // namespace
diff --git a/net/url_request/url_request_context_builder_v8.cc b/net/url_request/url_request_context_builder_v8.cc deleted file mode 100644 index d16f4d7..0000000 --- a/net/url_request/url_request_context_builder_v8.cc +++ /dev/null
@@ -1,64 +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 "net/url_request/url_request_context_builder_v8.h" - -#include "base/logging.h" -#include "net/proxy/proxy_config_service.h" -#include "net/proxy/proxy_script_fetcher_impl.h" -#include "net/proxy/proxy_service_v8.h" - -#ifdef ENABLE_NET_MOJO -#include "net/proxy/proxy_service_mojo.h" -#endif - -namespace net { - -URLRequestContextBuilderV8::URLRequestContextBuilderV8() - : dhcp_fetcher_factory_(new DhcpProxyScriptFetcherFactory()) {} - -URLRequestContextBuilderV8::~URLRequestContextBuilderV8() = default; - -std::unique_ptr<ProxyService> URLRequestContextBuilderV8::CreateProxyService( - std::unique_ptr<ProxyConfigService> proxy_config_service, - URLRequestContext* url_request_context, - HostResolver* host_resolver, - NetworkDelegate* network_delegate, - NetLog* net_log) { - DCHECK(url_request_context); - DCHECK(host_resolver); - - if (!use_v8_) { - return URLRequestContextBuilder::CreateProxyService( - std::move(proxy_config_service), url_request_context, host_resolver, - network_delegate, net_log); - } - - std::unique_ptr<net::DhcpProxyScriptFetcher> dhcp_proxy_script_fetcher = - dhcp_fetcher_factory_->Create(url_request_context); - std::unique_ptr<net::ProxyScriptFetcher> proxy_script_fetcher = - base::MakeUnique<ProxyScriptFetcherImpl>(url_request_context); - std::unique_ptr<ProxyService> proxy_service; -#ifdef ENABLE_NET_MOJO - if (mojo_proxy_resolver_factory_) { - proxy_service = CreateProxyServiceUsingMojoFactory( - mojo_proxy_resolver_factory_, std::move(proxy_config_service), - proxy_script_fetcher.release(), std::move(dhcp_proxy_script_fetcher), - host_resolver, net_log, network_delegate); - } -#endif // ENABLE_NET_MOJO - if (!proxy_service) { - proxy_service = CreateProxyServiceUsingV8ProxyResolver( - std::move(proxy_config_service), proxy_script_fetcher.release(), - std::move(dhcp_proxy_script_fetcher), host_resolver, net_log, - network_delegate); - } - - proxy_service->set_quick_check_enabled(quick_check_enabled_); - proxy_service->set_sanitize_url_policy(sanitize_url_policy_); - - return proxy_service; -} - -} // namespace net
diff --git a/net/url_request/url_request_context_builder_v8.h b/net/url_request/url_request_context_builder_v8.h deleted file mode 100644 index e44c359..0000000 --- a/net/url_request/url_request_context_builder_v8.h +++ /dev/null
@@ -1,92 +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 NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_ -#define NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_ - -#include <memory> - -#include "base/macros.h" -#include "net/proxy/dhcp_proxy_script_fetcher_factory.h" -#include "net/proxy/proxy_service.h" -#include "net/url_request/url_request_context_builder.h" - -namespace net { - -class HostResolver; -class NetLog; -class NetworkDelegate; -class MojoProxyResolverFactory; -class URLRequestContext; - -// Specialization of URLRequestContextBuilder that can create a ProxyService -// that uses a V8 ProxyResolver. PAC scripts are run by V8 in process, by -// default, but a Mojo factory can be passed in for out-of-process resolution. -// PAC scripts will be fetched using the request context itself. If a -// PoxyService is set directly via the URLRequestContextBuilder API, it will be -// used instead of the one this class normally creates. -class URLRequestContextBuilderV8 : public URLRequestContextBuilder { - public: - URLRequestContextBuilderV8(); - ~URLRequestContextBuilderV8() override; - - // If set to false, the URLrequestContextBuilder will create a ProxyService, - // which won't use V8. Defaults to true. - void set_use_v8(bool use_v8) { use_v8_ = use_v8; } - - // Sets whether quick PAC checks are enabled. Defaults to true. Ignored if - // use_v8 is false. - void set_quick_check_enabled(bool quick_check_enabled) { - quick_check_enabled_ = quick_check_enabled; - } - - // Sets policy for sanitizing URLs before passing them a PAC. Defaults to - // ProxyService::SanitizeUrlPolicy::SAFE. Ignored if use_v8 is false. - void set_pac_sanitize_url_policy( - net::ProxyService::SanitizeUrlPolicy sanitize_url_policy) { - sanitize_url_policy_ = sanitize_url_policy; - } - - // Overrides default DhcpProxyScriptFetcherFactory. Ignored if use_v8 is - // false. - void set_dhcp_fetcher_factory( - std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory) { - dhcp_fetcher_factory = std::move(dhcp_fetcher_factory_); - } - -#ifdef ENABLE_NET_MOJO - // Sets Mojo factory used to create ProxyResolvers. If not set, V8 will be - // used in process instead of Mojo. Ignored if use_v8 is false. The passed in - // factory must outlive the URLRequestContext the builder creates. - void set_mojo_proxy_resolver_factory( - MojoProxyResolverFactory* mojo_proxy_resolver_factory) { - mojo_proxy_resolver_factory_ = mojo_proxy_resolver_factory; - } -#endif // ENABLE_NET_MOJO - - private: - std::unique_ptr<ProxyService> CreateProxyService( - std::unique_ptr<ProxyConfigService> proxy_config_service, - URLRequestContext* url_request_context, - HostResolver* host_resolver, - NetworkDelegate* network_delegate, - NetLog* net_log) override; - - bool use_v8_ = true; - bool quick_check_enabled_ = true; - net::ProxyService::SanitizeUrlPolicy sanitize_url_policy_ = - net::ProxyService::SanitizeUrlPolicy::SAFE; - - std::unique_ptr<DhcpProxyScriptFetcherFactory> dhcp_fetcher_factory_; - -#ifdef ENABLE_NET_MOJO - MojoProxyResolverFactory* mojo_proxy_resolver_factory_ = nullptr; -#endif - - DISALLOW_COPY_AND_ASSIGN(URLRequestContextBuilderV8); -}; - -} // namespace net - -#endif // NET_URL_REQUEST_URL_REQUEST_CONTEXT_BUILDER_V8_H_
diff --git a/printing/backend/cups_jobs.cc b/printing/backend/cups_jobs.cc index e73ae8fb..80daed7 100644 --- a/printing/backend/cups_jobs.cc +++ b/printing/backend/cups_jobs.cc
@@ -11,8 +11,12 @@ #include <memory> #include "base/logging.h" +#include "base/stl_util.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" +#include "base/threading/thread_restrictions.h" +#include "base/version.h" +#include "printing/backend/cups_deleters.h" namespace printing { namespace { @@ -26,6 +30,11 @@ const char kPrinterStateReasons[] = "printer-state-reasons"; const char kPrinterStateMessage[] = "printer-state-message"; +const char kPrinterMakeAndModel[] = "printer-make-and-model"; +const char kIppVersionsSupported[] = "ipp-versions-supported"; +const char kIppFeaturesSupported[] = "ipp-features-supported"; +const char kDocumentFormatSupported[] = "document-format-supported"; + // job attributes const char kJobUri[] = "job-uri"; const char kJobId[] = "job-id"; @@ -44,6 +53,9 @@ const char kCompleted[] = "completed"; const char kNotCompleted[] = "not-completed"; +// ipp features +const char kIppEverywhere[] = "ipp-everywhere"; + // printer state severities const char kSeverityReport[] = "report"; const char kSeverityWarn[] = "warning"; @@ -88,10 +100,18 @@ constexpr std::array<const char* const, 3> kPrinterAttributes{ {kPrinterState, kPrinterStateReasons, kPrinterStateMessage}}; -std::unique_ptr<ipp_t, void (*)(ipp_t*)> WrapIpp(ipp_t* ipp) { - return std::unique_ptr<ipp_t, void (*)(ipp_t*)>(ipp, &ippDelete); +constexpr std::array<const char* const, 4> kPrinterInfo{ + {kPrinterMakeAndModel, kIppVersionsSupported, kIppFeaturesSupported, + kDocumentFormatSupported}}; + +using ScopedIppPtr = std::unique_ptr<ipp_t, void (*)(ipp_t*)>; + +ScopedIppPtr WrapIpp(ipp_t* ipp) { + return ScopedIppPtr(ipp, &ippDelete); } +using ScopedHttpPtr = std::unique_ptr<http_t, HttpDeleter>; + // Converts an IPP attribute |attr| to the appropriate JobState enum. CupsJob::JobState ToJobState(ipp_attribute_t* attr) { DCHECK_EQ(IPP_TAG_ENUM, ippGetValueTag(attr)); @@ -281,6 +301,40 @@ return base::StringPrintf("ipp://localhost/printers/%s", id.c_str()); } +// Extracts PrinterInfo fields from |response| and populates |printer_info|. +// Returns true if at least printer-make-and-model and ipp-versions-supported +// were read. +bool ParsePrinterInfo(ipp_t* response, PrinterInfo* printer_info) { + for (ipp_attribute_t* attr = ippFirstAttribute(response); attr != nullptr; + attr = ippNextAttribute(response)) { + base::StringPiece name = ippGetName(attr); + + if (name == base::StringPiece(kPrinterMakeAndModel)) { + DCHECK_EQ(IPP_TAG_TEXT, ippGetValueTag(attr)); + printer_info->make_and_model = ippGetString(attr, 0, nullptr); + } else if (name == base::StringPiece(kIppVersionsSupported)) { + std::vector<std::string> ipp_versions; + ParseCollection(attr, &ipp_versions); + for (const std::string& version : ipp_versions) { + base::Version major_minor(version); + if (major_minor.IsValid()) { + printer_info->ipp_versions.push_back(major_minor); + } + } + } else if (name == base::StringPiece(kIppFeaturesSupported)) { + std::vector<std::string> features; + ParseCollection(attr, &features); + printer_info->ipp_everywhere = + base::ContainsValue(features, kIppEverywhere); + } else if (name == base::StringPiece(kDocumentFormatSupported)) { + ParseCollection(attr, &printer_info->document_formats); + } + } + + return !printer_info->make_and_model.empty() && + !printer_info->ipp_versions.empty(); +} + } // namespace CupsJob::CupsJob() = default; @@ -295,6 +349,10 @@ PrinterStatus::~PrinterStatus() = default; +PrinterInfo::PrinterInfo() = default; + +PrinterInfo::~PrinterInfo() = default; + void ParseJobsResponse(ipp_t* response, const std::string& printer_id, std::vector<CupsJob>* jobs) { @@ -309,6 +367,40 @@ } } +// Returns an IPP response for a Get-Printer-Attributes request to |http|. For +// print servers, |printer_uri| is used as the printer-uri value. +// |resource_path| specifies the path portion of the server URI. +// |num_attributes| is the number of attributes in |attributes| which should be +// a list of IPP attributes. |status| is updated with status code for the +// request. A successful request will have the |status| IPP_STATUS_OK. +ScopedIppPtr GetPrinterAttributes(http_t* http, + const std::string& printer_uri, + const std::string& resource_path, + int num_attributes, + const char* const* attributes, + ipp_status_t* status) { + base::ThreadRestrictions::AssertIOAllowed(); + DCHECK(http); + + // CUPS expects a leading slash for resource names. Add one if it's missing. + std::string rp = !resource_path.empty() && resource_path.front() == '/' + ? resource_path + : "/" + resource_path; + + auto request = WrapIpp(ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES)); + + ippAddString(request.get(), IPP_TAG_OPERATION, IPP_TAG_URI, kPrinterUri, + nullptr, printer_uri.data()); + + ippAddStrings(request.get(), IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + kRequestedAttributes, num_attributes, nullptr, attributes); + + auto response = WrapIpp(cupsDoRequest(http, request.release(), rp.c_str())); + *status = ippGetStatusCode(response.get()); + + return response; +} + void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status) { for (ipp_attribute_t* attr = ippFirstAttribute(response); attr != nullptr; attr = ippNextAttribute(response)) { @@ -332,25 +424,45 @@ } } +bool GetPrinterInfo(const std::string& address, + const int port, + const std::string& resource, + PrinterInfo* printer_info) { + base::ThreadRestrictions::AssertIOAllowed(); + + ScopedHttpPtr http = ScopedHttpPtr( + httpConnect2(address.data(), port, nullptr, AF_INET, + HTTP_ENCRYPTION_IF_REQUESTED, 0, 200, nullptr)); + if (!http) { + LOG(WARNING) << "Could not connect to host"; + return false; + } + + ipp_status_t status; + ScopedIppPtr response = + GetPrinterAttributes(http.get(), resource, resource, kPrinterInfo.size(), + kPrinterInfo.data(), &status); + if (status != IPP_STATUS_OK || response.get() == nullptr) { + LOG(WARNING) << "Get attributes failure: " << status; + return false; + } + + return ParsePrinterInfo(response.get(), printer_info); +} + bool GetPrinterStatus(http_t* http, const std::string& printer_id, PrinterStatus* printer_status) { - DCHECK(http); + base::ThreadRestrictions::AssertIOAllowed(); - auto request = WrapIpp(ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES)); - + ipp_status_t status; const std::string printer_uri = PrinterUriFromName(printer_id); - ippAddString(request.get(), IPP_TAG_OPERATION, IPP_TAG_URI, kPrinterUri, - nullptr, printer_uri.data()); - ippAddStrings(request.get(), IPP_TAG_OPERATION, IPP_TAG_KEYWORD, - kRequestedAttributes, kPrinterAttributes.size(), nullptr, - kPrinterAttributes.data()); + ScopedIppPtr response = + GetPrinterAttributes(http, printer_uri, "/", kPrinterAttributes.size(), + kPrinterAttributes.data(), &status); - auto response = - WrapIpp(cupsDoRequest(http, request.release(), printer_uri.c_str())); - - if (ippGetStatusCode(response.get()) != IPP_STATUS_OK) + if (status != IPP_STATUS_OK) return false; ParsePrinterStatus(response.get(), printer_status); @@ -363,6 +475,7 @@ int limit, JobCompletionState which, std::vector<CupsJob>* jobs) { + base::ThreadRestrictions::AssertIOAllowed(); DCHECK(http); auto request = WrapIpp(ippNewRequest(IPP_OP_GET_JOBS)); @@ -390,12 +503,11 @@ } // cupsDoRequest will delete the request. - auto response = - WrapIpp(cupsDoRequest(http, request.release(), printer_uri.c_str())); + auto response = WrapIpp(cupsDoRequest(http, request.release(), "/")); ipp_status_t status = ippGetStatusCode(response.get()); - if (status != IPP_OK) { + if (status != IPP_STATUS_OK) { LOG(WARNING) << "IPP Error: " << cupsLastErrorString(); return false; }
diff --git a/printing/backend/cups_jobs.h b/printing/backend/cups_jobs.h index b1ca693c..8c0e4d4b 100644 --- a/printing/backend/cups_jobs.h +++ b/printing/backend/cups_jobs.h
@@ -10,10 +10,16 @@ #include <cups/cups.h> #include <string> +#include <utility> #include <vector> +#include "base/version.h" #include "printing/printing_export.h" +// This file contains a collection of functions used to query IPP printers or +// print servers and the related code to parse these responses. All Get* +// operations block on the network request and cannot be run on the UI thread. + namespace printing { // Represents a print job sent to the queue. @@ -110,6 +116,27 @@ std::string message; }; +struct PRINTING_EXPORT PrinterInfo { + PrinterInfo(); + PrinterInfo(const PrinterInfo& info); + + ~PrinterInfo(); + + // printer-make-and-model + std::string make_and_model; + + // document-format-supported + // MIME types for supported formats. + std::vector<std::string> document_formats; + + // ipp-versions-supported + // A collection of supported IPP protocol versions. + std::vector<base::Version> ipp_versions; + + // Does ipp-features-supported contain 'ipp-everywhere'. + bool ipp_everywhere = false; +}; + // Specifies classes of jobs. enum JobCompletionState { COMPLETED, // only completed jobs @@ -125,6 +152,13 @@ // Attempts to extract a PrinterStatus object out of |response|. void ParsePrinterStatus(ipp_t* response, PrinterStatus* printer_status); +// Queries the printer at |address| on |port| with a Get-Printer-Attributes +// request to populate |printer_info|. Returns false if the request failed. +bool PRINTING_EXPORT GetPrinterInfo(const std::string& address, + const int port, + const std::string& resource, + PrinterInfo* printer_info); + // Attempts to retrieve printer status using connection |http| for |printer_id|. // Returns true if succcssful and updates the fields in |printer_status| as // appropriate. Returns false if the request failed.
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index d70b26b..9575eda 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -69,7 +69,8 @@ base::WeakPtr<It2MeHost::Observer> observer, std::unique_ptr<SignalStrategy> signal_strategy, const std::string& username, - const std::string& directory_bot_jid) { + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config) { DCHECK(host_context->ui_task_runner()->BelongsToCurrentThread()); host_context_ = std::move(host_context); @@ -87,7 +88,7 @@ // Switch to the network thread to start the actual connection. host_context_->network_task_runner()->PostTask( FROM_HERE, base::Bind(&It2MeHost::ConnectOnNetworkThread, this, username, - directory_bot_jid)); + directory_bot_jid, ice_config)); } void It2MeHost::Disconnect() { @@ -97,7 +98,8 @@ } void It2MeHost::ConnectOnNetworkThread(const std::string& username, - const std::string& directory_bot_jid) { + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config) { DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); DCHECK_EQ(kDisconnected, state_); @@ -158,8 +160,7 @@ base::WrapUnique(new ChromiumUrlRequestFactory( host_context_->url_request_context_getter())), network_settings, protocol::TransportRole::SERVER); - transport_context->set_ice_config_url( - ServiceUrls::GetInstance()->ice_config_url()); + transport_context->set_turn_ice_config(ice_config); std::unique_ptr<protocol::SessionManager> session_manager( new protocol::JingleSessionManager(signal_strategy_.get()));
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h index 1ee72f30d..ca39912 100644 --- a/remoting/host/it2me/it2me_host.h +++ b/remoting/host/it2me/it2me_host.h
@@ -22,7 +22,7 @@ namespace base { class DictionaryValue; -} +} // namespace base namespace remoting { @@ -34,6 +34,10 @@ class RegisterSupportHostRequest; class RsaKeyPair; +namespace protocol { +struct IceConfig; +} // namespace protocol + // These state values are duplicated in host_session.js. Remember to update // both copies when making changes. enum It2MeHostState { @@ -73,7 +77,8 @@ base::WeakPtr<It2MeHost::Observer> observer, std::unique_ptr<SignalStrategy> signal_strategy, const std::string& username, - const std::string& directory_bot_jid); + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config); // Disconnects and shuts down the host. virtual void Disconnect(); @@ -106,8 +111,7 @@ private: friend class MockIt2MeHost; - FRIEND_TEST_ALL_PREFIXES(It2MeHostTest, HostUdpPortRangePolicy_ValidRange); - FRIEND_TEST_ALL_PREFIXES(It2MeHostTest, HostUdpPortRangePolicy_NoRange); + friend class It2MeHostTest; // Updates state of the host. Can be called only on the network thread. void SetState(It2MeHostState state, const std::string& error_message); @@ -122,7 +126,8 @@ // Task posted to the network thread from Connect(). void ConnectOnNetworkThread(const std::string& username, - const std::string& directory_bot_jid); + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config); // Called when the support host registration completes. void OnReceivedSupportID(const std::string& support_id,
diff --git a/remoting/host/it2me/it2me_host_unittest.cc b/remoting/host/it2me/it2me_host_unittest.cc index 10cec61..8f8e7ef 100644 --- a/remoting/host/it2me/it2me_host_unittest.cc +++ b/remoting/host/it2me/it2me_host_unittest.cc
@@ -54,6 +54,8 @@ // Note that this is intentionally different from the default port range. const char kPortRange[] = "12401-12408"; +const char kTestStunServer[] = "test_relay_server.com"; + } // namespace class FakeIt2MeConfirmationDialog : public It2MeConfirmationDialog { @@ -160,6 +162,8 @@ static base::ListValue MakeList( std::initializer_list<base::StringPiece> values); + ChromotingHost* GetHost() { return it2me_host_->host_.get(); } + ValidationResult validation_result_ = ValidationResult::SUCCESS; base::Closure state_change_callback_; @@ -259,13 +263,18 @@ new FakeIt2MeDialogFactory()); dialog_factory_ = dialog_factory.get(); + protocol::IceConfig ice_config; + ice_config.stun_servers.push_back(rtc::SocketAddress(kTestStunServer, 100)); + ice_config.expiration_time = + base::Time::Now() + base::TimeDelta::FromHours(1); + it2me_host_ = new It2MeHost(); it2me_host_->Connect(host_context_->Copy(), base::MakeUnique<base::DictionaryValue>(*policies_), std::move(dialog_factory), weak_factory_.GetWeakPtr(), base::WrapUnique(new FakeSignalStrategy( SignalingAddress("fake_local_jid"))), - kTestUserName, "fake_bot_jid"); + kTestUserName, "fake_bot_jid", ice_config); base::RunLoop run_loop; state_change_callback_ = @@ -330,9 +339,32 @@ return result; } -TEST_F(It2MeHostTest, HostValidation_NoHostDomainListPolicy) { +// Callback to receive IceConfig from TransportContext +void ReceiveIceConfig(protocol::IceConfig* ice_config, + const protocol::IceConfig& received_ice_config) { + *ice_config = received_ice_config; +} + +TEST_F(It2MeHostTest, StartAndStop) { StartHost(); ASSERT_EQ(It2MeHostState::kReceivedAccessCode, last_host_state_); + + ShutdownHost(); + ASSERT_EQ(It2MeHostState::kDisconnected, last_host_state_); +} + +// Verify that IceConfig is passed to the TransportContext. +TEST_F(It2MeHostTest, IceConfig) { + StartHost(); + ASSERT_EQ(It2MeHostState::kReceivedAccessCode, last_host_state_); + + protocol::IceConfig ice_config; + GetHost()->transport_context_for_tests()->set_relay_mode( + protocol::TransportContext::TURN); + GetHost()->transport_context_for_tests()->GetIceConfig( + base::Bind(&ReceiveIceConfig, &ice_config)); + EXPECT_EQ(ice_config.stun_servers[0].hostname(), kTestStunServer); + ShutdownHost(); ASSERT_EQ(It2MeHostState::kDisconnected, last_host_state_); } @@ -522,18 +554,16 @@ SetPolicies( {{policy::key::kRemoteAccessHostUdpPortRange, base::Value(kPortRange)}}); StartHost(); - PortRange port_range = it2me_host_->host_->transport_context_for_tests() - ->network_settings() - .port_range; + PortRange port_range = + GetHost()->transport_context_for_tests()->network_settings().port_range; ASSERT_EQ(port_range_actual.min_port, port_range.min_port); ASSERT_EQ(port_range_actual.max_port, port_range.max_port); } TEST_F(It2MeHostTest, HostUdpPortRangePolicy_NoRange) { StartHost(); - PortRange port_range = it2me_host_->host_->transport_context_for_tests() - ->network_settings() - .port_range; + PortRange port_range = + GetHost()->transport_context_for_tests()->network_settings().port_range; ASSERT_TRUE(port_range.is_null()); }
diff --git a/remoting/host/it2me/it2me_native_messaging_host.cc b/remoting/host/it2me/it2me_native_messaging_host.cc index bee792e0..6212deb1 100644 --- a/remoting/host/it2me/it2me_native_messaging_host.cc +++ b/remoting/host/it2me/it2me_native_messaging_host.cc
@@ -33,6 +33,7 @@ #include "remoting/host/host_exit_codes.h" #include "remoting/host/it2me/it2me_confirmation_dialog.h" #include "remoting/host/policy_watcher.h" +#include "remoting/protocol/ice_config.h" #include "remoting/signaling/delegating_signal_strategy.h" #if defined(OS_WIN) @@ -316,6 +317,12 @@ } #endif // !defined(NDEBUG) + base::DictionaryValue* ice_config_dict; + protocol::IceConfig ice_config; + if (message->GetDictionary("iceConfig", &ice_config_dict)) { + ice_config = protocol::IceConfig::Parse(*ice_config_dict); + } + std::unique_ptr<base::DictionaryValue> policies = policy_watcher_->GetCurrentPolicies(); if (policies->size() == 0) { @@ -332,7 +339,7 @@ it2me_host_->Connect(host_context_->Copy(), std::move(policies), base::MakeUnique<It2MeConfirmationDialogFactory>(), weak_ptr_, std::move(signal_strategy), username, - directory_bot_jid); + directory_bot_jid, ice_config); SendMessageToClient(std::move(response)); }
diff --git a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc index 730b61b..962456c 100644 --- a/remoting/host/it2me/it2me_native_messaging_host_unittest.cc +++ b/remoting/host/it2me/it2me_native_messaging_host_unittest.cc
@@ -33,6 +33,7 @@ #include "remoting/host/native_messaging/pipe_messaging_channel.h" #include "remoting/host/policy_watcher.h" #include "remoting/host/setup/test_util.h" +#include "remoting/protocol/ice_config.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { @@ -43,6 +44,8 @@ constexpr base::TimeDelta kTestAccessCodeLifetime = base::TimeDelta::FromSeconds(666); const char kTestClientUsername[] = "some_user@gmail.com"; +const char kTestBotJid[] = "remoting@bot.talk.google.com"; +const char kTestStunServer[] = "test_relay_server.com"; void VerifyId(std::unique_ptr<base::DictionaryValue> response, int expected_value) { @@ -91,7 +94,8 @@ base::WeakPtr<It2MeHost::Observer> observer, std::unique_ptr<SignalStrategy> signal_strategy, const std::string& username, - const std::string& directory_bot_jid) override; + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config) override; void Disconnect() override; private: @@ -109,9 +113,15 @@ base::WeakPtr<It2MeHost::Observer> observer, std::unique_ptr<SignalStrategy> signal_strategy, const std::string& username, - const std::string& directory_bot_jid) { + const std::string& directory_bot_jid, + const protocol::IceConfig& ice_config) { DCHECK(context->ui_task_runner()->BelongsToCurrentThread()); + // Verify that parameters are passed correctly. + EXPECT_EQ(username, kTestClientUsername); + EXPECT_EQ(directory_bot_jid, kTestBotJid); + EXPECT_EQ(ice_config.stun_servers[0].hostname(), kTestStunServer); + host_context_ = std::move(context); observer_ = std::move(observer); signal_strategy_ = std::move(signal_strategy); @@ -549,9 +559,14 @@ connect_message.SetString("type", "connect"); connect_message.SetString("xmppServerAddress", "talk.google.com:5222"); connect_message.SetBoolean("xmppServerUseTls", true); - connect_message.SetString("directoryBotJid", "remoting@bot.talk.google.com"); - connect_message.SetString("userName", "chromo.pyauto@gmail.com"); + connect_message.SetString("directoryBotJid", kTestBotJid); + connect_message.SetString("userName", kTestClientUsername); connect_message.SetString("authServiceWithToken", "oauth2:sometoken"); + connect_message.Set( + "iceConfig", + base::JSONReader::Read("{ \"iceServers\": [ { \"urls\": [ \"stun:" + + std::string(kTestStunServer) + "\" ] } ] }")); + WriteMessageToInputPipe(connect_message); }
diff --git a/remoting/protocol/ice_config.cc b/remoting/protocol/ice_config.cc index 63268270..79c2f1a 100644 --- a/remoting/protocol/ice_config.cc +++ b/remoting/protocol/ice_config.cc
@@ -5,6 +5,7 @@ #include "remoting/protocol/ice_config.h" #include "base/json/json_reader.h" +#include "base/json/json_writer.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -92,12 +93,9 @@ IceConfig::~IceConfig() {} // static -IceConfig IceConfig::Parse(const std::string& config_json) { - std::unique_ptr<base::Value> json = base::JSONReader::Read(config_json); - base::DictionaryValue* dictionary = nullptr; - base::ListValue* ice_servers_list = nullptr; - if (!json || !json->GetAsDictionary(&dictionary) || - !dictionary->GetList("iceServers", &ice_servers_list)) { +IceConfig IceConfig::Parse(const base::DictionaryValue& dictionary) { + const base::ListValue* ice_servers_list = nullptr; + if (!dictionary.GetList("iceServers", &ice_servers_list)) { return IceConfig(); } @@ -106,7 +104,7 @@ // Parse lifetimeDuration field. std::string lifetime_str; base::TimeDelta lifetime; - if (!dictionary->GetString("lifetimeDuration", &lifetime_str) || + if (!dictionary.GetString("lifetimeDuration", &lifetime_str) || !ParseLifetime(lifetime_str, &lifetime)) { LOG(ERROR) << "Received invalid lifetimeDuration value: " << lifetime_str; @@ -151,7 +149,12 @@ } if (errors_found) { - LOG(ERROR) << "Received ICE config with errors: " << config_json; + std::string json; + if (!base::JSONWriter::WriteWithOptions( + dictionary, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json)) { + NOTREACHED(); + } + LOG(ERROR) << "Received ICE config with errors: " << json; } // If there are no STUN or no TURN servers then mark the config as expired so @@ -164,5 +167,28 @@ return ice_config; } +// static +IceConfig IceConfig::Parse(const std::string& config_json) { + std::unique_ptr<base::Value> json = base::JSONReader::Read(config_json); + if (!json) { + return IceConfig(); + } + + base::DictionaryValue* dictionary = nullptr; + if (!json->GetAsDictionary(&dictionary)) { + return IceConfig(); + } + + // Handle the case when the config is wrapped in 'data', i.e. as {'data': { + // 'iceServers': {...} }}. + base::DictionaryValue* data_dictionary = nullptr; + if (!dictionary->HasKey("iceServers") && + dictionary->GetDictionary("data", &data_dictionary)) { + return Parse(*data_dictionary); + } + + return Parse(*dictionary); +} + } // namespace protocol } // namespace remoting
diff --git a/remoting/protocol/ice_config.h b/remoting/protocol/ice_config.h index d52fd6d..b039ba3f 100644 --- a/remoting/protocol/ice_config.h +++ b/remoting/protocol/ice_config.h
@@ -12,6 +12,10 @@ #include "third_party/webrtc/base/socketaddress.h" #include "third_party/webrtc/p2p/base/portallocator.h" +namespace base { +class DictionaryValue; +} // namespace base + namespace remoting { namespace protocol { @@ -24,6 +28,7 @@ // Parses JSON representation of the config. Returns null config if parsing // fails. + static IceConfig Parse(const base::DictionaryValue& dictionary); static IceConfig Parse(const std::string& config_json); // Time when the config will stop being valid and need to be refreshed.
diff --git a/remoting/protocol/ice_config_unittest.cc b/remoting/protocol/ice_config_unittest.cc index fdefe75..ab7aa7c5 100644 --- a/remoting/protocol/ice_config_unittest.cc +++ b/remoting/protocol/ice_config_unittest.cc
@@ -73,6 +73,25 @@ EXPECT_EQ(rtc::SocketAddress("1.2.3.4", 3478), config.stun_servers[1]); } +TEST(IceConfigTest, ParseDataEnvelope) { + const char kTestConfigJson[] = + "{\"data\":{" + " \"lifetimeDuration\": \"43200.000s\"," + " \"iceServers\": [" + " {" + " \"urls\": [" + " \"stun:1.2.3.4\"" + " ]" + " }" + " ]" + "}}"; + + IceConfig config = IceConfig::Parse(kTestConfigJson); + + EXPECT_EQ(1U, config.stun_servers.size()); + EXPECT_EQ(rtc::SocketAddress("1.2.3.4", 3478), config.stun_servers[0]); +} + // Verify that we can still proceed if some servers cannot be parsed. TEST(IceConfigTest, ParsePartiallyInvalid) { const char kTestConfigJson[] =
diff --git a/remoting/protocol/transport_context.h b/remoting/protocol/transport_context.h index 2a1ddb6..3d18b29 100644 --- a/remoting/protocol/transport_context.h +++ b/remoting/protocol/transport_context.h
@@ -51,6 +51,10 @@ const NetworkSettings& network_settings, TransportRole role); + void set_turn_ice_config(const IceConfig& ice_config) { + ice_config_[TURN] = ice_config; + } + void set_ice_config_url(const std::string& ice_config_url) { ice_config_url_ = ice_config_url; }
diff --git a/services/BUILD.gn b/services/BUILD.gn index a46978d..622af1c 100644 --- a/services/BUILD.gn +++ b/services/BUILD.gn
@@ -119,4 +119,21 @@ "//third_party/android_tools:android_support_annotations_java", ] } + + android_library("service_javatests") { + testonly = true + java_files = [ "shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java" ] + deps = [ + "//base:base_java_test_support", + "//mojo/public/java:bindings_java", + "//services/shape_detection:shape_detection_java", + "//services/shape_detection/public/interfaces:interfaces_java", + "//skia/public/interfaces:interfaces_java", + "//third_party/android_support_test_runner:runner_java", + "//ui/gfx/geometry/mojo:mojo_java", + ] + data = [ + "test/data/", + ] + } }
diff --git a/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java b/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java new file mode 100644 index 0000000..b8177d4 --- /dev/null +++ b/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java
@@ -0,0 +1,86 @@ +// 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. + +package org.chromium.shape_detection; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.support.test.filters.SmallTest; +import android.test.InstrumentationTestCase; + +import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.UrlUtils; +import org.chromium.shape_detection.mojom.FaceDetection; +import org.chromium.shape_detection.mojom.FaceDetectionResult; +import org.chromium.shape_detection.mojom.FaceDetectorOptions; +import org.chromium.skia.mojom.ColorType; + +import java.nio.ByteBuffer; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * Test suite for FaceDetectionImpl. + */ +public class FaceDetectionImplTest extends InstrumentationTestCase { + public static final org.chromium.skia.mojom.Bitmap MONA_LISA_BITMAP = + mojoBitmapFromFile("mona_lisa.jpg"); + // Different versions of Android have different implementations of FaceDetector.findFaces(), so + // we have to use a large error threshold. + public static final double BOUNDING_BOX_POSITION_ERROR = 10.0; + public static final double BOUNDING_BOX_SIZE_ERROR = 5.0; + + public FaceDetectionImplTest() {} + + private static org.chromium.skia.mojom.Bitmap mojoBitmapFromBitmap(Bitmap bitmap) { + ByteBuffer buffer = ByteBuffer.allocate(bitmap.getByteCount()); + bitmap.copyPixelsToBuffer(buffer); + + org.chromium.skia.mojom.Bitmap mojoBitmap = new org.chromium.skia.mojom.Bitmap(); + mojoBitmap.width = bitmap.getWidth(); + mojoBitmap.height = bitmap.getHeight(); + mojoBitmap.pixelData = buffer.array(); + mojoBitmap.colorType = ColorType.RGBA_8888; + return mojoBitmap; + } + + private static org.chromium.skia.mojom.Bitmap mojoBitmapFromFile(String relPath) { + String path = UrlUtils.getIsolatedTestFilePath("services/test/data/" + relPath); + Bitmap bitmap = BitmapFactory.decodeFile(path); + return mojoBitmapFromBitmap(bitmap); + } + + private static FaceDetectionResult[] detect(org.chromium.skia.mojom.Bitmap mojoBitmap) { + FaceDetectorOptions options = new FaceDetectorOptions(); + options.fastMode = false; + options.maxDetectedFaces = 32; + FaceDetection detector = new FaceDetectionImpl(options); + + final ArrayBlockingQueue<FaceDetectionResult[]> queue = new ArrayBlockingQueue<>(1); + detector.detect(mojoBitmap, new FaceDetection.DetectResponse() { + public void call(FaceDetectionResult[] results) { + queue.add(results); + } + }); + FaceDetectionResult[] toReturn = null; + try { + toReturn = queue.poll(5L, TimeUnit.SECONDS); + } catch (InterruptedException e) { + fail("Could not get FaceDetectionResult: " + e.toString()); + } + assertNotNull(toReturn); + return toReturn; + } + + @SmallTest + @Feature({"ShapeDetection"}) + public void testDetectSucceedsOnValidImage() { + FaceDetectionResult[] results = detect(MONA_LISA_BITMAP); + assertEquals(1, results.length); + assertEquals(40.0, results[0].boundingBox.width, BOUNDING_BOX_SIZE_ERROR); + assertEquals(40.0, results[0].boundingBox.height, BOUNDING_BOX_SIZE_ERROR); + assertEquals(24.0, results[0].boundingBox.x, BOUNDING_BOX_POSITION_ERROR); + assertEquals(20.0, results[0].boundingBox.y, BOUNDING_BOX_POSITION_ERROR); + } +}
diff --git a/services/shape_detection/face_detection_impl_mac_unittest.mm b/services/shape_detection/face_detection_impl_mac_unittest.mm index c8c2ed6b..83ea57e 100644 --- a/services/shape_detection/face_detection_impl_mac_unittest.mm +++ b/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -28,6 +28,7 @@ // Base64 encoding of the Mona Lisa Face thumbnail from: // https://commons.wikimedia.org/wiki/File:Mona_Lisa_face_800x800px.jpg +// TODO: Use services/test/data/mona_lisa.jpg. See https://crbug.com/729653. const int kJpegImageWidth = 120; const int kJpegImageHeight = 120; const char kJpegImageInBase64[]="/9j/4AAQSkZJRgABAQEAZABkAAD//gBSRmlsZSBzb3VyY2U6IGh0dHA6Ly9jb21tb25zLndpa2ltZWRpYS5vcmcvd2lraS9GaWxlOk1vbmFfTGlzYV9mYWNlXzgwMHg4MDBweC5qcGf/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAB4AHgDAREAAhEBAxEB/8QAHAAAAgIDAQEAAAAAAAAAAAAABQYEBwEDCAIA/8QAOxAAAgECBQIEBAQFAwMFAAAAAQIDBBEABRIhMQZBEyJRYQcycYEUkaGxFUJiwfAjJOEWF9ElM1LC8f/EABoBAAIDAQEAAAAAAAAAAAAAAAIDAQQFAAb/xAAvEQACAgICAgAEBQQCAwAAAAAAAQIRAyESMQRBBRMiUTJhcaGxFCNSgZHwweHx/9oADAMBAAIRAxEAPwBqiIChT5t7gEYwX1ssJUbY0ErKBHpFu498Q3fRKTMmJVNm2POo9/tiG2kTFG+FfIAq9t2ta2BtvsKtkqKmDE2UgMDiUn2C3ugTnvVGRdPy6M2zKFJxv+HivLN6i6LuPvbDsalPaRPy29Cw/wAYOn1kPgUmYS3OxZUjJvwbFrgYfHx8hziqCVF8V+namVUnSvojzqlp9SkD3QkYGWKa62SsY5ZVmVDmlMKnLamCqgvu8bBgPYjkH64U3x/FpkcWF4yT8oG4337YBzdUgVHezEwN1N1BxzurslJGI1uSpJG3bvjlew2bYUN+fS+Cj12DJkqEWNgOeL4OM66AaNscXkb2vziVK47ZD0IkcG1r/X/PthVWFZLRNKqAAdiCT9cC19jk77MRpqILKNjfi/tbCpcug40SooAz6tNyfLsOPbBQhslsrH4n/ECXLa+Tp7IZvBrxaOprEXU0Fx8if1+/a/ri3i8e1zn1/P8A6Ba6oR8h6YqY8szKshpauaWdNCzBHkZifmYk778ffAZvIU5Qg3pMsQg4xbS2KmcZQKPUaqmqItVhqeEqL9rnGhjzc3SaZXyY63QGDvSuJaScofVfMp57YsOPLUkLUnHcQplXUFfQZrFV5bK2XZkll8SEWRx6MnBB9D+mEywppqW0N+by/U6Y+EvXdP1rlrJKkVNnVMAtVTLsrDgSJ30nj2O3pjLz4XhlXr0d+JWh6eJQCy2b6DEOKAT+55hQrYsNrW98TH2S2ToAATYG5GwI4wUqSYPZuSEBNXAIBO2E8eO0TZ8UZVtf5hvbE7RHYkQRG6kix7f2wuMnexjr0SvDZiqpf6dsH30D12bIKe77gna7W7bYHbbCtIFdf9R0/R3S9VmcrIJFHh06t/PKR5Rbk+v0GLMISk1CK2wE03begP8ACHommhy6LM8zjhqM0qf9eeoljEjhm3sL7D7b++KmXK8+Tin9K0l+hcUflwTrbLXFHCABftYdvtthbjRHNgjOsoiqKaaJ9TqykFWAKn88Vsip6HwlfZzV8R+kKeikeSjS128wCD+2NT4f57yfTP0I8jCltFWyJJEXul0vYkLce4JxtqSfRRoJ9K5/WdNdSUOb5a7iWmbUVPEkZI1o3qCt/wBMBmxLLjcP+P1IjOpWztvJa+lzTJ6PMqF9dJVxLLG47qwuPpbi2MqP0Opd9ByV9E2KNWF97AbNiWlu2crN8cIABIFxyL7YW2yTZGhlNr7eltscnZD0ZkpyI++1+cMcVVg3sUUWMxRtHpbVc3GKr4voYrM063k32YEi9t9zhiTXRDJVHAzSB3uoK2F/bEwm4u7OaT0UL8cs9TqHPsqyZEH+nWxaWvuus7KB6keYn6Dti5gySm5Zn0kyflrGlBdtl7dNWp6FFY2awU39RjFxx1aNHJ9g6pdWa5LX3J9MS27aE0uyHXiSRCFN9rG3OEThyGxaQi9UdOpXwyCW1muDb/PbC4J4ZckNdTVM5u63y5cpzeemilCQDzebuff9bY9R4eV5cak+zMzxUJUhVmbUNQt6W9bC++LpWaSOjvgT1JK/w+ho5mtHl9Y1OD6o1pB9hrP5Yy/Mhxm697Gp3Wy0aXNhNMsIYi29u1j2v37Yq7fZLetB01arE5DKVQaRY8m+/wDbHUxTnvQRplvbcaTuL+/GIXdMY2bwbxFd2wXNtUD07KMyvqid3WGnLvqszF0PIB8o/LfEairZNT9D109mYzSmMiRaJUkMbjmxIDCx+hwacpNEKadk3Nq38HlE8oGpvw7sthvcKdsLlG6TCUt0jkbrCsaXramzCGSNr10MmkfNrUqtxfsQBtjS8eP9hwf2f7jJ25KS+6Lv/wC6VBDlQq0lSipEm/DhqpZSddr2IRG08H5iDtxjGXi5XJQjt1fa6L7yQrkx1n6p0dKSZwIwAE4vca+BY973B++KXJyfFd9B/LS2xLTq7NKbIWzvOfHpaeRxGFWkknILfKCFsBe3rg/lKWR48cr/ADbpHcmo3JAOLrjqHPcwio8uyeaohcj/AHUaSJGBv5jrUabW4P64tT8XHjjynk39tX+wr5km6jErP4oUM8Od+JUfM/zC99/rjT+GZYvHSRV8lNSViSmmF2XUrM1wQefe2NTsp7uix/hJWFKDNaUMViM0E5AYgsNJUi/2GKHmR/C/ZPWi5MkzgykxMYlABszCxuP32xVUFsGWR+w1Lm0cNJHGAJRIw3U302bfbne2IpdsSOXT9UKqEsHLJqBH0HbFKVqSTLqaadByJ/D1FgbW2vhuO07BbXRydQZocvqqclJCW31XA3IsSe1zfbFiWHndC1krQfyLrl6TI5KKFNFTGDaULfU1yGJ/NQCe2AyYJJ/T0Hjkktk2l6tmoTmVI0zSrBEqwySG5RmZthc8AXIxPy3KCZy1Oijxoi67yiKUf7eHNI1Z73DDxRck+v8A4xou/wCnlXbi/wCBqf1x17OwP4TBW05RJqiJTJ4jBQu7X3O4Nj7jHmFBTjyTNNzcHRo6ioUk6ckprBYGlBFxfYf/AIMdwaWiLTeyblGXRnLYYWqaiOwsdDDf87jELFyVSOlNx/Caa5abKKdjCZGL3LNI5YnC5pQdRQULkrZyz8YcwNZ1G3hFrIeB2/y2PRfCYccNv2Z/lu5UhEcuXErWYHdibbE/2xq1ZRHz4VpNP1BVU1I0i+PRlyq2a5V1P/2/XFPyopQTfoJLk9Fy5TRVkMjvLTVMpA3ZrHew/I/bvijyW9kSg0uiWIK2PSYaGpYA7CwvxyT3xzURLvsaukq2opJSKiCWJGJtZCdz9sJlFdpjMc2tMbJMxQqbyMCb8jAPI1sclZyPmMBZ2ZZWGkeJqLaix4A+mNODr0IaNbMYiDDJIAbgMBbUpAO4F9r3/K+J2yaT7AGeVdTYtHIG1Pu3qTcbn7n8sWMUVQSb5C3mFayrGYXa8bhyrdiDdbHvxh0YJ6GznpUdk9I9QJmuUUciOC00aEXO1iAf748jNPHcH6dGy6nUgN8QOuafpqloqGty+tkr5m3iiFw68albhhxxv64b4+CedaaSX3ETlHG7e7GLpPMzU9OUlZVRS0krhv8AQlPnUajpv72thTSg2rug/wASTFzrTNZTCywgkr9sLjHnJX6Dk6WjmLrCoaozeWR7sdR2btvwceq8VVjSRlZvxAaWcNEpK2f+axPGLCEMNdLVMkWYRmJn8UkqpHuLf87emByxuLvoh7LbynM8wphrSSrjB8xW1lJ2/wA7YoNKnQDeg7H1DXooAmrFckWUbn9rdsQ8a9CqDtB1XUJvUzh1202sDv625tgJwXVEptK7CY6jlqoisTygggGy7geuFcFdkcm/pbOdpa7xpQzCXzeQG2s27WONCMKHHppnlHhqg1KbhhtfjkG37euJBe2Q81y92y8vM6HUy2AI8p3P9t//ADgoZVy0iYJ3QqThI4NBVZJmc3bkqB6fXFlNt2Ntca9l5fA7qWlzTp6PJ6ipNPmVIDGrgjV4d/Kwvza9vtjznxXBKGR5K+mX8ml4mVTgoe0WR1OlR4UUZrcwqHUXSdcvjk29yLAfljN0pW/5LXoh5DA1NMZszrKyrn07LKiokYHoFHJuNyTiZSjJrVV+oKX52LvXGcwDxI42BYgjbfe22H+Pi5y2LyTpUc/Z9KZcwZ2Yl2a/t7DHqMKSjSMvK9gyVlvZCRtp+vqcNQtumFMhDfjIWifS9wb3taxwvJJKLOirLlpljjdYiulnF/KfNuNhx9+cZnPTdC3HVBCSjUxqZFOlPMCU77knb2xHNN7YFM30ckEQIAXTfY6fMLd8Tr2CyfJnsUKlIULNfsPl55PpxiJQV2FG0ikqKoLlRpRlbSCjC4O/Fr8k+98aEo/caHaWYyOVMOXBRIWCSHYj6ffCZxXabIoL5hl0/wD05WySJQNEkQmURhiWCkG1jyQL++EJrmtjIqip8x8JpnnkRXZyQNPC27n12tjSiq0TrtkGOtlocziqsullp54SGjkDWa+3+Wwc4KUeM9pkW4SuLOi+kfjrlz9PxwZ0r0+ZIgWTSl0f+ofX0x5/P8Kywf8Aa3H+DRx+VCf4tMEZ/wDEuOoB/A6UjI80kjC/5emBx/DZ95Dp511ErvMuojVvppr1EzXJfgL32vzjSx+Lw70V5ZL62LVXSy+O5ZjIxNy9tgMXLVUV3FoinQiG+7WNiB++D7AJuWzGJ1K3BUcn7EYiULVExdOy6qLNoTl1LIWEr2XSVIsGNr77d7jb9cZrwtXE7l7DdVXxVETeV4ybKoQ727m3bfCfkxUrBcrVUQBXwq7GJZmXRqKActf0+ww2Ka0C4Jn1TnETVI0sCC1iBGPU/p+3ptjpJvs5QS9i1Q0IVUctAlmuPCjB/ckg4a5xYwPUpiiZ1srPqHnbw9TahyABzta+Ikv8URFm+oqA0Eo8VDGV0MqkEDm4P14++EO09DE12UbnlGtPn1VTh2aNJLIVTc+VSARtv5gMa2KVwUgX2BZUu6nURcXJY73w7sGSoO9ARUcnWuUQ5giyUk1QIXRvl84Ki/3IxW8vl8mTi6dB4GlkXItXqb4WU8JY0EcSWO5AuAMZGH4nKL4z2Wsnjp7RAynonTIgnjUpcCygj8v3wefzk1pnQxv2TOrOlBT5S/gRqiqoJ2tbfck+mEeN5vLJ9TGSxaKlqKfwigdGUgHy25B4xvRmn0UZRNog8GjSWQeQFjbttYYlTTlR0o0rLL6OzCiqMshK1FPSLpWO7garj5u3YnnFDKppvt//AEFRTHVYacgQ0udQSMynWGS4tzzqxUtydyQTiq0YfpseHLWawaYC6u3kPoCvub4OOWvpbI4ezbTdJxC0r1XhIx1aW8oUn1v/AJvivPzI39DsdHx5PtUVPoneOVpayRKlKZfCaJiCdyTvck2F/uMaXKnpavYiiMnW1Y9OwqxTtO6C0ynQoIuo1AA78/8AGHy8aL6YN0eM16rr5qeHxggpp0CzaYwLMrndTyLGx9MQvHjvfR1+hPramevr6iaSZpJJZS2vgsext9hixGKjFJE22fZbltZmtctLQwy1FQ+yJGNRv+1vfHTyQhHnkdImMJSfFLZevw3+EUcEyV2czh6lfkVR5EbtYnk+/tjB8n4m8v0YVS/cu4vGUPql2XFJl5MAWYaibD5f8tjIk0XEjNNkSIxa2jfa/wCWBa+xNkHPMnSajdbgEIwIbv6XHpgVqXJBJXo5zqsnEWdGjIWS8oVSG+XU9h9bb3HbHpoZ+WHn+RQljqVEHqOkENFDSqiMq1UxW3JF7H7XXj64d487lyv0hWRar8wJk0arVCJ2RUJJ1MdlbixPobYt5HcW0V0iysiyTMa6ro2pqOi0RvdHjk1K+2wIBJIxk5pwjabewoxd2hpHRvU1TmFFXVGZapoTdjqKge3Nj2H0AxXl5eOMWlHsOOCTY7ZjUTUmVwrLL+JrVGyKCdbD1P8ALz3OMzDH63JaTLkp8Y17KG6k8OOKopKGIvII1GuxBtxb2G55/vj0HjqTlym/ZTlVUhPqqA/wWREVS8Uha+m+w2IB/LjGgprmhDTI2awuuVUxmLqI49Kqex1E2PvucdGVzdE1SsG0ccktSqxX1Dvbgep/PBt0rOirejpj4C9IJQ5TLWTxXnqW1K9iCYx8ot6Hn7jHmfifkPNlUU9L+TVwY/lw/Nl009Ivg2CgWsRccHFSNpWiW7dGWijuBGLXbAPYa12bWj0wGx78WxMlUQU9i91AqpSzCUnwyp498VcjldD8Zz7EIaTOqd6dkll/EukjWuCQbkqSeNyfXtvj0D5TxvkvVlZ1FiP1DXvJmwicqRCWN/fUf73xqePjUcdr2UMsvqPa5LVVVG88dNK8RYBNKni3Jt62wXz4xbi2FxbV0Fum80qKevSnqZXpp1kChilib8bYR5GFSi5R2LafRfGW9RR1FHFBUxzyGMJTuIxpAfgAXtfb19748/ODT2WYz0e6l6GOnWVzXxr4nhp8urUb3BBa/wBzhP1ctfuE6rZVOe0aNCskauXSO7Kw0rIO2/pe36Y1sGRp02VpxdWKeeS02V5PGs0aLUMRaPuSMaGLnlyWnoBpRVsQayplq5DJMQVDHSnZfYY0IxSWhTdlp/B3pMZtRzVksPiXa2+1gP2A2NxvjH+JeY8clCJf8TEmuTOm+k8pGU5VBT69ciLubW1H1AxhOTcm37LcpWHwBYDa/e+Du9AL7mDGRp3IOq9sQ4vom/Z9UJqW1rEbHvgZHJ7EvrVo48qqBJJa6FTcHk9vU4RdzikWI9MpSopZ6itCUdGoUEkuyhUDXW9zfbgbcXxtQmlG5S3/AOCrkT6iiZknw5paurmq5JRmFbK5Z1SIyxq1727Ltfe57YXk+JTSUIql+4C8ZW5NhvOsloaOkZMwzGKIR/8AtJNVrCL8GyxrueRtfAYcuSTk4x3+l/yFOMUtspvq5MtjrUejqF8YfM0c0rgenzqP0ON7xnkcWpr+DPy1eiT0v17XZUwhqJmeEEBJlVQwP9RNwdu/IwryPAhkuUdMnHlcdMtTJ/iHPDCGzFEZJPKr+EmpbDctpA59TvjMn4bb+mi1GQKp0myd2rM8rqengC6pUldW2K7WUEkX+vNhbA5az/Rhi2/0ohfRuWim+r83Gd59PVxK0dKvkp47Wsg9vfnHofGwfIxqDdv2Uck+UrQMjjaQrCpbzDg84baQNM6J+Due02Vwfgc5XRS2DxS6SFF+dQ/Kx+2PM/EcDlk+bD/Zq+PlShxZfFPXUtTRGqpqiOSMjV4isCCPrx3xm8lX2D4uyTSFpRrIIU4OKs6TrROATQe/IGHqOhLbs1SeGgYHn62H1wuSDTbK862rqGOOZDLrYA/JJpAJG4v22v72xWWJzmmh/wAxQVMqPMetMloJJHaMZhU2IjhtaFe3H83bnGvj+HZsi/xX7lV+RFO3sWM++JOdVkfgzVy5fSqDppqRLEDi5tsP0Pti/g+F4obrl+bEy8lvrQjVuc1Uxv8AiZyp/pA3+u+NKOCEVVFdzb7YPeeRyLs7G9zra+DSSAb9mI9QG1irHcDg46jhx6Unlqf/AEzYTIC8bjctYElSODtc7+n0xUz41H+5/wB/UtYJuX0P/v5A3rmeq/i38PqleMU41OjC12Nz+gNh9cT4UY8OcfYnNafF+hZbbzXv7W74t0IDmQQJJI81TfSGAuDxte+/+cYRlbWkGl9xsjzYitpIqYMksqDQNfyKCbk32vYHn/5DFT5Sabl6GqdPQcyjNJTI6ZfO1KsVtbU8ugsx33HDADfj88V8mBNXJXY6GV9Idss+IWf5epi/iaT6AAyVFOCRe1hdbeo5v2xVfiQ7imv9jVlT7C8HxZro95IKCcKbF4y4J/Q/TAf0kv8AIJzh3REz74pVE1NIbU9DDGt5JSS+/ZFIFy1+w3+g3wEfDcpV2BLyIpfSVD1D1f40FU5m8JpzaOJV8SZ151MSdMYNztuxxq4PD4ta6/4/19ytPNYjPXSyE+CCt99iSxPqTycaKikV07C2X5bClI1bVgtHTjdb7SPvZfzt+uFSnLkox7YVLshVcaRKseka7NyNgbL/AM4bFtnPQLWOQm6q5ABJ8p49T7e+D5AbZ6VvmNh2sL8Y6yVYRy+qemqaadLiSFw4sObdt8RJcotP2HGTi7XZ/9k=";
diff --git a/services/test/data/mona_lisa.jpg b/services/test/data/mona_lisa.jpg new file mode 100644 index 0000000..df28704 --- /dev/null +++ b/services/test/data/mona_lisa.jpg Binary files differ
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index d68a3d9..e0e086b 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -4820,12 +4820,6 @@ "shards": 2 } } - ], - "scripts": [ - { - "name": "nacl_integration", - "script": "nacl_integration.py" - } ] }, "ClangToTMacASan tester": {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 2b206f7c..5cd21e8 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1795,22 +1795,6 @@ ] } ], - "OfflinePageCache": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "OfflineBookmarks", - "OfflineRecentPages" - ] - } - ] - } - ], "OfflinePages": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 826cbfcc..058af07 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -914,8 +914,6 @@ crbug.com/498539 [ Win7 ] inspector/elements/styles-4/styles-update-from-js.html [ Crash Pass ] -crbug.com/731144 inspector/elements/edit/set-outer-html-2.html [ Failure Pass ] - crbug.com/596968 [ Win ] inspector-protocol/input/eventTimestamp.html [ Failure Pass ] crbug.com/487281 [ Mac ] fast/forms/select/menulist-narrow-width.html [ Failure ] @@ -2098,7 +2096,6 @@ crbug.com/626703 external/wpt/webaudio/the-audio-api/the-audioparam-interface/retrospective-setValueAtTime.html [ Timeout ] crbug.com/626703 external/wpt/webaudio/the-audio-api/the-audioparam-interface/retrospective-setValueCurveAtTime.html [ Timeout ] crbug.com/626703 external/wpt/webaudio/the-audio-api/the-mediaelementaudiosourcenode-interface/mediaElementAudioSourceToScriptProcessorTest.html [ Timeout ] -crbug.com/626703 external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html [ Timeout ] crbug.com/626703 external/wpt/webauthn/interfaces.https.html [ Timeout ] crbug.com/626703 external/wpt/webauthn/makecredential-badargs-accountinformation.https.html [ Timeout ] crbug.com/626703 external/wpt/webauthn/makecredential-badargs-attestationchallenge.https.html [ Timeout ] @@ -2509,11 +2506,10 @@ crbug.com/713891 virtual/exotic-color-space/images/animated-png.html [ Pass Failure ] crbug.com/713891 virtual/exotic-color-space/images/color-profile-border-image.html [ Pass Failure ] crbug.com/713891 virtual/exotic-color-space/images/color-profile-group.html [ Pass Failure ] -crbug.com/713891 virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb.html [ Pass Failure ] -crbug.com/713891 virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb.html [ Pass Failure ] +crbug.com/731211 virtual/exotic-color-space/images/color-profile-munsell-adobe-to-srgb.html [ Pass Failure Timeout ] +crbug.com/731211 virtual/exotic-color-space/images/color-profile-munsell-srgb-to-srgb.html [ Pass Failure Timeout ] crbug.com/731153 [ Mac10.9 ] virtual/exotic-color-space/images/color-profile-reflection.html [ Failure ] - # [selectors-4] crbug.com/706118 external/wpt/css/selectors4/hover-001-manual.html [ Skip ] crbug.com/576815 external/wpt/css/selectors4/selectors-dir-selector-ltr-001.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html index 791b74a6..ad31366 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html +++ b/third_party/WebKit/LayoutTests/external/wpt/webaudio/the-audio-api/the-waveshapernode-interface/curve-tests.html
@@ -111,16 +111,7 @@ Any sample value less than -1 will correspond to the first value in the curve array. Any sample value greater than +1 will correspond to the last value in the curve array. The implementation must perform linear interpolation between adjacent points in the curve. - Note: - I found a post on the W3C audio mailing list (from one of the Chris's) that suggested it would be feasible - to use the WaveShaperNode to create constant values. */ - (function() { - var oneElementCurve=[1.0]; - var inputData=[-1.0, 0, 1.0, -2.0, 2.0]; - var expectedData=[1.0, 1.0, 1.0, 1.0, 1.0]; - executeTest(oneElementCurve, inputData, expectedData, "Testing single-element curve (boundary condition)"); - })(); /* Testing null curve (should return input values) @@ -135,22 +126,6 @@ executeTest(null, inputData, expectedData, "Testing null curve (should return input values)"); })(); - /* - Testing zero-element curve (unspecified result) - =============================================== - From the specification: - Unspecified result (I assume it will be treated in the same way as a null curve). - Note: - Mozilla test_waveShaperNoCurve.html indicates they expect same results as a null curve. - */ - (function() { - var zeroElementCurve=[]; - var inputData=[-1.0, 0, 1.0, 2.0]; - var expectedData=[-1.0, 0.0, 1.0, 2.0]; - executeTest(zeroElementCurve, inputData, expectedData, "Testing zero-element curve (unspecified result)"); - })(); - - /** * Function that does the actual testing (using an asynchronous test). * @param {?Array.<number>} curveData - Array containing values for the WaveShaper curve.
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt index c77fa42..27a18046 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-data-expected.txt
@@ -1,15 +1,15 @@ -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback3 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback4 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback5 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback6 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback7 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback8 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback9 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback10 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback11 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback12 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback4 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback5 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback6 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback7 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback8 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback9 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback10 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback11 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback12 Tests that data is correctly loaded by IndexedDBModel from IndexedDB object store and index. Dumping values, fromIndex = false, skipCount = 0, pageSize = 2, idbKeyRange = null
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-names-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-names-expected.txt index 8b19b03755..1246cb45 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-names-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-names-expected.txt
@@ -1,7 +1,7 @@ -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback3 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback4 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback4 Tests that database names are correctly loaded and saved in IndexedDBModel. Dumping database names:
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view-expected.txt index f374ce0..0f281a5 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view-expected.txt
@@ -24,10 +24,22 @@ (no entries) Object store: testObjectStore2 (no entries) -Refreshed database. +Refreshed database view. Dumping ObjectStore data: Object store: testObjectStore1 Key = testKey, value = [object Object] Object store: testObjectStore2 (no entries) +Added testObjectStore2 entry. +Dumping ObjectStore data: + Object store: testObjectStore1 + Key = testKey, value = [object Object] + Object store: testObjectStore2 + (no entries) +Right-click refreshed database. +Dumping ObjectStore data: + Object store: testObjectStore1 + Key = testKey, value = [object Object] + Object store: testObjectStore2 + Key = testKey2, value = [object Object]
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view.html b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view.html index d9c3bb0..f9fb0a8c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view.html +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-refresh-view.html
@@ -6,70 +6,6 @@ <script src="indexeddb-test.js"></script> <script> -function onIndexedDBError(e) { - console.error("IndexedDB error: " + e); -} - -function createDatabase(databaseName) { - var callback; - var promise = new Promise((fulfill) => callback = fulfill); - var request = indexedDB.open(databaseName); - request.onerror = onIndexedDBError; - request.onsuccess = function(event) { - request.result.close(); - callback(); - } - return promise; -} - -function createObjectStore(databaseName, objectStoreName, indexName, keyPath) { - var callback; - var promise = new Promise((fulfill) => callback = fulfill); - var request = indexedDB.open(databaseName); - request.onerror = onIndexedDBError; - request.onsuccess = function(event) { - var db = request.result; - var version = db.version; - db.close(); - - var upgradeRequest = indexedDB.open(databaseName, version + 1); - - upgradeRequest.onerror = onIndexedDBError; - upgradeRequest.onupgradeneeded = function(e) { - var upgradeDb = e.target.result; - var store = upgradeDb.createObjectStore(objectStoreName, { keyPath: "test", autoIncrement: false }); - store.createIndex(indexName, "test", { unique: false, multiEntry: false }); - callback(); - } - upgradeRequest.onsuccess = function(e) { - var upgradeDb = e.target.result; - upgradeDb.close(); - callback(); - } - } - return promise; -} - -function addIDBValue(databaseName, objectStoreName, key, value) { - var callback; - var promise = new Promise((fulfill) => callback = fulfill); - var request = indexedDB.open(databaseName); - request.onerror = onIndexedDBError; - request.onsuccess = function(event) { - var db = request.result; - var transaction = db.transaction(objectStoreName, "readwrite"); - var store = transaction.objectStore(objectStoreName); - store.put({ test: key, testValue: value }); - - transaction.onerror = onIndexedDBError; - transaction.oncomplete = function() { - db.close(); - callback(); - }; - } - return promise; -} - async function test() { var databaseName = "testDatabase"; @@ -81,14 +17,23 @@ var indexedDBModel = InspectorTest.mainTarget.model(Resources.IndexedDBModel); var databaseId; - function waitRefreshDatabase(callback) { + function waitRefreshDatabase() { var view = UI.panels.resources._sidebar.indexedDBListTreeElement._idbDatabaseTreeElements[0]._view; - InspectorTest.addSniffer(Resources.IDBDatabaseView.prototype, "_updatedForTests", callback, false); view._refreshDatabaseButtonClicked(); + return new Promise((resolve) => { + InspectorTest.addSniffer(Resources.IDBDatabaseView.prototype, "_updatedForTests", resolve, false) + }); } - function waitUpdateDataView(callback) { - InspectorTest.addSniffer(Resources.IDBDataView.prototype, "_updatedDataForTests", callback, false); + function waitRefreshDatabaseRightClick() { + idbDatabaseTreeElement._refreshIndexedDB(); + return waitUpdateDataView(); + } + + function waitUpdateDataView() { + return new Promise((resolve) => { + InspectorTest.addSniffer(Resources.IDBDataView.prototype, "_updatedDataForTests", resolve, false) + }); } function waitDatabaseLoaded(callback) { @@ -128,7 +73,7 @@ InspectorTest.dumpIndexedDBTree(); // Create database - await InspectorTest.evaluateInPageAsync("createDatabase('" + databaseName + "')"); + await InspectorTest.createDatabaseAsync(databaseName); await new Promise(waitDatabaseAdded); var idbDatabaseTreeElement = UI.panels.resources._sidebar.indexedDBListTreeElement._idbDatabaseTreeElements[0]; databaseId = idbDatabaseTreeElement._databaseId; @@ -142,14 +87,14 @@ var databaseView = idbDatabaseTreeElement._view; // Create first objectstore - await InspectorTest.evaluateInPageAsync("createObjectStore('" + databaseName + "', '" + objectStoreName1 + "', '" + indexName + "', '" + keyPath + "')"); - await new Promise(waitRefreshDatabase); + await InspectorTest.createObjectStoreAsync(databaseName, objectStoreName1, indexName, keyPath); + await waitRefreshDatabase(); InspectorTest.addResult("Created first objectstore."); InspectorTest.dumpIndexedDBTree(); // Create second objectstore - await InspectorTest.evaluateInPageAsync("createObjectStore('" + databaseName + "', '" + objectStoreName2 + "', '" + indexName + "', '" + keyPath + "')"); - await new Promise(waitRefreshDatabase); + await InspectorTest.createObjectStoreAsync(databaseName, objectStoreName2, indexName, keyPath); + await waitRefreshDatabase(); InspectorTest.addResult("Created second objectstore."); InspectorTest.dumpIndexedDBTree(); @@ -160,21 +105,25 @@ } // Add entries - await InspectorTest.evaluateInPageAsync("addIDBValue('" + databaseName + "', '" + objectStoreName1 + "', 'testKey', 'testValue')"); + await InspectorTest.addIDBValueAsync(databaseName, objectStoreName1, "testKey", "testValue"); InspectorTest.addResult("Added " + objectStoreName1 + " entry."); dumpObjectStores(); // Refresh database view - await new Promise(waitRefreshDatabase); - for (var i = 0; i < idbDatabaseTreeElement.childCount(); ++i) { - var objectStoreTreeElement = idbDatabaseTreeElement.childAt(i); - if (objectStoreTreeElement._objectStore.name === objectStoreName1) { - objectStoreTreeElement.onselect(false); - break; - } - } - await new Promise(waitUpdateDataView); // Wait for objectstore data to load on page. - InspectorTest.addResult("Refreshed database."); + await waitRefreshDatabase(); + await waitUpdateDataView(); // Wait for second objectstore data to load on page. + InspectorTest.addResult("Refreshed database view."); + dumpObjectStores(); + + // Add entries + await InspectorTest.addIDBValueAsync(databaseName, objectStoreName2, "testKey2", "testValue2"); + InspectorTest.addResult("Added " + objectStoreName2 + " entry."); + dumpObjectStores(); + + // Right-click refresh database view + await waitRefreshDatabaseRightClick(); + await waitUpdateDataView(); // Wait for second objectstore data to load on page. + InspectorTest.addResult("Right-click refreshed database."); dumpObjectStores(); InspectorTest.completeTest();
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-structure-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-structure-expected.txt index e3eb3df2..59ca79c 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-structure-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/database-structure-expected.txt
@@ -1,13 +1,13 @@ -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback3 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback4 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback5 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback6 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback7 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback8 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback9 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback10 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback4 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback5 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback6 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback7 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback8 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback9 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback10 Tests that database names are correctly loaded and saved in IndexedDBModel. Dumping database:
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js index cf36c59a..0efa65a 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/indexeddb-test.js
@@ -105,6 +105,18 @@ indexedDBModel.enable(); return indexedDBModel; }; + +InspectorTest.createDatabaseAsync = function(databaseName) { + return InspectorTest.evaluateInPageAsync("createDatabaseAsync('" + databaseName + "')"); +}; + +InspectorTest.createObjectStoreAsync = function(databaseName, objectStoreName, indexName, keyPath) { + return InspectorTest.evaluateInPageAsync("createObjectStoreAsync('" + databaseName + "', '" + objectStoreName + "', '" + indexName + "', '" + keyPath + "')"); +}; + +InspectorTest.addIDBValueAsync = function(databaseName, objectStoreName, key, value) { + return InspectorTest.evaluateInPageAsync("addIDBValueAsync('" + databaseName + "', '" + objectStoreName + "', '" + key + "', '" + value + "')"); +}; }; function dispatchCallback(callbackId) @@ -260,3 +272,63 @@ request.onsuccess = commitCallback; } } + +function createDatabaseAsync(databaseName) { + var callback; + var promise = new Promise((fulfill) => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + request.onsuccess = function(event) { + request.result.close(); + callback(); + } + return promise; +} + +function createObjectStoreAsync(databaseName, objectStoreName, indexName, keyPath) { + var callback; + var promise = new Promise((fulfill) => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + request.onsuccess = function(event) { + var db = request.result; + var version = db.version; + db.close(); + + var upgradeRequest = indexedDB.open(databaseName, version + 1); + + upgradeRequest.onerror = onIndexedDBError; + upgradeRequest.onupgradeneeded = function(e) { + var upgradeDb = e.target.result; + var store = upgradeDb.createObjectStore(objectStoreName, { keyPath: "test", autoIncrement: false }); + store.createIndex(indexName, "test", { unique: false, multiEntry: false }); + callback(); + } + upgradeRequest.onsuccess = function(e) { + var upgradeDb = e.target.result; + upgradeDb.close(); + callback(); + } + } + return promise; +} + +function addIDBValueAsync(databaseName, objectStoreName, key, value) { + var callback; + var promise = new Promise((fulfill) => callback = fulfill); + var request = indexedDB.open(databaseName); + request.onerror = onIndexedDBError; + request.onsuccess = function(event) { + var db = request.result; + var transaction = db.transaction(objectStoreName, "readwrite"); + var store = transaction.objectStore(objectStoreName); + store.put({ test: key, testValue: value }); + + transaction.onerror = onIndexedDBError; + transaction.oncomplete = function() { + db.close(); + callback(); + }; + } + return promise; +}
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel-expected.txt index f85d717..3d2f53fa 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/resources-panel-expected.txt
@@ -1,9 +1,9 @@ -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback3 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback4 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback5 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback6 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback4 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback5 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback6 Tests IndexedDB tree element on resources panel. Expanded IndexedDB tree element.
diff --git a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/upgrade-events-expected.txt b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/upgrade-events-expected.txt index 3151189..96b11bd8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/upgrade-events-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/inspector/indexeddb/upgrade-events-expected.txt
@@ -1,13 +1,13 @@ -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback1 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback2 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback3 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback4 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback5 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback6 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback7 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback8 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback9 -CONSOLE MESSAGE: line 112: InspectorTest.IndexedDB_callback10 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback1 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback2 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback3 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback4 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback5 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback6 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback7 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback8 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback9 +CONSOLE MESSAGE: line 124: InspectorTest.IndexedDB_callback10 Tests that deleted databases do not get recreated. Preparing database
diff --git a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-2.html b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-2.html index 2f267c5..bee53ba6 100644 --- a/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-2.html +++ b/third_party/WebKit/LayoutTests/inspector/elements/edit/set-outer-html-2.html
@@ -14,7 +14,6 @@ function test() { -setTimeout(() => InspectorTest.completeTest(), 2000); InspectorTest.runTestSuite([ function testSetUp(next) {
diff --git a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp index 3eafdb78..13c92f9 100644 --- a/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp +++ b/third_party/WebKit/Source/core/loader/DocumentThreadableLoader.cpp
@@ -1127,9 +1127,12 @@ if (!client_) return; - RefPtr<const SharedBuffer> data = resource->ResourceBuffer(); - if (data) - HandleReceivedData(data->Data(), data->size()); + if (RefPtr<const SharedBuffer> data = resource->ResourceBuffer()) { + data->ForEachSegment([this](const char* segment, size_t segment_size, + size_t segment_offset) { + HandleReceivedData(segment, segment_size); + }); + } // The client may cancel this loader in handleReceivedData(). In such a case, // skip the rest.
diff --git a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp index 176238c..83530023 100644 --- a/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp +++ b/third_party/WebKit/Source/core/paint/InlineTextBoxPainter.cpp
@@ -23,6 +23,7 @@ #include "platform/graphics/paint/DrawingRecorder.h" #include "platform/graphics/paint/PaintRecord.h" #include "platform/graphics/paint/PaintRecorder.h" +#include "platform/graphics/paint/PaintShader.h" #include "platform/wtf/Optional.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -768,7 +769,7 @@ PaintFlags flags; flags.setAntiAlias(true); flags.setColor(color); - flags.setShader(SkGradientShader::MakeLinear( + flags.setShader(PaintShader::MakeLinearGradient( pts, colors, nullptr, ARRAY_SIZE(colors), SkShader::kClamp_TileMode)); PaintRecorder recorder; recorder.beginRecording(kMarkerWidth, kMarkerHeight); @@ -812,9 +813,9 @@ PaintFlags flags; flags.setAntiAlias(true); - flags.setShader(WrapSkShader(MakePaintShaderRecord( + flags.setShader(PaintShader::MakePaintRecord( sk_ref_sp(marker), FloatRect(0, 0, kMarkerWidth, kMarkerHeight), - SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode, &local_matrix))); + SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode, &local_matrix)); // Apply the origin translation as a global transform. This ensures that the // shader local matrix depends solely on zoom => Skia can reuse the same
diff --git a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp index 26aa2ca..0bdff49 100644 --- a/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp +++ b/third_party/WebKit/Source/core/svg/graphics/SVGImage.cpp
@@ -355,13 +355,13 @@ phase.Y() + spaced_tile.Y()); PaintFlags flags; - flags.setShader( - MakePaintShaderRecord(record, spaced_tile, SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, &pattern_transform)); + flags.setShader(PaintShader::MakePaintRecord( + record, spaced_tile, SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, &pattern_transform)); // If the shader could not be instantiated (e.g. non-invertible matrix), // draw transparent. // Note: we can't simply bail, because of arbitrary blend mode. - if (!flags.getShader()) + if (!flags.HasShader()) flags.setColor(SK_ColorTRANSPARENT); flags.setBlendMode(composite_op); @@ -403,7 +403,7 @@ IntRect bounds(IntPoint(), size); - flags.setShader(MakePaintShaderRecord( + flags.setShader(PaintShader::MakePaintRecord( PaintRecordForCurrentFrame(bounds, url), bounds, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode, &local_matrix));
diff --git a/third_party/WebKit/Source/devtools/front_end/common/UIString.js b/third_party/WebKit/Source/devtools/front_end/common/UIString.js index 45f73639..9333b76 100644 --- a/third_party/WebKit/Source/devtools/front_end/common/UIString.js +++ b/third_party/WebKit/Source/devtools/front_end/common/UIString.js
@@ -42,34 +42,6 @@ /** * @param {string} string - * @param {...*} vararg - * @return {string} - */ -Common.UIString.capitalize = function(string, vararg) { - if (Common._useLowerCaseMenuTitles === undefined) - throw 'Common.setLocalizationPlatform() has not been called'; - - var localized = Common.localize(string); - var capitalized; - if (Common._useLowerCaseMenuTitles) { - capitalized = localized.replace(/\^(.)/g, '$1'); - } else { - capitalized = localized.replace(/\^(.)/g, function(str, char) { - return char.toUpperCase(); - }); - } - return String.vsprintf(capitalized, Array.prototype.slice.call(arguments, 1)); -}; - -/** - * @param {string} platform - */ -Common.setLocalizationPlatform = function(platform) { - Common._useLowerCaseMenuTitles = platform === 'windows'; -}; - -/** - * @param {string} string * @return {string} */ Common.localize = function(string) {
diff --git a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js index 5c4d60d..dd56c97 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/components/DOMBreakpointsSidebarPane.js
@@ -174,10 +174,10 @@ */ _contextMenu(breakpoint, event) { var contextMenu = new UI.ContextMenu(event); - contextMenu.appendItem(Common.UIString.capitalize('Remove ^breakpoint'), () => { + contextMenu.appendItem(Common.UIString('Remove breakpoint'), () => { breakpoint.domDebuggerModel.removeDOMBreakpoint(breakpoint.node, breakpoint.type); }); - contextMenu.appendItem(Common.UIString.capitalize('Remove ^all DOM breakpoints'), () => { + contextMenu.appendItem(Common.UIString('Remove all DOM breakpoints'), () => { breakpoint.domDebuggerModel.removeAllDOMBreakpoints(); }); contextMenu.show();
diff --git a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js index 7517eb3b..b5794649 100644 --- a/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js +++ b/third_party/WebKit/Source/devtools/front_end/components/Linkifier.js
@@ -551,30 +551,22 @@ if (info.revealable) result.push({title: Common.UIString('Reveal'), handler: () => Common.Revealer.reveal(info.revealable)}); - if (uiLocation) { - result.push({ - title: Common.UIString.capitalize('Open in Sources ^panel'), - handler: () => Common.Revealer.reveal(uiLocation) - }); - } + if (uiLocation) + result.push({title: Common.UIString('Open in Sources panel'), handler: () => Common.Revealer.reveal(uiLocation)}); + if (resource) { - result.push({ - title: Common.UIString.capitalize('Open in Application ^panel'), - handler: () => Common.Revealer.reveal(resource) - }); + result.push( + {title: Common.UIString('Open in Application panel'), handler: () => Common.Revealer.reveal(resource)}); } - if (request) { - result.push({ - title: Common.UIString.capitalize('Open in Network ^panel'), - handler: () => Common.Revealer.reveal(request) - }); - } + if (request) + result.push({title: Common.UIString('Open in Network panel'), handler: () => Common.Revealer.reveal(request)}); + if (contentProvider) { var lineNumber = uiLocation ? uiLocation.lineNumber : info.lineNumber || 0; for (var title of Components.Linkifier._linkHandlers.keys()) { var handler = Components.Linkifier._linkHandlers.get(title); var action = { - title: Common.UIString.capitalize('Open using %s', title), + title: Common.UIString('Open using %s', title), handler: handler.bind(null, contentProvider, lineNumber) }; if (title === Components.Linkifier._linkHandlerSetting().get()) @@ -743,8 +735,7 @@ UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(contentProvider.contentURL())); for (var title of Components.Linkifier._linkHandlers.keys()) { var handler = Components.Linkifier._linkHandlers.get(title); - contextMenu.appendItem( - Common.UIString.capitalize('Open using %s', title), handler.bind(null, contentProvider, 0)); + contextMenu.appendItem(Common.UIString('Open using %s', title), handler.bind(null, contentProvider, 0)); } if (contentProvider instanceof SDK.NetworkRequest) return; @@ -785,7 +776,7 @@ if (contentProvider instanceof Workspace.UISourceCode) { var uiSourceCode = /** @type {!Workspace.UISourceCode} */ (contentProvider); if (!uiSourceCode.project().canSetFileContent()) - contextMenu.appendItem(Common.UIString.capitalize('Save ^as...'), save.bind(null, true)); + contextMenu.appendItem(Common.UIString('Save as...'), save.bind(null, true)); } } };
diff --git a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js index 3cc5a05..49c2cea 100644 --- a/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js +++ b/third_party/WebKit/Source/devtools/front_end/console/ConsoleView.js
@@ -548,14 +548,13 @@ var filterSubMenu = contextMenu.appendSubMenuItem(Common.UIString('Filter')); if (consoleMessage && consoleMessage.url) { - var menuTitle = - Common.UIString.capitalize('Hide ^messages from %s', new Common.ParsedURL(consoleMessage.url).displayName); + var menuTitle = Common.UIString('Hide messages from %s', new Common.ParsedURL(consoleMessage.url).displayName); filterSubMenu.appendItem(menuTitle, this._filter.addMessageURLFilter.bind(this._filter, consoleMessage.url)); } filterSubMenu.appendSeparator(); - var unhideAll = filterSubMenu.appendItem( - Common.UIString.capitalize('Unhide ^all'), this._filter.removeMessageURLFilter.bind(this._filter)); + var unhideAll = + filterSubMenu.appendItem(Common.UIString('Unhide all'), this._filter.removeMessageURLFilter.bind(this._filter)); filterSubMenu.appendSeparator(); var hasFilters = false;
diff --git a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js index d1c6472..3e5c12c 100644 --- a/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js +++ b/third_party/WebKit/Source/devtools/front_end/data_grid/DataGrid.js
@@ -1011,7 +1011,7 @@ if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) { if (this._editCallback) { if (gridNode === this.creationNode) { - contextMenu.appendItem(Common.UIString.capitalize('Add ^new'), this._startEditing.bind(this, target)); + contextMenu.appendItem(Common.UIString('Add new'), this._startEditing.bind(this, target)); } else { var columnId = this.columnIdFromNode(target); if (columnId && this._columns[columnId].editable) { @@ -1021,7 +1021,7 @@ } } if (this._deleteCallback && gridNode !== this.creationNode) - contextMenu.appendItem(Common.UIString.capitalize('Delete'), this._deleteCallback.bind(this, gridNode)); + contextMenu.appendItem(Common.UIString('Delete'), this._deleteCallback.bind(this, gridNode)); if (this._rowContextMenuCallback) this._rowContextMenuCallback(contextMenu, gridNode); }
diff --git a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js index 2833117..fe79eb0 100644 --- a/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/elements/ElementsPanel.js
@@ -872,7 +872,7 @@ if (Elements.ElementsPanel.instance().element.isAncestor(/** @type {!Node} */ (event.target))) return; var commandCallback = Common.Revealer.reveal.bind(Common.Revealer, object); - contextMenu.appendItem(Common.UIString.capitalize('Reveal in Elements ^panel'), commandCallback); + contextMenu.appendItem(Common.UIString('Reveal in Elements panel'), commandCallback); } };
diff --git a/third_party/WebKit/Source/devtools/front_end/emulation/MediaQueryInspector.js b/third_party/WebKit/Source/devtools/front_end/emulation/MediaQueryInspector.js index 1ac838a..db09f98a 100644 --- a/third_party/WebKit/Source/devtools/front_end/emulation/MediaQueryInspector.js +++ b/third_party/WebKit/Source/devtools/front_end/emulation/MediaQueryInspector.js
@@ -115,7 +115,7 @@ var contextMenuItems = uiLocations.keysArray().sort(); var contextMenu = new UI.ContextMenu(event); - var subMenuItem = contextMenu.appendSubMenuItem(Common.UIString.capitalize('Reveal in ^source ^code')); + var subMenuItem = contextMenu.appendSubMenuItem(Common.UIString('Reveal in source code')); for (var i = 0; i < contextMenuItems.length; ++i) { var title = contextMenuItems[i]; subMenuItem.appendItem(
diff --git a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js index 197b438..7573ae5 100644 --- a/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js +++ b/third_party/WebKit/Source/devtools/front_end/host/InspectorFrontendHost.js
@@ -526,7 +526,6 @@ // so the host instance should not initialized there. initializeInspectorFrontendHost(); window.InspectorFrontendAPI = new Host.InspectorFrontendAPIImpl(); - Common.setLocalizationPlatform(InspectorFrontendHost.platform()); })(); /**
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js index 16f0bfbb..c15bedf 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkLogView.js
@@ -1103,16 +1103,14 @@ UI.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, request.contentURL())); copyMenu.appendSeparator(); - if (request.requestHeadersText()) { - copyMenu.appendItem( - Common.UIString.capitalize('Copy ^request ^headers'), this._copyRequestHeaders.bind(this, request)); - } - if (request.responseHeadersText) { - copyMenu.appendItem( - Common.UIString.capitalize('Copy ^response ^headers'), this._copyResponseHeaders.bind(this, request)); - } + if (request.requestHeadersText()) + copyMenu.appendItem(Common.UIString('Copy request headers'), this._copyRequestHeaders.bind(this, request)); + + if (request.responseHeadersText) + copyMenu.appendItem(Common.UIString('Copy response headers'), this._copyResponseHeaders.bind(this, request)); + if (request.finished) - copyMenu.appendItem(Common.UIString.capitalize('Copy ^response'), this._copyResponse.bind(this, request)); + copyMenu.appendItem(Common.UIString('Copy response'), this._copyResponse.bind(this, request)); if (Host.isWin()) { copyMenu.appendItem(Common.UIString('Copy as cURL (cmd)'), this._copyCurlCommand.bind(this, request, 'win')); @@ -1126,14 +1124,14 @@ } else { copyMenu = contextMenu.appendSubMenuItem(Common.UIString('Copy')); } - copyMenu.appendItem(Common.UIString.capitalize('Copy ^all as HAR'), this._copyAll.bind(this)); + copyMenu.appendItem(Common.UIString('Copy all as HAR'), this._copyAll.bind(this)); contextMenu.appendSeparator(); - contextMenu.appendItem(Common.UIString.capitalize('Save as HAR with ^content'), this._exportAll.bind(this)); + contextMenu.appendItem(Common.UIString('Save as HAR with content'), this._exportAll.bind(this)); contextMenu.appendSeparator(); - contextMenu.appendItem(Common.UIString.capitalize('Clear ^browser ^cache'), this._clearBrowserCache.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Clear ^browser ^cookies'), this._clearBrowserCookies.bind(this)); + contextMenu.appendItem(Common.UIString('Clear browser cache'), this._clearBrowserCache.bind(this)); + contextMenu.appendItem(Common.UIString('Clear browser cookies'), this._clearBrowserCookies.bind(this)); if (request) { contextMenu.appendSeparator(); @@ -1144,21 +1142,19 @@ var urlWithoutScheme = request.parsedURL.urlWithoutScheme(); if (urlWithoutScheme && !patterns.find(pattern => pattern.url === urlWithoutScheme)) { - contextMenu.appendItem( - Common.UIString.capitalize('Block ^request URL'), addBlockedURL.bind(null, urlWithoutScheme)); + contextMenu.appendItem(Common.UIString('Block request URL'), addBlockedURL.bind(null, urlWithoutScheme)); } else if (urlWithoutScheme) { const croppedURL = urlWithoutScheme.trimMiddle(maxBlockedURLLength); contextMenu.appendItem( - Common.UIString.capitalize('Unblock ' + croppedURL), removeBlockedURL.bind(null, urlWithoutScheme)); + Common.UIString('Unblock %s', croppedURL), removeBlockedURL.bind(null, urlWithoutScheme)); } var domain = request.parsedURL.domain(); if (domain && !patterns.find(pattern => pattern.url === domain)) { - contextMenu.appendItem(Common.UIString.capitalize('Block ^request ^domain'), addBlockedURL.bind(null, domain)); + contextMenu.appendItem(Common.UIString('Block request domain'), addBlockedURL.bind(null, domain)); } else if (domain) { const croppedDomain = domain.trimMiddle(maxBlockedURLLength); - contextMenu.appendItem( - Common.UIString.capitalize('Unblock ' + croppedDomain), removeBlockedURL.bind(null, domain)); + contextMenu.appendItem(Common.UIString('Unblock %s', croppedDomain), removeBlockedURL.bind(null, domain)); } if (SDK.NetworkManager.canReplayRequest(request)) {
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js index 21e4f43..aed4007 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkPanel.js
@@ -504,7 +504,7 @@ * @this {Network.NetworkPanel} */ function appendRevealItem(request) { - contextMenu.appendItem(Common.UIString.capitalize('Reveal in Network ^panel'), reveal.bind(this, request)); + contextMenu.appendItem(Common.UIString('Reveal in Network panel'), reveal.bind(this, request)); } if (event.target.isSelfOrDescendant(this.element))
diff --git a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js index 194848ad..f2d959ac 100644 --- a/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js +++ b/third_party/WebKit/Source/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -96,10 +96,9 @@ */ function onRowContextMenu(contextMenu, node) { contextMenu.appendItem( - Common.UIString.capitalize('Copy ^message'), - InspectorFrontendHost.copyText.bind(InspectorFrontendHost, node.data.data)); + Common.UIString('Copy message'), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, node.data.data)); contextMenu.appendSeparator(); - contextMenu.appendItem(Common.UIString.capitalize('Clear ^all'), this._clearFrames.bind(this)); + contextMenu.appendItem(Common.UIString('Clear all'), this._clearFrames.bind(this)); } }
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/CustomPreviewComponent.js b/third_party/WebKit/Source/devtools/front_end/object_ui/CustomPreviewComponent.js index d8c31e3..9d8befa 100644 --- a/third_party/WebKit/Source/devtools/front_end/object_ui/CustomPreviewComponent.js +++ b/third_party/WebKit/Source/devtools/front_end/object_ui/CustomPreviewComponent.js
@@ -226,7 +226,7 @@ _contextMenuEventFired(event) { var contextMenu = new UI.ContextMenu(event); if (this._customPreviewSection) - contextMenu.appendItem(Common.UIString.capitalize('Show as Javascript ^object'), this._disassemble.bind(this)); + contextMenu.appendItem(Common.UIString('Show as JavaScript object'), this._disassemble.bind(this)); contextMenu.appendApplicableItems(this._object); contextMenu.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js index 861debe..ea17463 100644 --- a/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js +++ b/third_party/WebKit/Source/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -810,7 +810,7 @@ contextMenu.appendApplicableItems(property.value); var copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title); contextMenu.beforeShow(() => { - contextMenu.appendItem(Common.UIString.capitalize('Copy ^property ^path'), copyPathHandler); + contextMenu.appendItem(Common.UIString('Copy property path'), copyPathHandler); }); contextMenu.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js index 2f7594a4..a271160 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapProfilerPanel.js
@@ -52,7 +52,7 @@ }); } - contextMenu.appendItem(Common.UIString.capitalize('Reveal in Summary ^view'), revealInView.bind(this, 'Summary')); + contextMenu.appendItem(Common.UIString('Reveal in Summary view'), revealInView.bind(this, 'Summary')); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js index 56597f73..ca7db43 100644 --- a/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js +++ b/third_party/WebKit/Source/devtools/front_end/profiler/HeapSnapshotDataGrids.js
@@ -134,7 +134,7 @@ } if (node instanceof Profiler.HeapSnapshotRetainingObjectNode) - contextMenu.appendItem(Common.UIString.capitalize('Reveal in Summary ^view'), revealInSummaryView.bind(this)); + contextMenu.appendItem(Common.UIString('Reveal in Summary view'), revealInSummaryView.bind(this)); } resetSortingCache() {
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js index 6f7fdec..fa24238 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/ApplicationPanelSidebar.js
@@ -57,6 +57,7 @@ this._applicationTreeElement.appendChild(clearStorageTreeElement); var storageTreeElement = this._addSidebarSection(Common.UIString('Storage')); + this._addRefreshSectionButton(storageTreeElement, this._refreshStorageSection.bind(this)); this.localStorageListTreeElement = new Resources.StorageCategoryTreeElement(panel, Common.UIString('Local Storage'), 'LocalStorage'); var localStorageIcon = UI.Icon.create('mediumicon-table', 'resource-tree-item'); @@ -83,6 +84,7 @@ storageTreeElement.appendChild(this.cookieListTreeElement); var cacheTreeElement = this._addSidebarSection(Common.UIString('Cache')); + this._addRefreshSectionButton(cacheTreeElement, this._refreshCacheSection.bind(this)); this.cacheStorageListTreeElement = new Resources.ServiceWorkerCacheTreeElement(panel); cacheTreeElement.appendChild(this.cacheStorageListTreeElement); this.applicationCacheListTreeElement = @@ -131,6 +133,32 @@ } /** + * @param {!UI.TreeElement} treeElement + * @param {function()} refresh + */ + _addRefreshSectionButton(treeElement, refresh) { + var refreshIcon = UI.Icon.create('largeicon-refresh', 'sidebar-section-button'); + refreshIcon.addEventListener('click', refresh, false); + treeElement.setTrailingIcons([refreshIcon]); + } + + _refreshStorageSection() { + var visibleView = this._panel.visibleView; + if (visibleView instanceof Resources.DOMStorageItemsView || visibleView instanceof Resources.CookieItemsView) { + // Local Storage, Session Storage || Cookies + visibleView.refreshItems(); + } else if (visibleView instanceof Resources.DatabaseTableView) { + // Web SQL + visibleView.update(); + } + this.indexedDBListTreeElement.refreshIndexedDB(); + } + + _refreshCacheSection() { + this.cacheStorageListTreeElement._refreshCaches(); + } + + /** * @override * @param {!SDK.Target} target */ @@ -1176,6 +1204,7 @@ this._idbObjectStoreTreeElements = {}; var icon = UI.Icon.create('mediumicon-database', 'resource-tree-item'); this.setLeadingIcons([icon]); + this._model.addEventListener(Resources.IndexedDBModel.Events.DatabaseNamesRefreshed, this._refreshIndexedDB, this); } get itemURL() { @@ -1197,7 +1226,7 @@ } _refreshIndexedDB() { - this._model.refreshDatabaseNames(); + this._model.refreshDatabase(this._databaseId); } /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js index 9b495578..4e75ac2 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBModel.js
@@ -175,9 +175,10 @@ this._loadDatabaseNames(databaseId.securityOrigin); } - refreshDatabaseNames() { + async refreshDatabaseNames() { for (var securityOrigin in this._databaseNamesBySecurityOrigin) - this._loadDatabaseNames(securityOrigin); + await this._loadDatabaseNames(securityOrigin); + this.dispatchEventToListeners(Resources.IndexedDBModel.Events.DatabaseNamesRefreshed); } /** @@ -414,7 +415,8 @@ Resources.IndexedDBModel.Events = { DatabaseAdded: Symbol('DatabaseAdded'), DatabaseRemoved: Symbol('DatabaseRemoved'), - DatabaseLoaded: Symbol('DatabaseLoaded') + DatabaseLoaded: Symbol('DatabaseLoaded'), + DatabaseNamesRefreshed: Symbol('DatabaseNamesRefreshed') }; /**
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js index 7380efe5..a782dbb 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js +++ b/third_party/WebKit/Source/devtools/front_end/resources/IndexedDBViews.js
@@ -34,14 +34,15 @@ Resources.IDBDatabaseView = class extends UI.VBox { /** * @param {!Resources.IndexedDBModel} model - * @param {!Resources.IndexedDBModel.Database} database + * @param {?Resources.IndexedDBModel.Database} database */ constructor(model, database) { super(); this._model = model; + var databaseName = database ? database.databaseId.name : Common.UIString('Loading\u2026'); - this._reportView = new UI.ReportView(database.databaseId.name); + this._reportView = new UI.ReportView(databaseName); this._reportView.show(this.contentElement); var bodySection = this._reportView.appendSection(''); @@ -58,7 +59,8 @@ Common.UIString('Refresh database')); footer.appendChild(this._refreshButton); - this.update(database); + if (database) + this.update(database); } _refreshDatabase() { @@ -75,6 +77,7 @@ */ update(database) { this._database = database; + this._reportView.setTitle(this._database.databaseId.name); this._refreshDatabase(); this._updatedForTests(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/resources/resourcesSidebar.css b/third_party/WebKit/Source/devtools/front_end/resources/resourcesSidebar.css index ccebe240..60783a0 100644 --- a/third_party/WebKit/Source/devtools/front_end/resources/resourcesSidebar.css +++ b/third_party/WebKit/Source/devtools/front_end/resources/resourcesSidebar.css
@@ -26,6 +26,21 @@ display: none; } +li.storage-group-list-item +.trailing-icons { + width: 14px; + height: 14px; + margin-left: 6px; +} + +li.storage-group-list-item +.trailing-icons +.sidebar-section-button { + position: relative; + top: -1px; + left: -8px; +} + .navigator-tree-item { margin: -3px -7px -3px -7px; }
diff --git a/third_party/WebKit/Source/devtools/front_end/source_frame/ImageView.js b/third_party/WebKit/Source/devtools/front_end/source_frame/ImageView.js index 11e5909..3ffbf9ee 100644 --- a/third_party/WebKit/Source/devtools/front_end/source_frame/ImageView.js +++ b/third_party/WebKit/Source/devtools/front_end/source_frame/ImageView.js
@@ -108,13 +108,12 @@ _contextMenu(event) { var contextMenu = new UI.ContextMenu(event); if (!this._parsedURL.isDataURL()) - contextMenu.appendItem(Common.UIString.capitalize('Copy ^image URL'), this._copyImageURL.bind(this)); - if (this._imagePreviewElement.src) { - contextMenu.appendItem( - Common.UIString.capitalize('Copy ^image as Data URI'), this._copyImageAsDataURL.bind(this)); - } - contextMenu.appendItem(Common.UIString.capitalize('Open ^image in ^new ^tab'), this._openInNewTab.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Save\u2026'), this._saveImage.bind(this)); + contextMenu.appendItem(Common.UIString('Copy image URL'), this._copyImageURL.bind(this)); + if (this._imagePreviewElement.src) + contextMenu.appendItem(Common.UIString('Copy image as data URI'), this._copyImageAsDataURL.bind(this)); + + contextMenu.appendItem(Common.UIString('Open image in new tab'), this._openInNewTab.bind(this)); + contextMenu.appendItem(Common.UIString('Save\u2026'), this._saveImage.bind(this)); contextMenu.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js index ef7578b..504b8d3d 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/CallStackSidebarPane.js
@@ -271,8 +271,8 @@ return; var contextMenu = new UI.ContextMenu(event); if (item.debuggerCallFrame) - contextMenu.appendItem(Common.UIString.capitalize('Restart ^frame'), () => item.debuggerCallFrame.restart()); - contextMenu.appendItem(Common.UIString.capitalize('Copy ^stack ^trace'), this._copyStackTrace.bind(this)); + contextMenu.appendItem(Common.UIString('Restart frame'), () => item.debuggerCallFrame.restart()); + contextMenu.appendItem(Common.UIString('Copy stack trace'), this._copyStackTrace.bind(this)); var location = this._itemLocation(item); if (location) { var uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location); @@ -323,22 +323,19 @@ if (canBlackbox) { if (isBlackboxed) { contextMenu.appendItem( - Common.UIString.capitalize('Stop ^blackboxing'), - manager.unblackboxUISourceCode.bind(manager, uiSourceCode)); + Common.UIString('Stop blackboxing'), manager.unblackboxUISourceCode.bind(manager, uiSourceCode)); } else { contextMenu.appendItem( - Common.UIString.capitalize('Blackbox ^script'), manager.blackboxUISourceCode.bind(manager, uiSourceCode)); + Common.UIString('Blackbox script'), manager.blackboxUISourceCode.bind(manager, uiSourceCode)); } } if (isContentScript) { if (isBlackboxed) { contextMenu.appendItem( - Common.UIString.capitalize('Stop blackboxing ^all ^content ^scripts'), - manager.blackboxContentScripts.bind(manager)); + Common.UIString('Stop blackboxing all content scripts'), manager.blackboxContentScripts.bind(manager)); } else { contextMenu.appendItem( - Common.UIString.capitalize('Blackbox ^all ^content ^scripts'), - manager.unblackboxContentScripts.bind(manager)); + Common.UIString('Blackbox all content scripts'), manager.unblackboxContentScripts.bind(manager)); } } }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js index 05418f81..27ac557 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/JavaScriptSourceFrame.js
@@ -293,7 +293,7 @@ !Bindings.blackboxManager.isBlackboxedUISourceCode(this._debuggerSourceCode)) { if (this._scriptFileForDebuggerModel.size) { var scriptFile = this._scriptFileForDebuggerModel.valuesArray()[0]; - var addSourceMapURLLabel = Common.UIString.capitalize('Add ^source ^map\u2026'); + var addSourceMapURLLabel = Common.UIString('Add source map\u2026'); contextMenu.appendItem(addSourceMapURLLabel, addSourceMapURL.bind(null, scriptFile)); contextMenu.appendSeparator(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js index 3861fa4..a7fc4e4 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/SourcesPanel.js
@@ -779,12 +779,10 @@ var binding = Persistence.persistence.binding(uiSourceCode); if (!binding) { contextMenu.appendItem( - Common.UIString.capitalize('Map to ^network ^resource\u2026'), - this.mapFileSystemToNetwork.bind(this, uiSourceCode)); + Common.UIString('Map to network resource\u2026'), this.mapFileSystemToNetwork.bind(this, uiSourceCode)); } else { contextMenu.appendItem( - Common.UIString.capitalize('Remove ^network ^mapping'), - this._removeNetworkMapping.bind(this, binding.network)); + Common.UIString('Remove network mapping'), this._removeNetworkMapping.bind(this, binding.network)); } } @@ -801,8 +799,7 @@ return; if (this._workspace.uiSourceCodeForURL(uiSourceCode.url()) === uiSourceCode) { contextMenu.appendItem( - Common.UIString.capitalize('Map to ^file ^system ^resource\u2026'), - this.mapNetworkToFileSystem.bind(this, uiSourceCode)); + Common.UIString('Map to file system resource\u2026'), this.mapNetworkToFileSystem.bind(this, uiSourceCode)); } } } @@ -820,13 +817,13 @@ if (!uiSourceCode.project().isServiceProject() && !event.target.isSelfOrDescendant(this._navigatorTabbedLocation.widget().element)) { contextMenu.appendItem( - Common.UIString.capitalize('Reveal in ^navigator'), this._handleContextMenuReveal.bind(this, uiSourceCode)); + Common.UIString('Reveal in navigator'), this._handleContextMenuReveal.bind(this, uiSourceCode)); contextMenu.appendSeparator(); } this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode); if (!uiSourceCode.project().canSetFileContent()) { contextMenu.appendItem( - Common.UIString.capitalize('Local ^modifications\u2026'), this._showLocalHistory.bind(this, uiSourceCode)); + Common.UIString('Local modifications\u2026'), this._showLocalHistory.bind(this, uiSourceCode)); } } @@ -855,10 +852,9 @@ if (contentType.hasScripts()) { var target = UI.context.flavor(SDK.Target); var debuggerModel = target ? target.model(SDK.DebuggerModel) : null; - if (debuggerModel && debuggerModel.isPaused()) { - contextMenu.appendItem( - Common.UIString.capitalize('Continue to ^here'), this._continueToLocation.bind(this, uiLocation)); - } + if (debuggerModel && debuggerModel.isPaused()) + contextMenu.appendItem(Common.UIString('Continue to here'), this._continueToLocation.bind(this, uiLocation)); + this._callstackPane.appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode); } } @@ -880,11 +876,10 @@ return; var remoteObject = /** @type {!SDK.RemoteObject} */ (target); contextMenu.appendItem( - Common.UIString.capitalize('Store as ^global ^variable'), this._saveToTempVariable.bind(this, remoteObject)); + Common.UIString('Store as global variable'), this._saveToTempVariable.bind(this, remoteObject)); if (remoteObject.type === 'function') { contextMenu.appendItem( - Common.UIString.capitalize('Show ^function ^definition'), - this._showFunctionDefinition.bind(this, remoteObject)); + Common.UIString('Show function definition'), this._showFunctionDefinition.bind(this, remoteObject)); } } @@ -899,7 +894,7 @@ var uiSourceCode = this._workspace.uiSourceCodeForURL(request.url()); if (!uiSourceCode) return; - var openText = Common.UIString.capitalize('Open in Sources ^panel'); + var openText = Common.UIString('Open in Sources panel'); contextMenu.appendItem(openText, this.showUILocation.bind(this, uiSourceCode.uiLocation(0, 0))); }
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js index 2d2121b..bc98f10 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -156,12 +156,11 @@ isEditing |= watchExpression.isEditing(); if (!isEditing) - contextMenu.appendItem(Common.UIString.capitalize('Add ^watch ^expression'), this._addButtonClicked.bind(this)); + contextMenu.appendItem(Common.UIString('Add watch expression'), this._addButtonClicked.bind(this)); - if (this._watchExpressions.length > 1) { - contextMenu.appendItem( - Common.UIString.capitalize('Delete ^all ^watch ^expressions'), this._deleteAllButtonClicked.bind(this)); - } + if (this._watchExpressions.length > 1) + contextMenu.appendItem(Common.UIString('Delete all watch expressions'), this._deleteAllButtonClicked.bind(this)); + var target = event.deepElementFromPoint(); if (!target) @@ -405,13 +404,12 @@ * @param {!Event} event */ _populateContextMenu(contextMenu, event) { - if (!this.isEditing()) { - contextMenu.appendItem( - Common.UIString.capitalize('Delete ^watch ^expression'), this._updateExpression.bind(this, null)); - } + if (!this.isEditing()) + contextMenu.appendItem(Common.UIString('Delete watch expression'), this._updateExpression.bind(this, null)); + if (!this.isEditing() && this._result && (this._result.type === 'number' || this._result.type === 'string')) - contextMenu.appendItem(Common.UIString.capitalize('Copy ^value'), this._copyValueButtonClicked.bind(this)); + contextMenu.appendItem(Common.UIString('Copy value'), this._copyValueButtonClicked.bind(this)); var target = event.deepElementFromPoint(); if (target && this._valueElement.isSelfOrAncestor(target))
diff --git a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js index c4bdfe8..ba70f808 100644 --- a/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js +++ b/third_party/WebKit/Source/devtools/front_end/sources/XHRBreakpointsSidebarPane.js
@@ -36,7 +36,7 @@ _emptyElementContextMenu(event) { var contextMenu = new UI.ContextMenu(event); - contextMenu.appendItem(Common.UIString.capitalize('Add ^breakpoint'), this._addButtonClicked.bind(this)); + contextMenu.appendItem(Common.UIString('Add breakpoint'), this._addButtonClicked.bind(this)); contextMenu.show(); } @@ -153,10 +153,10 @@ this._removeBreakpoint(url); } } - var removeAllTitle = Common.UIString.capitalize('Remove ^all ^breakpoints'); + var removeAllTitle = Common.UIString('Remove all breakpoints'); - contextMenu.appendItem(Common.UIString.capitalize('Add ^breakpoint'), this._addButtonClicked.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Remove ^breakpoint'), removeBreakpoint.bind(this)); + contextMenu.appendItem(Common.UIString('Add breakpoint'), this._addButtonClicked.bind(this)); + contextMenu.appendItem(Common.UIString('Remove breakpoint'), removeBreakpoint.bind(this)); contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this)); contextMenu.show(); }
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/ReportView.js b/third_party/WebKit/Source/devtools/front_end/ui/ReportView.js index bd08064..16b6346 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/ReportView.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/ReportView.js
@@ -14,12 +14,22 @@ var contentBox = this.contentElement.createChild('div', 'report-content-box'); this._headerElement = contentBox.createChild('div', 'report-header vbox'); - this._headerElement.createChild('div', 'report-title').textContent = title; + this._titleElement = this._headerElement.createChild('div', 'report-title'); + this._titleElement.textContent = title; this._sectionList = contentBox.createChild('div', 'vbox'); } /** + * @param {string} title + */ + setTitle(title) { + if (this._titleElement && this._titleElement.textContent === title) + return; + this._titleElement.textContent = title; + } + + /** * @param {string} subtitle */ setSubtitle(subtitle) {
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js index f237768..db8eb31 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/TabbedPane.js
@@ -1185,10 +1185,10 @@ var contextMenu = new UI.ContextMenu(event); if (this._closeable) { - contextMenu.appendItem(Common.UIString.capitalize('Close'), close.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Close ^others'), closeOthers.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Close ^tabs to the ^right'), closeToTheRight.bind(this)); - contextMenu.appendItem(Common.UIString.capitalize('Close ^all'), closeAll.bind(this)); + contextMenu.appendItem(Common.UIString('Close'), close.bind(this)); + contextMenu.appendItem(Common.UIString('Close others'), closeOthers.bind(this)); + contextMenu.appendItem(Common.UIString('Close tabs to the right'), closeToTheRight.bind(this)); + contextMenu.appendItem(Common.UIString('Close all'), closeAll.bind(this)); } if (this._delegate) this._delegate.onContextMenu(this.id, contextMenu);
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js index f165b66..6f458e91 100644 --- a/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js +++ b/third_party/WebKit/Source/devtools/front_end/ui/UIUtils.js
@@ -630,14 +630,14 @@ * @return {string} */ UI.openLinkExternallyLabel = function() { - return Common.UIString.capitalize('Open in ^new ^tab'); + return Common.UIString('Open in new tab'); }; /** * @return {string} */ UI.copyLinkAddressLabel = function() { - return Common.UIString.capitalize('Copy ^link ^address'); + return Common.UIString('Copy link address'); }; /**
diff --git a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp index 56255791..a7b5b033 100644 --- a/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp +++ b/third_party/WebKit/Source/modules/canvas2d/BaseRenderingContext2D.cpp
@@ -1831,9 +1831,8 @@ if (is_source_over && image_type == CanvasRenderingContext2DState::kNoImage) { - PaintShader* shader = flags->getShader(); - if (shader) { - if (shader->isOpaque() && alpha == 0xFF) + if (flags->HasShader()) { + if (flags->ShaderIsOpaque() && alpha == 0xFF) GetImageBuffer()->WillOverwriteCanvas(); return; }
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp index 1a53ff5..0bc75ca1 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.cpp +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.cpp
@@ -55,17 +55,25 @@ VRDisplay::VRDisplay(NavigatorVR* navigator_vr, device::mojom::blink::VRDisplayPtr display, device::mojom::blink::VRDisplayClientRequest request) - : ContextLifecycleObserver(navigator_vr->GetDocument()), + : SuspendableObject(navigator_vr->GetDocument()), navigator_vr_(navigator_vr), capabilities_(new VRDisplayCapabilities()), eye_parameters_left_(new VREyeParameters()), eye_parameters_right_(new VREyeParameters()), display_(std::move(display)), submit_frame_client_binding_(this), - display_client_binding_(this, std::move(request)) {} + display_client_binding_(this, std::move(request)) { + SuspendIfNeeded(); // Initialize SuspendabaleObject. +} VRDisplay::~VRDisplay() {} +void VRDisplay::Suspend() {} + +void VRDisplay::Resume() { + RequestVSync(); +} + VRController* VRDisplay::Controller() { return navigator_vr_->Controller(); } @@ -135,6 +143,9 @@ << " in_animation_frame_=" << in_animation_frame_ << " did_submit_this_frame_=" << did_submit_this_frame_; + if (!pending_vrdisplay_raf_) + return; + // The logic here is a bit subtle. We get called from one of the following // four contexts: // @@ -802,6 +813,12 @@ return; } + if (doc->IsContextSuspended()) { + // We are currently suspended - try ProcessScheduledAnimations again later + // when we resume. + return; + } + TRACE_EVENT1("gpu", "VRDisplay::OnVSync", "frame", vr_frame_id_); if (pending_vrdisplay_raf_ && scripted_animation_controller_) { @@ -911,7 +928,8 @@ return EventTargetNames::VRDisplay; } -void VRDisplay::ContextDestroyed(ExecutionContext*) { +void VRDisplay::ContextDestroyed(ExecutionContext* context) { + SuspendableObject::ContextDestroyed(context); ForceExitPresent(); scripted_animation_controller_.Clear(); }
diff --git a/third_party/WebKit/Source/modules/vr/VRDisplay.h b/third_party/WebKit/Source/modules/vr/VRDisplay.h index 308ed3f..87ceae0 100644 --- a/third_party/WebKit/Source/modules/vr/VRDisplay.h +++ b/third_party/WebKit/Source/modules/vr/VRDisplay.h
@@ -7,6 +7,7 @@ #include "core/dom/Document.h" #include "core/dom/FrameRequestCallback.h" +#include "core/dom/SuspendableObject.h" #include "core/events/EventTarget.h" #include "device/vr/vr_service.mojom-blink.h" #include "modules/vr/VRDisplayCapabilities.h" @@ -39,7 +40,7 @@ class VRDisplay final : public EventTargetWithInlineData, public ActiveScriptWrappable<VRDisplay>, - public ContextLifecycleObserver, + public SuspendableObject, public device::mojom::blink::VRDisplayClient, public device::mojom::blink::VRSubmitFrameClient { DEFINE_WRAPPERTYPEINFO(); @@ -89,6 +90,10 @@ // ScriptWrappable implementation. bool HasPendingActivity() const final; + // SuspendableObject: + void Suspend() override; + void Resume() override; + void FocusChanged(); DECLARE_VIRTUAL_TRACE();
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp index 6bdb579e..69b3132 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.cpp
@@ -95,6 +95,7 @@ destination_node_(nullptr), is_cleared_(false), is_resolving_resume_promises_(false), + has_posted_cleanup_task_(false), user_gesture_required_(false), connection_count_(0), deferred_task_handler_(DeferredTaskHandler::Create()), @@ -149,7 +150,6 @@ // be in the destructor if there are still AudioNodes around. DCHECK(!IsDestinationInitialized()); DCHECK(!active_source_nodes_.size()); - DCHECK(!finished_source_handlers_.size()); DCHECK(!is_resolving_resume_promises_); DCHECK(!resume_resolvers_.size()); DCHECK(!autoplay_status_.has_value()); @@ -700,34 +700,10 @@ void BaseAudioContext::NotifySourceNodeFinishedProcessing( AudioHandler* handler) { DCHECK(IsAudioThread()); + MutexLocker lock(finished_source_handlers_mutex_); finished_source_handlers_.push_back(handler); } -void BaseAudioContext::RemoveFinishedSourceNodes(bool needs_removal) { - DCHECK(IsAudioThread()); - - if (needs_removal) { - Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask( - BLINK_FROM_HERE, - CrossThreadBind( - &BaseAudioContext::RemoveFinishedSourceNodesOnMainThread, - WrapCrossThreadPersistent(this))); - } -} - -void BaseAudioContext::RemoveFinishedSourceNodesOnMainThread() { - DCHECK(IsMainThread()); - AutoLocker locker(this); - // Quadratic worst case, but sizes of both vectors are considered - // manageable, especially |m_finishedSourceNodes| is likely to be short. - for (AudioNode* node : finished_source_nodes_) { - size_t i = active_source_nodes_.Find(node); - if (i != kNotFound) - active_source_nodes_.erase(i); - } - finished_source_nodes_.clear(); -} - Document* BaseAudioContext::GetDocument() const { return ToDocument(GetExecutionContext()); } @@ -754,26 +730,6 @@ return false; } -bool BaseAudioContext::ReleaseFinishedSourceNodes() { - DCHECK(IsGraphOwner()); - DCHECK(IsAudioThread()); - bool did_remove = false; - for (AudioHandler* handler : finished_source_handlers_) { - for (AudioNode* node : active_source_nodes_) { - if (finished_source_nodes_.Contains(node)) - continue; - if (handler == &node->Handler()) { - handler->BreakConnection(); - finished_source_nodes_.insert(node); - did_remove = true; - break; - } - } - } - finished_source_handlers_.clear(); - return did_remove; -} - void BaseAudioContext::NotifySourceNodeStartedProcessing(AudioNode* node) { DCHECK(IsMainThread()); AutoLocker locker(this); @@ -791,23 +747,11 @@ } void BaseAudioContext::HandleStoppableSourceNodes() { + DCHECK(IsAudioThread()); DCHECK(IsGraphOwner()); - // Find AudioBufferSourceNodes to see if we can stop playing them. - for (AudioNode* node : active_source_nodes_) { - // If the AudioNode has been marked as finished and released by - // the audio thread, but not yet removed by the main thread - // (see releaseActiveSourceNodes() above), |node| must not be - // touched as its handler may have been released already. - if (finished_source_nodes_.Contains(node)) - continue; - if (node->Handler().GetNodeType() == - AudioHandler::kNodeTypeAudioBufferSource) { - AudioBufferSourceNode* source_node = - static_cast<AudioBufferSourceNode*>(node); - source_node->GetAudioBufferSourceHandler().HandleStoppableSourceNode(); - } - } + if (active_source_nodes_.size()) + ScheduleMainThreadCleanup(); } void BaseAudioContext::HandlePreRenderTasks( @@ -844,39 +788,88 @@ // is that there will be some nodes which will take slightly longer than usual // to be deleted or removed from the render graph (in which case they'll // render silence). - bool did_remove = false; if (TryLock()) { // Take care of AudioNode tasks where the tryLock() failed previously. GetDeferredTaskHandler().BreakConnections(); - // Dynamically clean up nodes which are no longer needed. - did_remove = ReleaseFinishedSourceNodes(); - GetDeferredTaskHandler().HandleDeferredTasks(); GetDeferredTaskHandler().RequestToDeleteHandlersOnMainThread(); unlock(); } - - RemoveFinishedSourceNodes(did_remove); } -void BaseAudioContext::ResolvePromisesForResumeOnMainThread() { +void BaseAudioContext::PerformCleanupOnMainThread() { DCHECK(IsMainThread()); AutoLocker locker(this); - for (auto& resolver : resume_resolvers_) { - if (context_state_ == kClosed) { - resolver->Reject(DOMException::Create( - kInvalidStateError, "Cannot resume a context that has been closed")); - } else { - SetContextState(kRunning); - resolver->Resolve(); + if (is_resolving_resume_promises_) { + for (auto& resolver : resume_resolvers_) { + if (context_state_ == kClosed) { + resolver->Reject(DOMException::Create( + kInvalidStateError, + "Cannot resume a context that has been closed")); + } else { + SetContextState(kRunning); + resolver->Resolve(); + } } + resume_resolvers_.clear(); + is_resolving_resume_promises_ = false; } - resume_resolvers_.clear(); - is_resolving_resume_promises_ = false; + if (active_source_nodes_.size()) { + // Find AudioBufferSourceNodes to see if we can stop playing them. + for (AudioNode* node : active_source_nodes_) { + if (node->Handler().GetNodeType() == + AudioHandler::kNodeTypeAudioBufferSource) { + AudioBufferSourceNode* source_node = + static_cast<AudioBufferSourceNode*>(node); + source_node->GetAudioBufferSourceHandler().HandleStoppableSourceNode(); + } + } + + Vector<AudioHandler*> finished_handlers; + { + MutexLocker lock(finished_source_handlers_mutex_); + finished_source_handlers_.swap(finished_handlers); + } + // Break the connection and release active nodes that have finished + // playing. + unsigned remove_count = 0; + Vector<bool> removables; + removables.resize(active_source_nodes_.size()); + for (AudioHandler* handler : finished_handlers) { + for (unsigned i = 0; i < active_source_nodes_.size(); ++i) { + if (handler == &active_source_nodes_[i]->Handler()) { + handler->BreakConnection(); + removables[i] = true; + remove_count++; + break; + } + } + } + + // Copy over the surviving active nodes. + HeapVector<Member<AudioNode>> actives; + actives.ReserveInitialCapacity(active_source_nodes_.size() - remove_count); + for (unsigned i = 0; i < removables.size(); ++i) { + if (!removables[i]) + actives.push_back(active_source_nodes_[i]); + } + active_source_nodes_.swap(actives); + } + has_posted_cleanup_task_ = false; +} + +void BaseAudioContext::ScheduleMainThreadCleanup() { + if (has_posted_cleanup_task_) + return; + Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask( + BLINK_FROM_HERE, + CrossThreadBind(&BaseAudioContext::PerformCleanupOnMainThread, + WrapCrossThreadPersistent(this))); + has_posted_cleanup_task_ = true; } void BaseAudioContext::ResolvePromisesForResume() { @@ -890,10 +883,7 @@ // often and it takes some time to resolve the promises in the main thread. if (!is_resolving_resume_promises_ && resume_resolvers_.size() > 0) { is_resolving_resume_promises_ = true; - Platform::Current()->MainThread()->GetWebTaskRunner()->PostTask( - BLINK_FROM_HERE, - CrossThreadBind(&BaseAudioContext::ResolvePromisesForResumeOnMainThread, - WrapCrossThreadPersistent(this))); + ScheduleMainThreadCleanup(); } }
diff --git a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h index 13db3f7..20852989 100644 --- a/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h +++ b/third_party/WebKit/Source/modules/webaudio/BaseAudioContext.h
@@ -273,16 +273,6 @@ // Called at the end of each render quantum. void HandlePostRenderTasks(); - // Called periodically at the end of each render quantum to release - // finished source nodes. Updates m_finishedSourceNodes with nodes - // to be deleted. Returns true if any node needs deletion. Must be - // run from the audio thread. - bool ReleaseFinishedSourceNodes(); - - // The finished source nodes found by |releaseFinishedSourceNodes| - // will be removed on the main thread, which is done here. - void RemoveFinishedSourceNodes(bool needs_removal); - // Keeps track of the number of connections made. void IncrementConnectionCount() { DCHECK(IsMainThread()); @@ -413,11 +403,6 @@ // haven't finished playing. Make sure to release them here. void ReleaseActiveSourceNodes(); - // Actually remove the nodes noted for deletion by - // releaseFinishedSourceNodes. Must be run from the main thread, - // and must not be run with the context lock. - void RemoveFinishedSourceNodesOnMainThread(); - // Returns the Document wich wich the instance is associated. Document* GetDocument() const; @@ -430,9 +415,12 @@ // Listener for the PannerNodes Member<AudioListener> listener_; - // Only accessed in the audio thread. + // Accessed by audio thread and main thread, coordinated using + // the associated mutex. + // // These raw pointers are safe because AudioSourceNodes in - // m_activeSourceNodes own them. + // active_source_nodes_ own them. + Mutex finished_source_handlers_mutex_; Vector<AudioHandler*> finished_source_handlers_; // List of source nodes. This is either accessed when the graph lock is @@ -443,17 +431,24 @@ // this. HeapVector<Member<AudioNode>> active_source_nodes_; - // The main thread controls m_activeSourceNodes, all updates and additions - // are performed by it. When the audio thread marks a source node as finished, - // the nodes are added to |m_finishedSourceNodes| and scheduled for removal - // from |m_activeSourceNodes| by the main thread. - HashSet<UntracedMember<AudioNode>> finished_source_nodes_; - - // FIXME(dominicc): Move these to AudioContext because only - // it creates these Promises. - // Handle Promises for resume() and suspend() + // Called by the audio thread to handle Promises for resume() and suspend(), + // posting a main thread task to perform the actual resolving, if needed. + // + // TODO(dominicc): Move to AudioContext because only it creates + // these Promises. void ResolvePromisesForResume(); - void ResolvePromisesForResumeOnMainThread(); + + // The audio thread relies on the main thread to perform some operations + // over the objects that it owns and controls; |ScheduleMainThreadCleanup()| + // posts the task to initiate those. + // + // That is, we combine all those sub-tasks into one task action for + // convenience and performance, |PerformCleanupOnMainThread()|. It handles + // promise resolving, stopping and finishing up of audio source nodes etc. + // Actions that should happen, but can happen asynchronously to the + // audio thread making rendering progress. + void ScheduleMainThreadCleanup(); + void PerformCleanupOnMainThread(); // When the context is going away, reject any pending script promise // resolvers. @@ -467,6 +462,11 @@ // don't want to call resolve an excessive number of times. bool is_resolving_resume_promises_; + // Set to |true| by the audio thread when it posts a main-thread task to + // perform delayed state sync'ing updates that needs to be done on the main + // thread. Cleared by the main thread task once it has run. + bool has_posted_cleanup_task_; + // Whether a user gesture is required to start this AudioContext. bool user_gesture_required_;
diff --git a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp index b7dcfba5..257fc90 100644 --- a/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp +++ b/third_party/WebKit/Source/modules/webaudio/OfflineAudioContext.cpp
@@ -388,17 +388,13 @@ // OfflineGraphAutoLocker here locks the audio graph for the same reason // above in |handlePreOfflineRenderTasks|. - bool did_remove = false; { OfflineGraphAutoLocker locker(this); GetDeferredTaskHandler().BreakConnections(); - did_remove = ReleaseFinishedSourceNodes(); GetDeferredTaskHandler().HandleDeferredTasks(); GetDeferredTaskHandler().RequestToDeleteHandlersOnMainThread(); } - - RemoveFinishedSourceNodes(did_remove); } OfflineAudioDestinationHandler& OfflineAudioContext::DestinationHandler() {
diff --git a/third_party/WebKit/Source/platform/graphics/Gradient.cpp b/third_party/WebKit/Source/platform/graphics/Gradient.cpp index a96f9f7..af08ed4 100644 --- a/third_party/WebKit/Source/platform/graphics/Gradient.cpp +++ b/third_party/WebKit/Source/platform/graphics/Gradient.cpp
@@ -121,7 +121,7 @@ } } -sk_sp<PaintShader> Gradient::CreateShaderInternal( +std::unique_ptr<PaintShader> Gradient::CreateShaderInternal( const SkMatrix& local_matrix) { SortStopsIfNecessary(); DCHECK(stops_sorted_); @@ -151,20 +151,20 @@ uint32_t flags = color_interpolation_ == ColorInterpolation::kPremultiplied ? SkGradientShader::kInterpolateColorsInPremul_Flag : 0; - sk_sp<SkShader> shader = CreateShader(colors, pos, tile, flags, local_matrix); - if (!shader) { - // use last color, since our "geometry" was degenerate (e.g. radius==0) - shader = SkShader::MakeColorShader(colors.back()); - } + std::unique_ptr<PaintShader> shader = + CreateShader(colors, pos, tile, flags, local_matrix, colors.back()); + DCHECK(shader); - return WrapSkShader(std::move(shader)); + return shader; } void Gradient::ApplyToFlags(PaintFlags& flags, const SkMatrix& local_matrix) { - if (!cached_shader_ || local_matrix != cached_shader_->getLocalMatrix()) + if (!cached_shader_ || + local_matrix != cached_shader_->sk_shader()->getLocalMatrix()) { cached_shader_ = CreateShaderInternal(local_matrix); + } - flags.setShader(cached_shader_); + flags.setShader(WTF::MakeUnique<PaintShader>(*cached_shader_)); // Legacy behavior: gradients are always dithered. flags.setDither(true); @@ -183,15 +183,17 @@ p1_(p1) {} protected: - sk_sp<SkShader> CreateShader(const ColorBuffer& colors, - const OffsetBuffer& pos, - SkShader::TileMode tile_mode, - uint32_t flags, - const SkMatrix& local_matrix) const override { + std::unique_ptr<PaintShader> CreateShader( + const ColorBuffer& colors, + const OffsetBuffer& pos, + SkShader::TileMode tile_mode, + uint32_t flags, + const SkMatrix& local_matrix, + SkColor fallback_color) const override { SkPoint pts[2] = {p0_.Data(), p1_.Data()}; - return SkGradientShader::MakeLinear(pts, colors.data(), pos.data(), - static_cast<int>(colors.size()), - tile_mode, flags, &local_matrix); + return PaintShader::MakeLinearGradient( + pts, colors.data(), pos.data(), static_cast<int>(colors.size()), + tile_mode, flags, &local_matrix, fallback_color); } private: @@ -216,11 +218,13 @@ aspect_ratio_(aspect_ratio) {} protected: - sk_sp<SkShader> CreateShader(const ColorBuffer& colors, - const OffsetBuffer& pos, - SkShader::TileMode tile_mode, - uint32_t flags, - const SkMatrix& local_matrix) const override { + std::unique_ptr<PaintShader> CreateShader( + const ColorBuffer& colors, + const OffsetBuffer& pos, + SkShader::TileMode tile_mode, + uint32_t flags, + const SkMatrix& local_matrix, + SkColor fallback_color) const override { SkTCopyOnFirstWrite<SkMatrix> adjusted_local_matrix(local_matrix); if (aspect_ratio_ != 1) { // CSS3 elliptical gradients: apply the elliptical scaling at the @@ -233,20 +237,20 @@ // Since the two-point radial gradient is slower than the plain radial, // only use it if we have to. if (p0_ == p1_ && r0_ <= 0.0f) { - return SkGradientShader::MakeRadial( + return PaintShader::MakeRadialGradient( p1_.Data(), r1_, colors.data(), pos.data(), static_cast<int>(colors.size()), tile_mode, flags, - adjusted_local_matrix); + adjusted_local_matrix, fallback_color); } // The radii we give to Skia must be positive. If we're given a // negative radius, ask for zero instead. const SkScalar radius0 = std::max(WebCoreFloatToSkScalar(r0_), 0.0f); const SkScalar radius1 = std::max(WebCoreFloatToSkScalar(r1_), 0.0f); - return SkGradientShader::MakeTwoPointConical( + return PaintShader::MakeTwoPointConicalGradient( p0_.Data(), radius0, p1_.Data(), radius1, colors.data(), pos.data(), static_cast<int>(colors.size()), tile_mode, flags, - adjusted_local_matrix); + adjusted_local_matrix, fallback_color); } private: @@ -267,11 +271,13 @@ angle_(angle) {} protected: - sk_sp<SkShader> CreateShader(const ColorBuffer& colors, - const OffsetBuffer& pos, - SkShader::TileMode tile_mode, - uint32_t flags, - const SkMatrix& local_matrix) const override { + std::unique_ptr<PaintShader> CreateShader( + const ColorBuffer& colors, + const OffsetBuffer& pos, + SkShader::TileMode tile_mode, + uint32_t flags, + const SkMatrix& local_matrix, + SkColor fallback_color) const override { DCHECK_NE(tile_mode, SkShader::kMirror_TileMode); // Skia's sweep gradient angles are relative to the x-axis, not the y-axis. @@ -282,9 +288,10 @@ position_.Y()); } - return SkGradientShader::MakeSweep( + return PaintShader::MakeSweepGradient( position_.X(), position_.Y(), colors.data(), pos.data(), - static_cast<int>(colors.size()), flags, adjusted_local_matrix); + static_cast<int>(colors.size()), flags, adjusted_local_matrix, + fallback_color); } private:
diff --git a/third_party/WebKit/Source/platform/graphics/Gradient.h b/third_party/WebKit/Source/platform/graphics/Gradient.h index 8eb54c1..b7a1c6a5 100644 --- a/third_party/WebKit/Source/platform/graphics/Gradient.h +++ b/third_party/WebKit/Source/platform/graphics/Gradient.h
@@ -102,14 +102,16 @@ using ColorBuffer = Vector<SkColor, 8>; using OffsetBuffer = Vector<SkScalar, 8>; - virtual sk_sp<SkShader> CreateShader(const ColorBuffer&, - const OffsetBuffer&, - SkShader::TileMode, - uint32_t flags, - const SkMatrix&) const = 0; + virtual std::unique_ptr<PaintShader> CreateShader(const ColorBuffer&, + const OffsetBuffer&, + SkShader::TileMode, + uint32_t flags, + const SkMatrix&, + SkColor) const = 0; private: - sk_sp<PaintShader> CreateShaderInternal(const SkMatrix& local_matrix); + std::unique_ptr<PaintShader> CreateShaderInternal( + const SkMatrix& local_matrix); void SortStopsIfNecessary(); void FillSkiaStops(ColorBuffer&, OffsetBuffer&) const; @@ -121,7 +123,7 @@ Vector<ColorStop, 2> stops_; bool stops_sorted_; - mutable sk_sp<PaintShader> cached_shader_; + mutable std::unique_ptr<PaintShader> cached_shader_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Image.cpp b/third_party/WebKit/Source/platform/graphics/Image.cpp index c0fe493d..d930750 100644 --- a/third_party/WebKit/Source/platform/graphics/Image.cpp +++ b/third_party/WebKit/Source/platform/graphics/Image.cpp
@@ -227,14 +227,15 @@ namespace { -sk_sp<PaintShader> CreatePatternShader(const PaintImage& image, - const SkMatrix& shader_matrix, - const PaintFlags& paint, - const FloatSize& spacing, - SkShader::TileMode tmx, - SkShader::TileMode tmy) { - if (spacing.IsZero()) - return MakePaintShaderImage(image.sk_image(), tmx, tmy, &shader_matrix); +std::unique_ptr<PaintShader> CreatePatternShader(const PaintImage& image, + const SkMatrix& shader_matrix, + const PaintFlags& paint, + const FloatSize& spacing, + SkShader::TileMode tmx, + SkShader::TileMode tmy) { + if (spacing.IsZero()) { + return PaintShader::MakeImage(image.sk_image(), tmx, tmy, &shader_matrix); + } // Arbitrary tiling is currently only supported for SkPictureShader, so we use // that instead of a plain bitmap shader to implement spacing. @@ -246,8 +247,8 @@ PaintCanvas* canvas = recorder.beginRecording(tile_rect); canvas->drawImage(image, 0, 0, &paint); - return MakePaintShaderRecord(recorder.finishRecordingAsPicture(), tile_rect, - tmx, tmy, &shader_matrix); + return PaintShader::MakePaintRecord(recorder.finishRecordingAsPicture(), + tile_rect, tmx, tmy, &shader_matrix); } SkShader::TileMode ComputeTileMode(float left, @@ -327,7 +328,7 @@ // If the shader could not be instantiated (e.g. non-invertible matrix), // draw transparent. // Note: we can't simply bail, because of arbitrary blend mode. - if (!flags.getShader()) + if (!flags.HasShader()) flags.setColor(SK_ColorTRANSPARENT); context.DrawRect(dest_rect, flags); @@ -359,9 +360,10 @@ if (!image) return false; - flags.setShader(image->makeShader(SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, &local_matrix)); - if (!flags.getShader()) + flags.setShader( + PaintShader::MakeImage(std::move(image), SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, &local_matrix)); + if (!flags.HasShader()) return false; // Animation is normally refreshed in draw() impls, which we don't call when
diff --git a/third_party/WebKit/Source/platform/graphics/ImagePattern.cpp b/third_party/WebKit/Source/platform/graphics/ImagePattern.cpp index b913790..dbf9de5 100644 --- a/third_party/WebKit/Source/platform/graphics/ImagePattern.cpp +++ b/third_party/WebKit/Source/platform/graphics/ImagePattern.cpp
@@ -29,14 +29,16 @@ return local_matrix != previous_local_matrix_; } -sk_sp<PaintShader> ImagePattern::CreateShader(const SkMatrix& local_matrix) { - if (!tile_image_) - return WrapSkShader(SkShader::MakeColorShader(SK_ColorTRANSPARENT)); +std::unique_ptr<PaintShader> ImagePattern::CreateShader( + const SkMatrix& local_matrix) { + if (!tile_image_) { + return PaintShader::MakeColor(SK_ColorTRANSPARENT); + } if (IsRepeatXY()) { // Fast path: for repeatXY we just return a shader from the original image. - return MakePaintShaderImage(tile_image_, SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, &local_matrix); + return PaintShader::MakeImage(tile_image_, SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, &local_matrix); } // Skia does not have a "draw the tile only once" option. Clamp_TileMode @@ -73,8 +75,8 @@ SkMatrix adjusted_matrix(local_matrix); adjusted_matrix.postTranslate(-border_pixel_x, -border_pixel_y); - return MakePaintShaderImage(std::move(tile_image), tile_mode_x, tile_mode_y, - &adjusted_matrix); + return PaintShader::MakeImage(std::move(tile_image), tile_mode_x, tile_mode_y, + &adjusted_matrix); } bool ImagePattern::IsTextureBacked() const {
diff --git a/third_party/WebKit/Source/platform/graphics/ImagePattern.h b/third_party/WebKit/Source/platform/graphics/ImagePattern.h index a9c0ffb..ed52189 100644 --- a/third_party/WebKit/Source/platform/graphics/ImagePattern.h +++ b/third_party/WebKit/Source/platform/graphics/ImagePattern.h
@@ -20,7 +20,7 @@ bool IsTextureBacked() const override; protected: - sk_sp<PaintShader> CreateShader(const SkMatrix&) override; + std::unique_ptr<PaintShader> CreateShader(const SkMatrix&) override; bool IsLocalMatrixChanged(const SkMatrix&) const override; private:
diff --git a/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.cpp b/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.cpp index 1a9250f..c3b59885 100644 --- a/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.cpp +++ b/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.cpp
@@ -33,11 +33,11 @@ PaintRecordPattern::~PaintRecordPattern() {} -sk_sp<PaintShader> PaintRecordPattern::CreateShader( +std::unique_ptr<PaintShader> PaintRecordPattern::CreateShader( const SkMatrix& local_matrix) { - return MakePaintShaderRecord(tile_record_, tile_record_bounds_, - SkShader::kRepeat_TileMode, - SkShader::kRepeat_TileMode, &local_matrix); + return PaintShader::MakePaintRecord( + tile_record_, tile_record_bounds_, SkShader::kRepeat_TileMode, + SkShader::kRepeat_TileMode, &local_matrix); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.h b/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.h index fe3d95d..3d826a63 100644 --- a/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.h +++ b/third_party/WebKit/Source/platform/graphics/PaintRecordPattern.h
@@ -21,7 +21,7 @@ ~PaintRecordPattern() override; protected: - sk_sp<PaintShader> CreateShader(const SkMatrix&) override; + std::unique_ptr<PaintShader> CreateShader(const SkMatrix&) override; private: PaintRecordPattern(sk_sp<PaintRecord>,
diff --git a/third_party/WebKit/Source/platform/graphics/Pattern.cpp b/third_party/WebKit/Source/platform/graphics/Pattern.cpp index dc1c2f6..53cf3a8 100644 --- a/third_party/WebKit/Source/platform/graphics/Pattern.cpp +++ b/third_party/WebKit/Source/platform/graphics/Pattern.cpp
@@ -59,11 +59,11 @@ if (!cached_shader_ || IsLocalMatrixChanged(local_matrix)) cached_shader_ = CreateShader(local_matrix); - flags.setShader(cached_shader_); + flags.setShader(WTF::MakeUnique<PaintShader>(*cached_shader_)); } bool Pattern::IsLocalMatrixChanged(const SkMatrix& local_matrix) const { - return local_matrix != cached_shader_->getLocalMatrix(); + return local_matrix != cached_shader_->sk_shader()->getLocalMatrix(); } } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/Pattern.h b/third_party/WebKit/Source/platform/graphics/Pattern.h index 1db8d22..f939b5e 100644 --- a/third_party/WebKit/Source/platform/graphics/Pattern.h +++ b/third_party/WebKit/Source/platform/graphics/Pattern.h
@@ -72,13 +72,13 @@ virtual bool IsTextureBacked() const { return false; } protected: - virtual sk_sp<PaintShader> CreateShader(const SkMatrix&) = 0; + virtual std::unique_ptr<PaintShader> CreateShader(const SkMatrix&) = 0; virtual bool IsLocalMatrixChanged(const SkMatrix&) const; RepeatMode repeat_mode_; Pattern(RepeatMode); - mutable sk_sp<PaintShader> cached_shader_; + mutable std::unique_ptr<PaintShader> cached_shader_; }; } // namespace blink
diff --git a/third_party/WebKit/Source/platform/graphics/PlaceholderImage.cpp b/third_party/WebKit/Source/platform/graphics/PlaceholderImage.cpp index 9023571e..e215eb305 100644 --- a/third_party/WebKit/Source/platform/graphics/PlaceholderImage.cpp +++ b/third_party/WebKit/Source/platform/graphics/PlaceholderImage.cpp
@@ -5,22 +5,24 @@ #include "platform/graphics/PlaceholderImage.h" #include "platform/geometry/FloatRect.h" -#include "platform/graphics/Color.h" +#include "platform/geometry/IntPoint.h" +#include "platform/geometry/IntRect.h" +#include "platform/graphics/BitmapImage.h" +#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/ImageObserver.h" +#include "platform/graphics/paint/PaintCanvas.h" +#include "platform/graphics/paint/PaintFlags.h" #include "platform/graphics/paint/PaintRecord.h" #include "platform/graphics/paint/PaintRecorder.h" +#include "platform/wtf/StdLibExtras.h" #include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkSize.h" namespace blink { -namespace { - -// Gray with 40% opacity. -const RGBA32 kFillColor = 0x66808080; - -} // namespace +PlaceholderImage::PlaceholderImage(ImageObserver* observer, const IntSize& size) + : Image(observer), size_(size) {} PlaceholderImage::~PlaceholderImage() {} @@ -30,6 +32,7 @@ const FloatRect dest_rect(0.0f, 0.0f, static_cast<float>(size_.Width()), static_cast<float>(size_.Height())); + PaintRecorder paint_recorder; Draw(paint_recorder.beginRecording(dest_rect), PaintFlags(), dest_rect, dest_rect, kDoNotRespectImageOrientation, kClampImageToSourceRect); @@ -46,18 +49,68 @@ const PaintFlags& base_flags, const FloatRect& dest_rect, const FloatRect& src_rect, - RespectImageOrientationEnum, - ImageClampingMode) { + RespectImageOrientationEnum respect_orientation, + ImageClampingMode image_clamping_mode) { if (!src_rect.Intersects(FloatRect(0.0f, 0.0f, static_cast<float>(size_.Width()), static_cast<float>(size_.Height())))) { return; } + // Placeholder image visual specifications: + // https://docs.google.com/document/d/1BHeA1azbgCdZgCnr16VN2g7A9MHPQ_dwKn5szh8evMQ/edit + PaintFlags flags(base_flags); flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(kFillColor); + flags.setColor(SkColorSetARGB(0x80, 0xD9, 0xD9, 0xD9)); canvas->drawRect(dest_rect, flags); + + constexpr int kIconWidth = 24; + constexpr int kIconHeight = 24; + constexpr int kIconPaddingX = 8; + constexpr int kIconPaddingY = 5; + + if (dest_rect.Width() < kIconWidth + 2 * kIconPaddingX || + dest_rect.Height() < kIconHeight + 2 * kIconPaddingY) { + return; + } + + DEFINE_STATIC_REF(Image, icon_image, + (Image::LoadPlatformResource("placeholderIcon"))); + DCHECK(!icon_image->IsNull()); + + FloatRect icon_dest_rect( + dest_rect.X() + (dest_rect.Width() - kIconWidth) / 2.0f, + dest_rect.Y() + (dest_rect.Height() - kIconHeight) / 2.0f, kIconWidth, + kIconHeight); + + // Note that the |icon_image| is not scaled according to dest_rect / src_rect, + // and is always drawn at the same size. This is so that placeholder icons are + // visible (e.g. when replacing a large image that's scaled down to a small + // area) and so that all placeholder images on the same page look consistent. + canvas->drawImageRect(icon_image->PaintImageForCurrentFrame(), + IntRect(IntPoint::Zero(), icon_image->Size()), + icon_dest_rect, &base_flags, + PaintCanvas::kFast_SrcRectConstraint); +} + +void PlaceholderImage::DrawPattern(GraphicsContext& context, + const FloatRect& src_rect, + const FloatSize& scale, + const FloatPoint& phase, + SkBlendMode mode, + const FloatRect& dest_rect, + const FloatSize& repeat_spacing) { + DCHECK(context.Canvas()); + + PaintFlags flags = context.FillFlags(); + flags.setBlendMode(mode); + + // Ignore the pattern specifications and just draw a single placeholder image + // over the whole |dest_rect|. This is done in order to prevent repeated icons + // from cluttering tiled background images. + Draw(context.Canvas(), flags, dest_rect, src_rect, + kDoNotRespectImageOrientation, kClampImageToSourceRect); } void PlaceholderImage::DestroyDecodedData() {
diff --git a/third_party/WebKit/Source/platform/graphics/PlaceholderImage.h b/third_party/WebKit/Source/platform/graphics/PlaceholderImage.h index f87d166..cb465863 100644 --- a/third_party/WebKit/Source/platform/graphics/PlaceholderImage.h +++ b/third_party/WebKit/Source/platform/graphics/PlaceholderImage.h
@@ -15,7 +15,10 @@ namespace blink { +class FloatPoint; class FloatRect; +class FloatSize; +class GraphicsContext; class ImageObserver; // A generated placeholder image that shows a translucent gray rectangle. @@ -42,8 +45,7 @@ void DestroyDecodedData() override; private: - PlaceholderImage(ImageObserver* observer, const IntSize& size) - : Image(observer), size_(size) {} + PlaceholderImage(ImageObserver*, const IntSize&); bool CurrentFrameHasSingleSecurityOrigin() const override { return true; } @@ -53,7 +55,16 @@ return false; } - IntSize size_; + void DrawPattern(GraphicsContext&, + const FloatRect& src_rect, + const FloatSize& scale, + const FloatPoint& phase, + SkBlendMode, + const FloatRect& dest_rect, + const FloatSize& repeat_spacing = FloatSize()) override; + + const IntSize size_; + // Lazily initialized. sk_sp<SkImage> image_for_current_frame_; };
diff --git a/third_party/WebKit/Source/platform/graphics/paint/PaintShader.h b/third_party/WebKit/Source/platform/graphics/paint/PaintShader.h index 8bff588..9d1b8a8 100644 --- a/third_party/WebKit/Source/platform/graphics/paint/PaintShader.h +++ b/third_party/WebKit/Source/platform/graphics/paint/PaintShader.h
@@ -9,9 +9,6 @@ namespace blink { using cc::PaintShader; -using cc::MakePaintShaderImage; -using cc::MakePaintShaderRecord; -using cc::WrapSkShader; } #endif // PaintShader_h
diff --git a/third_party/WebKit/public/blink_image_resources.grd b/third_party/WebKit/public/blink_image_resources.grd index 1361772..bc40341 100644 --- a/third_party/WebKit/public/blink_image_resources.grd +++ b/third_party/WebKit/public/blink_image_resources.grd
@@ -36,6 +36,7 @@ <structure type="chrome_scaled_image" name="IDR_SEARCH_CANCEL_PRESSED" file="blink/search_cancel_pressed.png" /> <structure type="chrome_scaled_image" name="IDR_PASSWORD_GENERATION_ICON" file="blink/password_generation.png" /> <structure type="chrome_scaled_image" name="IDR_PASSWORD_GENERATION_ICON_HOVER" file="blink/password_generation_hover.png" /> + <structure type="chrome_scaled_image" name="IDR_PLACEHOLDER_ICON" file="blink/placeholder_icon.png" /> </structures> </release> </grit>
diff --git a/third_party/WebKit/public/default_100_percent/blink/placeholder_icon.png b/third_party/WebKit/public/default_100_percent/blink/placeholder_icon.png new file mode 100644 index 0000000..faa63ff --- /dev/null +++ b/third_party/WebKit/public/default_100_percent/blink/placeholder_icon.png Binary files differ
diff --git a/third_party/closure_compiler/compile2.py b/third_party/closure_compiler/compile2.py index a292c8d..224856d7 100755 --- a/third_party/closure_compiler/compile2.py +++ b/third_party/closure_compiler/compile2.py
@@ -14,7 +14,6 @@ import tempfile import processor -import error_filter _CURRENT_DIR = os.path.join(os.path.dirname(__file__)) @@ -45,7 +44,6 @@ self._target = None self._temp_files = [] self._verbose = verbose - self._error_filter = error_filter.PromiseErrorFilter() def _nuke_temp_files(self): """Deletes any temp files this class knows about.""" @@ -122,29 +120,6 @@ real_file = self._processor.get_file_from_line(match.group(1)) return "%s:%d" % (os.path.abspath(real_file.file), real_file.line_number) - def _filter_errors(self, errors): - """Removes some extraneous errors. For example, we ignore: - - Variable x first declared in /tmp/expanded/file - - Because it's just a duplicated error (it'll only ever show up 2+ times). - We also ignore Promise-based errors: - - found : function (VolumeInfo): (Promise<(DirectoryEntry|null)>|null) - required: (function (Promise<VolumeInfo>): ?|null|undefined) - - as templates don't work with Promises in all cases yet. See - https://github.com/google/closure-compiler/issues/715 for details. - - Args: - errors: A list of string errors extracted from Closure Compiler output. - - Return: - A slimmer, sleeker list of relevant errors (strings). - """ - first_declared_in = lambda e: " first declared in " not in e - return self._error_filter.filter(filter(first_declared_in, errors)) - def _clean_up_error(self, error): """Reverse the effects that funky <include> preprocessing steps have on errors messages. @@ -295,8 +270,7 @@ f.write('') if process_includes: - filtered_errors = self._filter_errors(errors) - errors = map(self._clean_up_error, filtered_errors) + errors = map(self._clean_up_error, errors) output = self._format_errors(errors) if errors:
diff --git a/third_party/closure_compiler/error_filter.py b/third_party/closure_compiler/error_filter.py deleted file mode 100644 index a5a549a..0000000 --- a/third_party/closure_compiler/error_filter.py +++ /dev/null
@@ -1,152 +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. - -"""Implement filtering out closure compiler errors due to incorrect type- -checking on promise-based return types. - -The compiler's type-checker doesn't correctly unwrap Promised return values -prior to type-checking them. There are a couple of scenarios where this occurs, -examples can be found below in the code that deals with each specific scenario. - -This filtering code applies a set of matchers to the errors that the compiler -emits. Each matcher fits a known pattern for compiler errors arising from the -issue described above. If any of the matchers matches an error, that error is -filtered out of the error list. - -Note that this is just a coarse filter. It doesn't, for example, check that the -unwrapped promise type actually matches the type accepted by the next callback -in the Promise chain. Doing so would be the correct way to fix this problem, -but that fix belongs in the compiler. - -""" - -import re - - -class PromiseErrorFilter: - """Runs checks to filter out promise chain errors.""" - def __init__(self): - self._allowed_error_patterns = [ - ChainedPromisePattern(), - ReturnedPromisePattern() - ] - - def filter(self, error_list): - """Filters out errors matching any of the allowed patterns. - - Args: - error_list: A list of errors from the closure compiler. - - Return: - A list of errors, with spurious Promise type errors removed. - """ - return [error for error in error_list if not self._should_ignore(error)]; - - def _should_ignore(self, error): - """Check the given error against all the filters. An error should be - ignored if it is a match for any of the allowed message patterns. - - Args: - error: A single entry from the closure compiler error list. - - Return: - True if the error should be ignored, False otherwise. - """ - return any([pattern.match(error) - for pattern in self._allowed_error_patterns]); - - -class ErrorPattern: - """A matcher for compiler error messages. This matches compiler type errors, - which look like: - # ERROR - <some error message> - # found : <some type expression> - # required: <some type expression> - The message and type expressions are customizable. - """ - def __init__(self, msg, found_pattern, required_pattern): - # A string literal that is compared to the first line of the error. - self._error_msg = msg - # A regex for matching the found type. - self._found_line_regex = re.compile("found\s*:\s*" + found_pattern) - # A regex for matching the required type. - self._required_line_regex = re.compile("required:\s*" + required_pattern) - - def match(self, error): - error_lines = error.split('\n') - - # Match the error message to see if this pattern applies to the given error. - # If the error message matches, then compare the found and required lines. - if self._error_msg not in error_lines[0]: - return False - else: - return (self._found_line_regex.match(error_lines[1]) and - self._required_line_regex.match(error_lines[2])) - - -class ChainedPromisePattern(ErrorPattern): - """Matcher for spurious errors arising from chained promises. Example code: - - Promise.resolve() - .then( - /** @return {!Promise<string>} */ - function() { return Promise.resolve('foo'); }) - .then( - /** @param {string} s */ - function(s) { console.log(s); }); - - The compiler will emit an error that looks like - - ERROR - actual parameter 1 of Promise.prototype.then does not match formal - parameter - found : function (string): undefined - required: (function (Promise<string>): ?|null|undefined) - """ - def __init__(self): - # Matches the initial error message. - msg = ("ERROR - actual parameter 1 of Promise.prototype.then " - "does not match formal parameter") - - # Examples: - # - function (string): Promise<string> - # - function ((SomeType|null)): SomeOtherType - found_pattern = "function\s*\(.*\):\s*.*" - - # Examples: - # - (function(Promise<string>): ?|null|undefined) - required_pattern = "\(function\s*\(Promise<.*>\):\s*.*\)" - - ErrorPattern.__init__(self, msg, found_pattern, required_pattern) - - -class ReturnedPromisePattern(ErrorPattern): - """Matcher for spurious errors arising from Promised return values. Example - code: - - /** @return {!Promise<string>} */ - var getStringAsync = function() { - /** @return {!Promise<string>} */ - var generateString = function() {return Promise.resolve('foo');}; - return Promise.resolve().then(generateString); - }; - - The compiler will emit an error that looks like - - ERROR - inconsistent return type - found : Promise<Promise<string>> - required: Promise<string> - """ - def __init__(self): - # Matches the initial error message. - msg = "ERROR - inconsistent return type" - - # Example: - # - Promise<Promise<string>> - found_pattern = "Promise<Promise<[^<>]*>" - - # Example: - # - Promise<string> - required_pattern = "Promise<[^<>]*>" - - ErrorPattern.__init__(self, msg, found_pattern, required_pattern)
diff --git a/third_party/flatbuffers/BUILD.gn b/third_party/flatbuffers/BUILD.gn index 6407c35..a1554f2 100644 --- a/third_party/flatbuffers/BUILD.gn +++ b/third_party/flatbuffers/BUILD.gn
@@ -78,9 +78,8 @@ flatbuffer("flatbuffers_samplebuffer") { testonly = true sources = [ - # Disabled as workaround for crbug.com/611351 - # "src/tests/include_test/include_test1.fbs", - # "src/tests/include_test/sub/include_test2.fbs", + "src/tests/include_test/include_test1.fbs", + "src/tests/include_test/sub/include_test2.fbs", "src/tests/monster_test.fbs", "src/tests/namespace_test/namespace_test1.fbs", "src/tests/namespace_test/namespace_test2.fbs",
diff --git a/tools/binary_size/libsupersize/describe.py b/tools/binary_size/libsupersize/describe.py index 19dd064..ad0412950 100644 --- a/tools/binary_size/libsupersize/describe.py +++ b/tools/binary_size/libsupersize/describe.py
@@ -55,17 +55,31 @@ self.recursive = recursive def _DescribeSectionSizes(self, section_sizes): - relevant_names = models.SECTION_TO_SECTION_NAME.values() - section_names = sorted(k for k in section_sizes.iterkeys() - if k in relevant_names or k.startswith('.data')) + def include_in_totals(name): + return name != '.bss' and '(' not in name + total_bytes = sum(v for k, v in section_sizes.iteritems() - if k in section_names and k != '.bss') + if include_in_totals(k)) + max_bytes = max(abs(v) for k, v in section_sizes.iteritems() + if include_in_totals(k)) + + def is_relevant_section(name, size): + # Show all sections containing symbols, plus relocations. + # As a catch-all, also include any section that comprises > 4% of the + # largest section. Use largest section rather than total so that it still + # works out when showing a diff containing +100, -100 (total=0). + return (name in models.SECTION_TO_SECTION_NAME.values() or + name in ('.rela.dyn', '.rel.dyn') or + include_in_totals(name) and abs(_Divide(size, max_bytes)) > .04) + + section_names = sorted(k for k, v in section_sizes.iteritems() + if is_relevant_section(k, v)) yield '' yield 'Section Sizes (Total={} ({} bytes)):'.format( _PrettySize(total_bytes), total_bytes) for name in section_names: size = section_sizes[name] - if name == '.bss': + if not include_in_totals(name): yield ' {}: {} ({} bytes) (not included in totals)'.format( name, _PrettySize(size), size) else: @@ -79,8 +93,12 @@ section_names = sorted(k for k in section_sizes.iterkeys() if k not in section_names) for name in section_names: - yield ' {}: {} ({} bytes)'.format( - name, _PrettySize(section_sizes[name]), section_sizes[name]) + not_included_part = '' + if not include_in_totals(name): + not_included_part = ' (not included in totals)' + yield ' {}: {} ({} bytes){}'.format( + name, _PrettySize(section_sizes[name]), section_sizes[name], + not_included_part) def _DescribeSymbol(self, sym, single_line=False): if sym.IsGroup():
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden index 4208cc1..cb12723 100644 --- a/tools/binary_size/libsupersize/testdata/Console.golden +++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -56,13 +56,15 @@ map_file_name=../test.map tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/ -Section Sizes (Total=41.8mb (43785380 bytes)): +Section Sizes (Total=95.6mb (100233874 bytes)): + .ARM.exidx: 1.47mb (1536456 bytes) (1.5%) .bss: 1.24mb (1300456 bytes) (not included in totals) - .data: 99.4kb (101768 bytes) (0.2%) - .data.rel.ro: 1.02mb (1065224 bytes) (2.4%) - .data.rel.ro.local: 771kb (790024 bytes) (1.8%) - .rodata: 5.65mb (5927652 bytes) (13.5%) - .text: 34.2mb (35900712 bytes) (82.0%) + .data: 99.4kb (101768 bytes) (0.1%) + .rel.dyn: 2.53mb (2655384 bytes) (2.6%) + .rodata: 5.65mb (5927652 bytes) (5.9%) + .strtab: 33.2mb (34841854 bytes) (34.8%) + .symtab: 16.4mb (17166112 bytes) (17.1%) + .text: 34.2mb (35900712 bytes) (35.8%) Showing 45 symbols (42 unique) with total pss: 43785380 bytes .text=34.2mb .rodata=5.65mb .data*=1.87mb .bss=512kb total=41.8mb
diff --git a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden index b6b6070..8d756e1 100644 --- a/tools/binary_size/libsupersize/testdata/Diff_Basic.golden +++ b/tools/binary_size/libsupersize/testdata/Diff_Basic.golden
@@ -9,8 +9,7 @@ Section Sizes (Total=0 bytes (0 bytes)): .bss: 0 bytes (0 bytes) (not included in totals) .data: 0 bytes (0 bytes) (0.0%) - .data.rel.ro: 0 bytes (0 bytes) (0.0%) - .data.rel.ro.local: 0 bytes (0 bytes) (0.0%) + .rel.dyn: 0 bytes (0 bytes) (0.0%) .rodata: 0 bytes (0 bytes) (0.0%) .text: 0 bytes (0 bytes) (0.0%) @@ -18,6 +17,8 @@ .ARM.attributes: 0 bytes (0 bytes) .ARM.exidx: 0 bytes (0 bytes) .ARM.extab: 0 bytes (0 bytes) + .data.rel.ro: 0 bytes (0 bytes) + .data.rel.ro.local: 0 bytes (0 bytes) .dynamic: 0 bytes (0 bytes) .dynstr: 0 bytes (0 bytes) .dynsym: 0 bytes (0 bytes) @@ -32,7 +33,6 @@ .note.gnu.build-id: 0 bytes (0 bytes) .note.gnu.gold-version: 0 bytes (0 bytes) .plt: 0 bytes (0 bytes) - .rel.dyn: 0 bytes (0 bytes) .rel.plt: 0 bytes (0 bytes) .shstrtab: 0 bytes (0 bytes) .strtab: 0 bytes (0 bytes)
diff --git a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden index a780240..f1c0bd3 100644 --- a/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden +++ b/tools/binary_size/libsupersize/testdata/Diff_NullDiff.golden
@@ -13,8 +13,7 @@ Section Sizes (Total=0 bytes (0 bytes)): .bss: 0 bytes (0 bytes) (not included in totals) .data: 0 bytes (0 bytes) (0.0%) - .data.rel.ro: 0 bytes (0 bytes) (0.0%) - .data.rel.ro.local: 0 bytes (0 bytes) (0.0%) + .rel.dyn: 0 bytes (0 bytes) (0.0%) .rodata: 0 bytes (0 bytes) (0.0%) .text: 0 bytes (0 bytes) (0.0%)
diff --git a/tools/binary_size/libsupersize/testdata/FullDescription.golden b/tools/binary_size/libsupersize/testdata/FullDescription.golden index de96cdd..5b94619 100644 --- a/tools/binary_size/libsupersize/testdata/FullDescription.golden +++ b/tools/binary_size/libsupersize/testdata/FullDescription.golden
@@ -8,18 +8,21 @@ map_file_name=../test.map tool_prefix=tools/binary_size/libsupersize/testdata/mock_toolchain/ -Section Sizes (Total=41.8mb (43785380 bytes)): +Section Sizes (Total=95.6mb (100233874 bytes)): + .ARM.exidx: 1.47mb (1536456 bytes) (1.5%) .bss: 1.24mb (1300456 bytes) (not included in totals) - .data: 99.4kb (101768 bytes) (0.2%) - .data.rel.ro: 1.02mb (1065224 bytes) (2.4%) - .data.rel.ro.local: 771kb (790024 bytes) (1.8%) - .rodata: 5.65mb (5927652 bytes) (13.5%) - .text: 34.2mb (35900712 bytes) (82.0%) + .data: 99.4kb (101768 bytes) (0.1%) + .rel.dyn: 2.53mb (2655384 bytes) (2.6%) + .rodata: 5.65mb (5927652 bytes) (5.9%) + .strtab: 33.2mb (34841854 bytes) (34.8%) + .symtab: 16.4mb (17166112 bytes) (17.1%) + .text: 34.2mb (35900712 bytes) (35.8%) Other section sizes: .ARM.attributes: 60 bytes (60 bytes) - .ARM.exidx: 1.47mb (1536456 bytes) .ARM.extab: 179kb (183632 bytes) + .data.rel.ro: 1.02mb (1065224 bytes) + .data.rel.ro.local: 771kb (790024 bytes) .dynamic: 304 bytes (304 bytes) .dynstr: 3.93kb (4025 bytes) .dynsym: 6.34kb (6496 bytes) @@ -34,11 +37,8 @@ .note.gnu.build-id: 36 bytes (36 bytes) .note.gnu.gold-version: 28 bytes (28 bytes) .plt: 4.14kb (4244 bytes) - .rel.dyn: 2.53mb (2655384 bytes) .rel.plt: 2.75kb (2816 bytes) .shstrtab: 436 bytes (436 bytes) - .strtab: 33.2mb (34841854 bytes) - .symtab: 16.4mb (17166112 bytes) Section r: has 100.0% of 5927652 bytes accounted for from 10 symbols. 0 bytes are unaccounted for. * Padding accounts for 11 bytes (0.0%)
diff --git a/tools/chrome_proxy/webdriver/common.py b/tools/chrome_proxy/webdriver/common.py index 04819c5..945ccbf 100644 --- a/tools/chrome_proxy/webdriver/common.py +++ b/tools/chrome_proxy/webdriver/common.py
@@ -228,8 +228,9 @@ 'networkConnectionEnabled': True, 'mobileEmulationEnabled': True, }) - chrome_options.add_experimental_option('mobileEmulation', - {'deviceName': 'Google Nexus 5'}) + if not self._flags.android: + chrome_options.add_experimental_option('mobileEmulation', + {'deviceName': 'Google Nexus 5'}) for arg in self._chrome_args: chrome_options.add_argument(arg) self._logger.info('Starting Chrome with these flags: %s',
diff --git a/tools/chrome_proxy/webdriver/video.py b/tools/chrome_proxy/webdriver/video.py index 7b203bef1..01e2866c 100644 --- a/tools/chrome_proxy/webdriver/video.py +++ b/tools/chrome_proxy/webdriver/video.py
@@ -8,7 +8,6 @@ from common import TestDriver from common import IntegrationTest from common import ParseFlags -from decorators import NotAndroid from decorators import Slow from selenium.webdriver.common.by import By @@ -86,18 +85,10 @@ # Check that the compressed video can be seeked. Use a slow network to ensure # the entire video isn't downloaded before we have a chance to seek. - # - # This test cannot run on android because of control_network_connection=True. - # That option is used to reduce flakes that might happen on fast networks, - # where the video is completely downloaded before a seeking request can be - # sent. The test can be manually simulated by the following steps: set network - # emulation in DevTools on Android (via device inspector), load a video, pause - # the video, then seek and verify the seek continues to play the video. @Slow - @NotAndroid def testVideoSeeking(self): with TestDriver(control_network_connection=True) as t: - t.SetNetworkConnection("3G") + t.SetNetworkConnection("2G") t.AddChromeArg('--enable-spdy-proxy-auth') t.LoadURL( 'http://check.googlezip.net/cacheable/video/'+ @@ -124,7 +115,10 @@ }; v.play(); ''') - t.WaitForJavascriptExpression('window.testDone', 10) + if ParseFlags().android: + # v.play() won't work on Android, so give it a click instead. + t.FindElement(By.TAG_NAME, "video").click() + t.WaitForJavascriptExpression('window.testDone', 15) # Check request was proxied and we got a compressed video back. # We expect to make multiple requests for the video: ensure they # all have the same ETag.
diff --git a/tools/gn/function_get_label_info.cc b/tools/gn/function_get_label_info.cc index 267c7b0..a67a3719 100644 --- a/tools/gn/function_get_label_info.cc +++ b/tools/gn/function_get_label_info.cc
@@ -71,7 +71,7 @@ get_label_info(":foo", "name") # Returns string "foo". - get_label_info("//foo/bar:baz", "gen_dir") + get_label_info("//foo/bar:baz", "target_gen_dir") # Returns string "//out/Debug/gen/foo/bar". )*";
diff --git a/tools/licenses.py b/tools/licenses.py index bf0b53bc..ec63ff4 100755 --- a/tools/licenses.py +++ b/tools/licenses.py
@@ -555,6 +555,19 @@ template = template.replace('{{%s}}' % key, val) return template + def MetadataToTemplateEntry(metadata, entry_template, entry_id): + env = { + 'name': metadata['Name'], + 'url': metadata['URL'], + 'license': open(metadata['License File'], 'rb').read(), + 'id': str(entry_id), + } + return { + 'name': metadata['Name'], + 'content': EvaluateTemplate(entry_template, env), + 'license_file': metadata['License File'], + } + if gn_target: third_party_dirs = FindThirdPartyDeps(gn_out_dir, gn_target) @@ -575,7 +588,17 @@ 'about_credits_entry.tmpl') entry_template = open(entry_template_file).read() + entry_id = 0 entries = [] + # Start from Chromium's LICENSE file + chromium_license_metadata = { + 'Name': 'The Chromium Project', + 'URL': 'http://www.chromium.org', + 'License File': os.path.join(_REPOSITORY_ROOT, 'LICENSE') } + entries.append(MetadataToTemplateEntry(chromium_license_metadata, + entry_template, entry_id)) + entry_id += 1 + for path in third_party_dirs: try: metadata = ParseDir(path, _REPOSITORY_ROOT) @@ -592,22 +615,11 @@ # updated to provide --gn-target to this script. if path in KNOWN_NON_IOS_LIBRARIES: continue - env = { - 'name': metadata['Name'], - 'url': metadata['URL'], - 'license': open(metadata['License File'], 'rb').read(), - } - entry = { - 'name': metadata['Name'], - 'content': EvaluateTemplate(entry_template, env), - 'license_file': metadata['License File'], - } - entries.append(entry) - # Sort by size in order to improve gzip compression ratio (puts similar - # licenses near each other). The licenses are re-sorted by the JavaScript - # when loaded. - entries.sort(key=lambda entry: (len(entry['content']), - entry['name'], entry['content'])) + entries.append(MetadataToTemplateEntry(metadata, entry_template, + entry_id)) + entry_id += 1 + + entries.sort(key=lambda entry: (entry['name'], entry['content'])) entries_contents = '\n'.join([entry['content'] for entry in entries]) file_template = open(file_template_file).read()
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 3961fe27..3d4e3da 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -23485,6 +23485,13 @@ </summary> </histogram> +<histogram name="GPU.ProgramCache.MemoryReleasedOnPressure" units="KB"> + <owner>ssid@chromium.org</owner> + <summary> + Amount of memory released from the program cache on memory pressure. + </summary> +</histogram> + <histogram name="GPU.ProgramCache.MemorySizeAfterKb" units="KB"> <owner>vmiura@chromium.org</owner> <summary> @@ -77406,6 +77413,24 @@ </summary> </histogram> +<histogram name="Toolbar.Menu.NewIncognitoTabPresentationDuration" units="ms"> + <owner>peterlaurens@chromium.org</owner> + <summary> + The number of millseconds between the user requesting a new incognito tab, + e.g. by tapping the New Incognito Tab entry in the main tools menu, and it + completing its animation on screen. + </summary> +</histogram> + +<histogram name="Toolbar.Menu.NewTabPresentationDuration" units="ms"> + <owner>peterlaurens@chromium.org</owner> + <summary> + The number of millseconds between the user requesting a new tab, e.g. by + tapping the New Tab entry in the main tools menu, and it completing its + animation on screen. + </summary> +</histogram> + <histogram name="Toolbar.ShowToolsMenuResponsiveness" units="ms"> <owner>peterlaurens@chromium.org</owner> <summary> @@ -77416,6 +77441,25 @@ </summary> </histogram> +<histogram name="Toolbar.TabSwitcher.NewIncognitoTabPresentationDuration" + units="ms"> + <owner>peterlaurens@chromium.org</owner> + <summary> + The number of millseconds between the user requesting a new incognito tab, + from within the tab switcher, e.g. by tapping the New Tab button from the + tab switcher UI, and it completing its animation on screen. + </summary> +</histogram> + +<histogram name="Toolbar.TabSwitcher.NewTabPresentationDuration" units="ms"> + <owner>peterlaurens@chromium.org</owner> + <summary> + The number of millseconds between the user requesting a new tab, from within + the tab switcher UI, e.g. by tapping the New Tab button from the tab + switcher UI, and it completing its animation on screen. + </summary> +</histogram> + <histogram name="TopSites.NumberOfApplyBlacklist"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <summary>The number of times TopSitesImpl::ApplyBlacklist is called.</summary> @@ -81329,6 +81373,15 @@ </summary> </histogram> +<histogram name="WebApk.Install.GooglePlayErrorCode" units="code"> + <owner>hanxi@chromium.org</owner> + <owner>pkotwicz@chromium.org</owner> + <owner>yfriedman@chromium.org</owner> + <summary> + Records the error code when installing a WebAPK from Google Play fails. + </summary> +</histogram> + <histogram name="WebApk.Install.GooglePlayInstallResult" enum="WebApkGooglePlayInstallResult"> <owner>hanxi@chromium.org</owner>
diff --git a/ui/app_list/app_list_features.cc b/ui/app_list/app_list_features.cc index b3c89fa..770e0e03 100644 --- a/ui/app_list/app_list_features.cc +++ b/ui/app_list/app_list_features.cc
@@ -35,13 +35,13 @@ int APP_LIST_EXPORT AnswerCardMaxWidth() { static const int max_width = base::GetFieldTrialParamByFeatureAsInt( - kEnableAnswerCard, "CardMaxWidth", 640); + kEnableAnswerCard, "CardMaxWidth", 608); return max_width; } int APP_LIST_EXPORT AnswerCardMaxHeight() { static const int max_height = base::GetFieldTrialParamByFeatureAsInt( - kEnableAnswerCard, "CardMaxHeight", 288); + kEnableAnswerCard, "CardMaxHeight", 266); return max_height; }
diff --git a/ui/app_list/views/search_result_answer_card_view.cc b/ui/app_list/views/search_result_answer_card_view.cc index ee32bc1..0132a12 100644 --- a/ui/app_list/views/search_result_answer_card_view.cc +++ b/ui/app_list/views/search_result_answer_card_view.cc
@@ -15,6 +15,11 @@ namespace app_list { +namespace { +constexpr int kVerticalPadding = 11; +constexpr int kHorizontalPadding = 16; +} + // Container of the search answer view. class SearchResultAnswerCardView::SearchAnswerContainerView : public views::CustomButton, @@ -25,11 +30,11 @@ : CustomButton(this), view_delegate_(view_delegate) { // Center the card horizontally in the container. views::BoxLayout* answer_container_layout = - new views::BoxLayout(views::BoxLayout::kHorizontal); + new views::BoxLayout(views::BoxLayout::kHorizontal, + gfx::Insets(kVerticalPadding, kHorizontalPadding)); answer_container_layout->set_main_axis_alignment( - views::BoxLayout::MAIN_AXIS_ALIGNMENT_CENTER); + views::BoxLayout::MAIN_AXIS_ALIGNMENT_START); SetLayoutManager(answer_container_layout); - SetVisible(false); } void SetSelected(bool selected) { @@ -58,8 +63,6 @@ search_result_->AddObserver(this); SetAccessibleName(search_result_->title()); } - - SetVisible(new_result_view != nullptr); } // views::CustomButton overrides: @@ -138,6 +141,7 @@ search_answer_container_view_->SetSearchResult( have_result ? display_results[0] : nullptr); + parent()->SetVisible(have_result); set_container_score(have_result ? display_results.front()->relevance() : 0); return have_result ? 1 : 0;
diff --git a/ui/app_list/views/search_result_page_view.cc b/ui/app_list/views/search_result_page_view.cc index cda5251..67e6b72 100644 --- a/ui/app_list/views/search_result_page_view.cc +++ b/ui/app_list/views/search_result_page_view.cc
@@ -27,8 +27,9 @@ namespace { -const int kGroupSpacing = 6; -const int kTopPadding = 8; +constexpr int kGroupSpacing = 6; +constexpr int kTopPadding = 8; +constexpr int kFullscreenHeight = 440; // The z-height of the search box and cards in this view. const int kSearchResultZHeight = 1; @@ -46,12 +47,17 @@ AddChildView(content_view); } + // views::View overrides: + const char* GetClassName() const override { return "SearchCardView"; } + ~SearchCardView() override {} }; } // namespace -SearchResultPageView::SearchResultPageView() : selected_index_(0) { +SearchResultPageView::SearchResultPageView() + : selected_index_(0), + is_fullscreen_app_list_enabled_(features::IsFullscreenAppListEnabled()) { gfx::ShadowValue shadow = GetShadowForZHeight(kSearchResultZHeight); std::unique_ptr<views::Border> border(new views::ShadowBorder(shadow)); @@ -213,10 +219,11 @@ gfx::Rect SearchResultPageView::GetPageBoundsForState( AppListModel::State state) const { - gfx::Rect onscreen_bounds = - features::IsAnswerCardEnabled() && !features::IsAnswerCardDarkRunEnabled() - ? GetFullContentsBounds() - : GetDefaultContentsBounds(); + gfx::Rect onscreen_bounds = GetDefaultContentsBounds(); + + if (is_fullscreen_app_list_enabled_) + onscreen_bounds.set_height(kFullscreenHeight); + switch (state) { case AppListModel::STATE_SEARCH_RESULTS: return onscreen_bounds;
diff --git a/ui/app_list/views/search_result_page_view.h b/ui/app_list/views/search_result_page_view.h index 9dcd5489..f929ed63 100644 --- a/ui/app_list/views/search_result_page_view.h +++ b/ui/app_list/views/search_result_page_view.h
@@ -66,6 +66,9 @@ // -1 indicates no selection. int selected_index_; + // Whether launcher is shown in fullscreen mode. + bool const is_fullscreen_app_list_enabled_; + DISALLOW_COPY_AND_ASSIGN(SearchResultPageView); };
diff --git a/ui/compositor/debug_utils.cc b/ui/compositor/debug_utils.cc index 3d4837e3..75f3457 100644 --- a/ui/compositor/debug_utils.cc +++ b/ui/compositor/debug_utils.cc
@@ -92,7 +92,7 @@ *out << '\n' << property_indent_str; *out << "rotation: "; - *out << std::acos(decomp.quaternion[3]) * 360.0 / M_PI; + *out << std::acos(decomp.quaternion.w()) * 360.0 / M_PI; *out << '\n' << property_indent_str; *out << "scale: " << decomp.scale[0];
diff --git a/ui/compositor/transform_animation_curve_adapter.cc b/ui/compositor/transform_animation_curve_adapter.cc index a41df05..e698be6 100644 --- a/ui/compositor/transform_animation_curve_adapter.cc +++ b/ui/compositor/transform_animation_curve_adapter.cc
@@ -46,12 +46,9 @@ return initial_value_; double progress = cc::TimeUtil::Divide(t, duration_); - gfx::DecomposedTransform to_return; - gfx::BlendDecomposedTransforms(&to_return, - decomposed_target_value_, - decomposed_initial_value_, - gfx::Tween::CalculateValue(tween_type_, - progress)); + gfx::DecomposedTransform to_return = gfx::BlendDecomposedTransforms( + decomposed_target_value_, decomposed_initial_value_, + gfx::Tween::CalculateValue(tween_type_, progress)); return gfx::ComposeTransform(to_return); }
diff --git a/ui/events/ozone/evdev/input_controller_evdev.cc b/ui/events/ozone/evdev/input_controller_evdev.cc index 1de725c..aac3e2a0 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.cc +++ b/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -8,6 +8,7 @@ #include <algorithm> +#include "base/callback.h" #include "base/memory/ptr_util.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/events/devices/device_data_manager.h" @@ -85,9 +86,9 @@ keyboard_->GetAutoRepeatRate(delay, interval); } -bool InputControllerEvdev::SetCurrentLayoutByName( +void InputControllerEvdev::SetCurrentLayoutByName( const std::string& layout_name) { - return keyboard_->SetCurrentLayoutByName(layout_name); + keyboard_->SetCurrentLayoutByName(layout_name); } void InputControllerEvdev::SetInternalTouchpadEnabled(bool enabled) { @@ -159,20 +160,19 @@ } void InputControllerEvdev::GetTouchDeviceStatus( - const GetTouchDeviceStatusReply& reply) { + GetTouchDeviceStatusReply reply) { if (input_device_factory_) - input_device_factory_->GetTouchDeviceStatus(reply); + input_device_factory_->GetTouchDeviceStatus(std::move(reply)); else - reply.Run(base::WrapUnique(new std::string)); + std::move(reply).Run(std::string()); } -void InputControllerEvdev::GetTouchEventLog( - const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) { +void InputControllerEvdev::GetTouchEventLog(const base::FilePath& out_dir, + GetTouchEventLogReply reply) { if (input_device_factory_) - input_device_factory_->GetTouchEventLog(out_dir, reply); + input_device_factory_->GetTouchEventLog(out_dir, std::move(reply)); else - reply.Run(base::WrapUnique(new std::vector<base::FilePath>)); + std::move(reply).Run(std::vector<base::FilePath>()); } void InputControllerEvdev::ScheduleUpdateDeviceSettings() {
diff --git a/ui/events/ozone/evdev/input_controller_evdev.h b/ui/events/ozone/evdev/input_controller_evdev.h index a590b358..6d1adcf 100644 --- a/ui/events/ozone/evdev/input_controller_evdev.h +++ b/ui/events/ozone/evdev/input_controller_evdev.h
@@ -48,7 +48,7 @@ const base::TimeDelta& interval) override; void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) override; - bool SetCurrentLayoutByName(const std::string& layout_name) override; + void SetCurrentLayoutByName(const std::string& layout_name) override; void SetTouchEventLoggingEnabled(bool enabled) override; void SetTouchpadSensitivity(int value) override; void SetTapToClick(bool enabled) override; @@ -58,9 +58,9 @@ void SetMouseSensitivity(int value) override; void SetPrimaryButtonRight(bool right) override; void SetTapToClickPaused(bool state) override; - void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override; + void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) override; void GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) override; + GetTouchEventLogReply reply) override; void SetInternalTouchpadEnabled(bool enabled) override; bool IsInternalTouchpadEnabled() const override; void SetTouchscreensEnabled(bool enabled) override;
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.cc b/ui/events/ozone/evdev/input_device_factory_evdev.cc index 4eb65773..ab3ec28 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -267,24 +267,22 @@ } void InputDeviceFactoryEvdev::GetTouchDeviceStatus( - const GetTouchDeviceStatusReply& reply) { - std::unique_ptr<std::string> status(new std::string); + InputController::GetTouchDeviceStatusReply reply) { + std::string status; #if defined(USE_EVDEV_GESTURES) - DumpTouchDeviceStatus(gesture_property_provider_.get(), status.get()); + DumpTouchDeviceStatus(gesture_property_provider_.get(), &status); #endif - reply.Run(std::move(status)); + std::move(reply).Run(status); } void InputDeviceFactoryEvdev::GetTouchEventLog( const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) { - std::unique_ptr<std::vector<base::FilePath>> log_paths( - new std::vector<base::FilePath>); + InputController::GetTouchEventLogReply reply) { #if defined(USE_EVDEV_GESTURES) DumpTouchEventLog(converters_, gesture_property_provider_.get(), out_dir, - std::move(log_paths), reply); + std::move(reply)); #else - reply.Run(std::move(log_paths)); + std::move(reply).Run(std::vector<base::FilePath>()); #endif }
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev.h b/ui/events/ozone/evdev/input_device_factory_evdev.h index ddfbc999..3c20987 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev.h +++ b/ui/events/ozone/evdev/input_device_factory_evdev.h
@@ -20,6 +20,7 @@ #include "ui/events/ozone/evdev/event_device_info.h" #include "ui/events/ozone/evdev/events_ozone_evdev_export.h" #include "ui/events/ozone/evdev/input_device_settings_evdev.h" +#include "ui/ozone/public/input_controller.h" namespace ui { @@ -34,11 +35,6 @@ class GesturePropertyProvider; #endif -typedef base::Callback<void(std::unique_ptr<std::string>)> - GetTouchDeviceStatusReply; -typedef base::Callback<void(std::unique_ptr<std::vector<base::FilePath>>)> - GetTouchEventLogReply; - // Manager for event device objects. All device I/O starts here. class EVENTS_OZONE_EVDEV_EXPORT InputDeviceFactoryEvdev { public: @@ -61,9 +57,9 @@ // Bits from InputController that have to be answered on IO. void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); - void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); + void GetTouchDeviceStatus(InputController::GetTouchDeviceStatusReply reply); void GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply); + InputController::GetTouchEventLogReply reply); base::WeakPtr<InputDeviceFactoryEvdev> GetWeakPtr();
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc index 8eb3697..2696967 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc +++ b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.cc
@@ -5,6 +5,7 @@ #include "ui/events/ozone/evdev/input_device_factory_evdev_proxy.h" #include "base/bind.h" +#include "base/callback.h" #include "base/threading/thread_task_runner_handle.h" #include "ui/events/ozone/evdev/input_device_factory_evdev.h" @@ -14,19 +15,19 @@ void ForwardGetTouchDeviceStatusReply( scoped_refptr<base::SingleThreadTaskRunner> reply_runner, - const GetTouchDeviceStatusReply& reply, - std::unique_ptr<std::string> status) { + InputController::GetTouchDeviceStatusReply reply, + const std::string& status) { // Thread hop back to UI for reply. - reply_runner->PostTask(FROM_HERE, base::Bind(reply, base::Passed(&status))); + reply_runner->PostTask(FROM_HERE, base::BindOnce(std::move(reply), status)); } void ForwardGetTouchEventLogReply( scoped_refptr<base::SingleThreadTaskRunner> reply_runner, - const GetTouchEventLogReply& reply, - std::unique_ptr<std::vector<base::FilePath>> log_paths) { + InputController::GetTouchEventLogReply reply, + const std::vector<base::FilePath>& log_paths) { // Thread hop back to UI for reply. reply_runner->PostTask(FROM_HERE, - base::Bind(reply, base::Passed(&log_paths))); + base::BindOnce(std::move(reply), log_paths)); } } // namespace @@ -74,24 +75,26 @@ } void InputDeviceFactoryEvdevProxy::GetTouchDeviceStatus( - const GetTouchDeviceStatusReply& reply) { + InputController::GetTouchDeviceStatusReply reply) { task_runner_->PostTask( FROM_HERE, - base::Bind(&InputDeviceFactoryEvdev::GetTouchDeviceStatus, - input_device_factory_, - base::Bind(&ForwardGetTouchDeviceStatusReply, - base::ThreadTaskRunnerHandle::Get(), reply))); + base::BindOnce(&InputDeviceFactoryEvdev::GetTouchDeviceStatus, + input_device_factory_, + base::BindOnce(&ForwardGetTouchDeviceStatusReply, + base::ThreadTaskRunnerHandle::Get(), + std::move(reply)))); } void InputDeviceFactoryEvdevProxy::GetTouchEventLog( const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) { + InputController::GetTouchEventLogReply reply) { task_runner_->PostTask( FROM_HERE, - base::Bind(&InputDeviceFactoryEvdev::GetTouchEventLog, - input_device_factory_, out_dir, - base::Bind(&ForwardGetTouchEventLogReply, - base::ThreadTaskRunnerHandle::Get(), reply))); + base::BindOnce(&InputDeviceFactoryEvdev::GetTouchEventLog, + input_device_factory_, out_dir, + base::BindOnce(&ForwardGetTouchEventLogReply, + base::ThreadTaskRunnerHandle::Get(), + std::move(reply)))); } } // namespace ui
diff --git a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h index 1b736ea..c7c07070 100644 --- a/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h +++ b/ui/events/ozone/evdev/input_device_factory_evdev_proxy.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "ui/events/ozone/evdev/events_ozone_evdev_export.h" +#include "ui/ozone/public/input_controller.h" namespace ui { @@ -23,11 +24,6 @@ class InputDeviceFactoryEvdev; struct InputDeviceSettingsEvdev; -typedef base::Callback<void(std::unique_ptr<std::string>)> - GetTouchDeviceStatusReply; -typedef base::Callback<void(std::unique_ptr<std::vector<base::FilePath>>)> - GetTouchEventLogReply; - // Thread safe proxy for InputDeviceFactoryEvdev. // // This is used on the UI thread to proxy calls to the real object on @@ -47,9 +43,9 @@ void SetCapsLockLed(bool enabled); void SetTouchEventLoggingEnabled(bool enabled); void UpdateInputDeviceSettings(const InputDeviceSettingsEvdev& settings); - void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply); + void GetTouchDeviceStatus(InputController::GetTouchDeviceStatusReply reply); void GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply); + InputController::GetTouchEventLogReply reply); private: scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc b/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc index 0d6bc53..3b1f400 100644 --- a/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc +++ b/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.cc
@@ -173,8 +173,8 @@ converters, GesturePropertyProvider* provider, const base::FilePath& out_dir, - std::unique_ptr<std::vector<base::FilePath>> log_paths, - const GetTouchEventLogReply& reply) { + InputController::GetTouchEventLogReply reply) { + std::vector<base::FilePath> log_paths; // Get device ids. std::vector<int> ids; provider->GetDeviceIdsByType(DT_ALL, &ids); @@ -215,9 +215,9 @@ // Historically, we compress touchpad/mouse logs with gzip before tarring // them up. We DONT compress touchscreen logs though. log_paths_to_be_compressed->push_back(gesture_log_filename); - log_paths->push_back(base::FilePath(gesture_log_filename)); + log_paths.push_back(base::FilePath(gesture_log_filename)); log_paths_to_be_compressed->push_back(evdev_log_filename); - log_paths->push_back(base::FilePath(evdev_log_filename)); + log_paths.push_back(base::FilePath(evdev_log_filename)); } for (const auto& converter_pair : converters) { @@ -228,7 +228,7 @@ out_dir, "evdev_input_events_", now, converter->id()); base::Move(base::FilePath(kInputEventsLogFile), base::FilePath(touch_evdev_log_filename)); - log_paths->push_back(base::FilePath(touch_evdev_log_filename)); + log_paths.push_back(base::FilePath(touch_evdev_log_filename)); } } @@ -238,7 +238,7 @@ {base::MayBlock(), base::TaskPriority::BACKGROUND, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::Bind(&CompressDumpedLog, base::Passed(&log_paths_to_be_compressed)), - base::Bind(reply, base::Passed(&log_paths))); + base::BindOnce(std::move(reply), log_paths)); } } // namespace ui
diff --git a/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h b/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h index ab6ffcc..da2a356 100644 --- a/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h +++ b/ui/events/ozone/evdev/libgestures_glue/gesture_feedback.h
@@ -9,10 +9,10 @@ #include <string> #include <vector> -#include "base/callback.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "ui/events/ozone/evdev/touch_event_converter_evdev.h" +#include "ui/ozone/public/input_controller.h" namespace ui { @@ -26,9 +26,6 @@ class GesturePropertyProvider; -typedef base::Callback<void(std::unique_ptr<std::vector<base::FilePath>>)> - GetTouchEventLogReply; - // Utility functions for generating gesture related logs. These logs will be // included in user feedback reports. void DumpTouchDeviceStatus(GesturePropertyProvider* provider, @@ -39,8 +36,7 @@ converter, GesturePropertyProvider* provider, const base::FilePath& out_dir, - std::unique_ptr<std::vector<base::FilePath>> log_paths, - const GetTouchEventLogReply& reply); + InputController::GetTouchEventLogReply reply); } // namespace ui
diff --git a/ui/gfx/BUILD.gn b/ui/gfx/BUILD.gn index e78c050c..8b34733 100644 --- a/ui/gfx/BUILD.gn +++ b/ui/gfx/BUILD.gn
@@ -658,6 +658,7 @@ "geometry/point3_unittest.cc", "geometry/point_unittest.cc", "geometry/quad_unittest.cc", + "geometry/quaternion_unittest.cc", "geometry/rect_unittest.cc", "geometry/safe_integer_conversions_unittest.cc", "geometry/scroll_offset_unittest.cc",
diff --git a/ui/gfx/geometry/BUILD.gn b/ui/gfx/geometry/BUILD.gn index 0bf2db1..7bbae4d 100644 --- a/ui/gfx/geometry/BUILD.gn +++ b/ui/gfx/geometry/BUILD.gn
@@ -29,6 +29,8 @@ "point_f.h", "quad_f.cc", "quad_f.h", + "quaternion.cc", + "quaternion.h", "rect.cc", "rect.h", "rect_conversions.cc",
diff --git a/ui/gfx/geometry/quaternion.cc b/ui/gfx/geometry/quaternion.cc new file mode 100644 index 0000000..283df36 --- /dev/null +++ b/ui/gfx/geometry/quaternion.cc
@@ -0,0 +1,76 @@ +// 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 "ui/gfx/geometry/quaternion.h" + +#include <algorithm> +#include <cmath> + +#include "base/strings/stringprintf.h" +#include "ui/gfx/geometry/vector3d_f.h" + +namespace gfx { + +namespace { + +const double kEpsilon = 1e-5; + +} // namespace + +Quaternion::Quaternion(const Vector3dF& axis, double theta) { + // Rotation angle is the product of |angle| and the magnitude of |axis|. + double length = axis.Length(); + if (std::abs(length) < kEpsilon) + return; + + Vector3dF normalized = axis; + normalized.Scale(1.0 / length); + + theta *= 0.5; + double s = sin(theta); + x_ = normalized.x() * s; + y_ = normalized.y() * s; + z_ = normalized.z() * s; + w_ = cos(theta); +} + +// Taken from http://www.w3.org/TR/css3-transforms/. +Quaternion Quaternion::Slerp(const Quaternion& q, double t) const { + double dot = x_ * q.x_ + y_ * q.y_ + z_ * q.z_ + w_ * q.w_; + + // Clamp dot to -1.0 <= dot <= 1.0. + dot = std::min(std::max(dot, -1.0), 1.0); + + // Quaternions are facing the same direction. + if (std::abs(dot - 1.0) < kEpsilon || std::abs(dot + 1.0) < kEpsilon) + return *this; + + // TODO(vmpstr): In case the dot is 0, the vectors are exactly opposite + // of each other. In this case, it's technically not correct to just pick one + // of the vectors, we instead need to pick how to interpolate. However, the + // spec isn't clear on this. If we don't handle the -1 case explicitly, it + // results in inf and nans however, which is worse. See crbug.com/506543 for + // more discussion. + if (std::abs(dot) < kEpsilon) + return *this; + + double denom = std::sqrt(1.0 - dot * dot); + double theta = std::acos(dot); + double w = std::sin(t * theta) * (1.0 / denom); + + double s1 = std::cos(t * theta) - dot * w; + double s2 = w; + + return (s1 * *this) + (s2 * q); +} + +Quaternion Quaternion::Lerp(const Quaternion& q, double t) const { + return ((1.0 - t) * *this) + (t * q); +} + +std::string Quaternion::ToString() const { + return base::StringPrintf("[%f %f %f %f]", x_, y_, z_, w_); +} + +} // namespace gfx
diff --git a/ui/gfx/geometry/quaternion.h b/ui/gfx/geometry/quaternion.h new file mode 100644 index 0000000..9b214a0 --- /dev/null +++ b/ui/gfx/geometry/quaternion.h
@@ -0,0 +1,80 @@ +// 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 UI_GFX_GEOMETRY_QUATERNION_ +#define UI_GFX_GEOMETRY_QUATERNION_ + +#include <string> + +#include "ui/gfx/gfx_export.h" + +namespace gfx { + +class Vector3dF; + +class GFX_EXPORT Quaternion { + public: + constexpr Quaternion() = default; + constexpr Quaternion(double x, double y, double z, double w) + : x_(x), y_(y), z_(z), w_(w) {} + Quaternion(const Vector3dF& axis, double angle); + + constexpr double x() const { return x_; } + void set_x(double x) { x_ = x; } + + constexpr double y() const { return y_; } + void set_y(double y) { y_ = y; } + + constexpr double z() const { return z_; } + void set_z(double z) { z_ = z; } + + constexpr double w() const { return w_; } + void set_w(double w) { w_ = w; } + + Quaternion operator+(const Quaternion& q) const { + return {q.x_ + x_, q.y_ + y_, q.z_ + z_, q.w_ + w_}; + } + + Quaternion operator*(const Quaternion& q) const { + return {w_ * q.x_ + x_ * q.w_ + y_ * q.z_ - z_ * q.y_, + w_ * q.y_ - x_ * q.z_ + y_ * q.w_ + z_ * q.x_, + w_ * q.z_ + x_ * q.y_ - y_ * q.x_ + z_ * q.w_, + w_ * q.w_ - x_ * q.x_ - y_ * q.y_ - z_ * q.z_}; + } + + Quaternion inverse() const { return {-x_, -y_, -z_, w_}; } + + // Blends with the given quaternion, |q|, via spherical linear interpolation. + // Values of |t| in the range [0, 1] will interpolate between |this| and |q|, + // and values outside that range will extrapolate beyond in either direction. + Quaternion Slerp(const Quaternion& q, double t) const; + + // Blends with the given quaternion, |q|, via linear interpolation. This is + // rarely what you want. Use only if you know what you're doing. + // Values of |t| in the range [0, 1] will interpolate between |this| and |q|, + // and values outside that range will extrapolate beyond in either direction. + Quaternion Lerp(const Quaternion& q, double t) const; + + std::string ToString() const; + + private: + double x_ = 0.0; + double y_ = 0.0; + double z_ = 0.0; + double w_ = 1.0; +}; + +// |s| is an arbitrary, real constant. +inline Quaternion operator*(const Quaternion& q, double s) { + return Quaternion(q.x() * s, q.y() * s, q.z() * s, q.w() * s); +} + +// |s| is an arbitrary, real constant. +inline Quaternion operator*(double s, const Quaternion& q) { + return Quaternion(q.x() * s, q.y() * s, q.z() * s, q.w() * s); +} + +} // namespace gfx + +#endif // UI_GFX_GEOMETRY_QUATERNION_
diff --git a/ui/gfx/geometry/quaternion_unittest.cc b/ui/gfx/geometry/quaternion_unittest.cc new file mode 100644 index 0000000..b66d0ffd8 --- /dev/null +++ b/ui/gfx/geometry/quaternion_unittest.cc
@@ -0,0 +1,158 @@ +// 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. + +#define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. + +#include <cmath> + +#include "base/macros.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/quaternion.h" +#include "ui/gfx/geometry/vector3d_f.h" + +namespace gfx { + +namespace { + +const double kEpsilon = 1e-7; + +} // namespace + +TEST(QuatTest, DefaultConstruction) { + Quaternion q; + EXPECT_FLOAT_EQ(0.0, q.x()); + EXPECT_FLOAT_EQ(0.0, q.y()); + EXPECT_FLOAT_EQ(0.0, q.z()); + EXPECT_FLOAT_EQ(1.0, q.w()); +} + +TEST(QuatTest, AxisAngleCommon) { + float radians = 0.5; + Quaternion q(Vector3dF(1.0f, 0.0f, 0.0f), radians); + EXPECT_FLOAT_EQ(std::sin(radians / 2), q.x()); + EXPECT_FLOAT_EQ(0.0, q.y()); + EXPECT_FLOAT_EQ(0.0, q.z()); + EXPECT_FLOAT_EQ(std::cos(radians / 2), q.w()); +} + +TEST(QuatTest, AxisAngleWithZeroLengthAxis) { + Quaternion q(Vector3dF(0.0f, 0.0f, 0.0f), 0.5); + // If the axis of zero length, we should assume the default values. + EXPECT_FLOAT_EQ(0.0, q.x()); + EXPECT_FLOAT_EQ(0.0, q.y()); + EXPECT_FLOAT_EQ(0.0, q.z()); + EXPECT_FLOAT_EQ(1.0, q.w()); +} + +TEST(QuatTest, Addition) { + float values[] = {0.f, 1.0f, 100.0f}; + for (size_t i = 0; i < arraysize(values); ++i) { + float t = values[i]; + Quaternion a(t, 2 * t, 3 * t, 4 * t); + Quaternion b(5 * t, 4 * t, 3 * t, 2 * t); + Quaternion sum = a + b; + EXPECT_FLOAT_EQ(6 * t, sum.x()); + EXPECT_FLOAT_EQ(6 * t, sum.y()); + EXPECT_FLOAT_EQ(6 * t, sum.z()); + EXPECT_FLOAT_EQ(6 * t, sum.w()); + } +} + +TEST(QuatTest, Multiplication) { + struct { + Quaternion a; + Quaternion b; + Quaternion expected; + } cases[] = { + {Quaternion(1, 0, 0, 0), Quaternion(1, 0, 0, 0), Quaternion(0, 0, 0, -1)}, + {Quaternion(0, 1, 0, 0), Quaternion(0, 1, 0, 0), Quaternion(0, 0, 0, -1)}, + {Quaternion(0, 0, 1, 0), Quaternion(0, 0, 1, 0), Quaternion(0, 0, 0, -1)}, + {Quaternion(0, 0, 0, 1), Quaternion(0, 0, 0, 1), Quaternion(0, 0, 0, 1)}, + {Quaternion(1, 2, 3, 4), Quaternion(5, 6, 7, 8), + Quaternion(24, 48, 48, -6)}, + {Quaternion(5, 6, 7, 8), Quaternion(1, 2, 3, 4), + Quaternion(32, 32, 56, -6)}, + }; + + for (size_t i = 0; i < arraysize(cases); ++i) { + Quaternion product = cases[i].a * cases[i].b; + EXPECT_FLOAT_EQ(cases[i].expected.x(), product.x()); + EXPECT_FLOAT_EQ(cases[i].expected.y(), product.y()); + EXPECT_FLOAT_EQ(cases[i].expected.z(), product.z()); + EXPECT_FLOAT_EQ(cases[i].expected.w(), product.w()); + } +} + +TEST(QuatTest, Scaling) { + float values[] = {0.f, 1.0f, 100.0f}; + for (size_t i = 0; i < arraysize(values); ++i) { + Quaternion q(1, 2, 3, 4); + Quaternion qs = q * values[i]; + Quaternion sq = values[i] * q; + EXPECT_FLOAT_EQ(1 * values[i], qs.x()); + EXPECT_FLOAT_EQ(2 * values[i], qs.y()); + EXPECT_FLOAT_EQ(3 * values[i], qs.z()); + EXPECT_FLOAT_EQ(4 * values[i], qs.w()); + EXPECT_FLOAT_EQ(1 * values[i], sq.x()); + EXPECT_FLOAT_EQ(2 * values[i], sq.y()); + EXPECT_FLOAT_EQ(3 * values[i], sq.z()); + EXPECT_FLOAT_EQ(4 * values[i], sq.w()); + } +} + +TEST(QuatTest, Lerp) { + for (size_t i = 0; i < 100; ++i) { + Quaternion a(0, 0, 0, 0); + Quaternion b(1, 2, 3, 4); + float t = static_cast<float>(i) / 100.0f; + Quaternion interpolated = a.Lerp(b, t); + EXPECT_FLOAT_EQ(1 * t, interpolated.x()); + EXPECT_FLOAT_EQ(2 * t, interpolated.y()); + EXPECT_FLOAT_EQ(3 * t, interpolated.z()); + EXPECT_FLOAT_EQ(4 * t, interpolated.w()); + } +} + +TEST(QuatTest, Slerp) { + Vector3dF axis(1, 1, 1); + double start_radians = -0.5; + double stop_radians = 0.5; + Quaternion start(axis, start_radians); + Quaternion stop(axis, stop_radians); + + for (size_t i = 0; i < 100; ++i) { + float t = static_cast<float>(i) / 100.0f; + double radians = (1.0 - t) * start_radians + t * stop_radians; + Quaternion expected(axis, radians); + Quaternion interpolated = start.Slerp(stop, t); + EXPECT_NEAR(expected.x(), interpolated.x(), kEpsilon); + EXPECT_NEAR(expected.y(), interpolated.y(), kEpsilon); + EXPECT_NEAR(expected.z(), interpolated.z(), kEpsilon); + EXPECT_NEAR(expected.w(), interpolated.w(), kEpsilon); + } +} + +TEST(QuatTest, SlerpOppositeAngles) { + Vector3dF axis(1, 1, 1); + double start_radians = -M_PI_2; + double stop_radians = M_PI_2; + Quaternion start(axis, start_radians); + Quaternion stop(axis, stop_radians); + + // When quaternions are pointed in the fully opposite direction, we take the + // interpolated quaternion to be the first. This is arbitrary, but if we + // change this policy, this test should fail. + Quaternion expected = start; + + for (size_t i = 0; i < 100; ++i) { + float t = static_cast<float>(i) / 100.0f; + Quaternion interpolated = start.Slerp(stop, t); + EXPECT_FLOAT_EQ(expected.x(), interpolated.x()); + EXPECT_FLOAT_EQ(expected.y(), interpolated.y()); + EXPECT_FLOAT_EQ(expected.z(), interpolated.z()); + EXPECT_FLOAT_EQ(expected.w(), interpolated.w()); + } +} + +} // namespace gfx
diff --git a/ui/gfx/interpolated_transform.cc b/ui/gfx/interpolated_transform.cc index fe367f9..8cf04d25 100644 --- a/ui/gfx/interpolated_transform.cc +++ b/ui/gfx/interpolated_transform.cc
@@ -364,12 +364,8 @@ gfx::Transform InterpolatedMatrixTransform::InterpolateButDoNotCompose(float t) const { - gfx::DecomposedTransform blended; - bool success = gfx::BlendDecomposedTransforms(&blended, - end_decomp_, - start_decomp_, - t); - DCHECK(success); + gfx::DecomposedTransform blended = + gfx::BlendDecomposedTransforms(end_decomp_, start_decomp_, t); return gfx::ComposeTransform(blended); }
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc index 97b6c8f..5cf7737 100644 --- a/ui/gfx/render_text.cc +++ b/ui/gfx/render_text.cc
@@ -12,6 +12,7 @@ #include "base/command_line.h" #include "base/i18n/break_iterator.h" #include "base/logging.h" +#include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -105,11 +106,11 @@ // Creates a SkShader to fade the text, with |left_part| specifying the left // fade effect, if any, and |right_part| specifying the right fade effect. -sk_sp<SkShader> CreateFadeShader(const FontList& font_list, - const Rect& text_rect, - const Rect& left_part, - const Rect& right_part, - SkColor color) { +std::unique_ptr<cc::PaintShader> CreateFadeShader(const FontList& font_list, + const Rect& text_rect, + const Rect& left_part, + const Rect& right_part, + SkColor color) { // The shader should only specify transparency of the fade itself, not the // original transparency, which will be applied by the actual renderer. DCHECK_EQ(SkColorGetA(color), static_cast<uint8_t>(0xff)); @@ -144,9 +145,9 @@ const SkPoint points[2] = { PointToSkPoint(text_rect.origin()), PointToSkPoint(text_rect.top_right()) }; - return - SkGradientShader::MakeLinear(&points[0], &colors[0], &positions[0], - colors.size(), SkShader::kClamp_TileMode); + return cc::PaintShader::MakeLinearGradient(&points[0], &colors[0], + &positions[0], colors.size(), + SkShader::kClamp_TileMode); } // Converts a FontRenderParams::Hinting value to the corresponding @@ -231,8 +232,8 @@ flags_.setColor(foreground); } -void SkiaTextRenderer::SetShader(sk_sp<SkShader> shader) { - flags_.setShader(cc::WrapSkShader(std::move(shader))); +void SkiaTextRenderer::SetShader(std::unique_ptr<cc::PaintShader> shader) { + flags_.setShader(std::move(shader)); } void SkiaTextRenderer::SetUnderlineMetrics(SkScalar thickness,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h index 00fe00c..5353be69 100644 --- a/ui/gfx/render_text.h +++ b/ui/gfx/render_text.h
@@ -37,7 +37,6 @@ class SkDrawLooper; struct SkPoint; -class SkShader; class SkTypeface; namespace gfx { @@ -63,7 +62,7 @@ void SetTypeface(sk_sp<SkTypeface> typeface); void SetTextSize(SkScalar size); void SetForegroundColor(SkColor foreground); - void SetShader(sk_sp<SkShader> shader); + void SetShader(std::unique_ptr<cc::PaintShader> shader); // Sets underline metrics to use if the text will be drawn with an underline. // If not set, default values based on the size of the text will be used. The // two metrics must be set together.
diff --git a/ui/gfx/skia_paint_util.cc b/ui/gfx/skia_paint_util.cc index dcaea71b..6bbe1ca 100644 --- a/ui/gfx/skia_paint_util.cc +++ b/ui/gfx/skia_paint_util.cc
@@ -4,6 +4,7 @@ #include "ui/gfx/skia_paint_util.h" +#include "base/memory/ptr_util.h" #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/effects/SkBlurMaskFilter.h" #include "third_party/skia/include/effects/SkGradientShader.h" @@ -12,16 +13,17 @@ namespace gfx { -sk_sp<cc::PaintShader> CreateImageRepShader(const gfx::ImageSkiaRep& image_rep, - cc::PaintShader::TileMode tile_mode, - const SkMatrix& local_matrix) { - return cc::WrapSkShader(CreateImageRepShaderForScale( - image_rep, tile_mode, local_matrix, image_rep.scale())); +std::unique_ptr<cc::PaintShader> CreateImageRepShader( + const gfx::ImageSkiaRep& image_rep, + SkShader::TileMode tile_mode, + const SkMatrix& local_matrix) { + return CreateImageRepShaderForScale(image_rep, tile_mode, local_matrix, + image_rep.scale()); } -sk_sp<cc::PaintShader> CreateImageRepShaderForScale( +std::unique_ptr<cc::PaintShader> CreateImageRepShaderForScale( const gfx::ImageSkiaRep& image_rep, - cc::PaintShader::TileMode tile_mode, + SkShader::TileMode tile_mode, const SkMatrix& local_matrix, SkScalar scale) { // Unscale matrix by |scale| such that the bitmap is drawn at the @@ -36,21 +38,22 @@ shader_scale.setScaleX(local_matrix.getScaleX() / scale); shader_scale.setScaleY(local_matrix.getScaleY() / scale); - return cc::PaintShader::MakeBitmapShader(image_rep.sk_bitmap(), tile_mode, - tile_mode, &shader_scale); + return cc::PaintShader::MakeImage( + SkImage::MakeFromBitmap(image_rep.sk_bitmap()), tile_mode, tile_mode, + &shader_scale); } -sk_sp<cc::PaintShader> CreateGradientShader(int start_point, - int end_point, - SkColor start_color, - SkColor end_color) { +std::unique_ptr<cc::PaintShader> CreateGradientShader(int start_point, + int end_point, + SkColor start_color, + SkColor end_color) { SkColor grad_colors[2] = {start_color, end_color}; SkPoint grad_points[2]; grad_points[0].iset(0, start_point); grad_points[1].iset(0, end_point); - return cc::WrapSkShader(SkGradientShader::MakeLinear( - grad_points, grad_colors, NULL, 2, cc::PaintShader::kClamp_TileMode)); + return cc::PaintShader::MakeLinearGradient(grad_points, grad_colors, nullptr, + 2, SkShader::kClamp_TileMode); } // This is copied from
diff --git a/ui/gfx/skia_paint_util.h b/ui/gfx/skia_paint_util.h index f7e5d82d..1d163437 100644 --- a/ui/gfx/skia_paint_util.h +++ b/ui/gfx/skia_paint_util.h
@@ -5,6 +5,7 @@ #ifndef UI_GFX_SKIA_PAINT_UTIL_H_ #define UI_GFX_SKIA_PAINT_UTIL_H_ +#include <memory> #include <vector> #include "cc/paint/paint_shader.h" @@ -25,24 +26,25 @@ // TODO(pkotwicz): Allow shader's local matrix to be changed after the shader // is created. // -GFX_EXPORT sk_sp<cc::PaintShader> CreateImageRepShader( +GFX_EXPORT std::unique_ptr<cc::PaintShader> CreateImageRepShader( const gfx::ImageSkiaRep& image_rep, - cc::PaintShader::TileMode tile_mode, + SkShader::TileMode tile_mode, const SkMatrix& local_matrix); // Creates a bitmap shader for the image rep with the passed in scale factor. -GFX_EXPORT sk_sp<cc::PaintShader> CreateImageRepShaderForScale( +GFX_EXPORT std::unique_ptr<cc::PaintShader> CreateImageRepShaderForScale( const gfx::ImageSkiaRep& image_rep, - cc::PaintShader::TileMode tile_mode, + SkShader::TileMode tile_mode, const SkMatrix& local_matrix, SkScalar scale); // Creates a vertical gradient shader. The caller owns the shader. // Example usage to avoid leaks: -GFX_EXPORT sk_sp<cc::PaintShader> CreateGradientShader(int start_point, - int end_point, - SkColor start_color, - SkColor end_color); +GFX_EXPORT std::unique_ptr<cc::PaintShader> CreateGradientShader( + int start_point, + int end_point, + SkColor start_color, + SkColor end_color); // Creates a draw looper to generate |shadows|. The caller owns the draw looper. // NULL is returned if |shadows| is empty since no draw looper is needed in
diff --git a/ui/gfx/transform.cc b/ui/gfx/transform.cc index 9c8a0053..6e6aa91 100644 --- a/ui/gfx/transform.cc +++ b/ui/gfx/transform.cc
@@ -14,6 +14,7 @@ #include "ui/gfx/geometry/box_f.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point3_f.h" +#include "ui/gfx/geometry/quaternion.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/safe_integer_conversions.h" #include "ui/gfx/geometry/vector3d_f.h" @@ -100,6 +101,25 @@ matrix_.set(1, 3, y_translation); } +Transform::Transform(const Quaternion& q) + : matrix_(SkMatrix44::kUninitialized_Constructor) { + double x = q.x(); + double y = q.y(); + double z = q.z(); + double w = q.w(); + + // Implicitly calls matrix.setIdentity() + matrix_.set3x3(SkDoubleToMScalar(1.0 - 2.0 * (y * y + z * z)), + SkDoubleToMScalar(2.0 * (x * y + z * w)), + SkDoubleToMScalar(2.0 * (x * z - y * w)), + SkDoubleToMScalar(2.0 * (x * y - z * w)), + SkDoubleToMScalar(1.0 - 2.0 * (x * x + z * z)), + SkDoubleToMScalar(2.0 * (y * z + x * w)), + SkDoubleToMScalar(2.0 * (x * z + y * w)), + SkDoubleToMScalar(2.0 * (y * z - x * w)), + SkDoubleToMScalar(1.0 - 2.0 * (x * x + y * y))); +} + void Transform::RotateAboutXAxis(double degrees) { double radians = degrees * M_PI / 180; SkMScalar cosTheta = SkDoubleToMScalar(std::cos(radians)); @@ -506,8 +526,7 @@ !DecomposeTransform(&from_decomp, from)) return false; - if (!BlendDecomposedTransforms(&to_decomp, to_decomp, from_decomp, progress)) - return false; + to_decomp = BlendDecomposedTransforms(to_decomp, from_decomp, progress); matrix_ = ComposeTransform(to_decomp).matrix(); return true;
diff --git a/ui/gfx/transform.h b/ui/gfx/transform.h index a942bd6c..0964f74 100644 --- a/ui/gfx/transform.h +++ b/ui/gfx/transform.h
@@ -19,6 +19,7 @@ class RectF; class Point; class Point3F; +class Quaternion; class Vector3dF; // 4x4 transformation matrix. Transform is cheap and explicitly allows @@ -69,6 +70,9 @@ SkMScalar x_translation, SkMScalar y_translation); + // Constructs a transform corresponding to the given quaternion. + explicit Transform(const Quaternion& q); + bool operator==(const Transform& rhs) const { return matrix_ == rhs.matrix_; } bool operator!=(const Transform& rhs) const { return matrix_ != rhs.matrix_; }
diff --git a/ui/gfx/transform_unittest.cc b/ui/gfx/transform_unittest.cc index 136f4198..b1b880a 100644 --- a/ui/gfx/transform_unittest.cc +++ b/ui/gfx/transform_unittest.cc
@@ -745,13 +745,8 @@ // A 180 degree rotation is exactly opposite on the sphere, therefore // either great circle arc to it is equivalent (and numerical precision // will determine which is closer). Test both directions. - Transform expected1; - expected1.RotateAbout(axes[index], 180.0 * t); - Transform expected2; - expected2.RotateAbout(axes[index], -180.0 * t); - - EXPECT_TRUE(MatricesAreNearlyEqual(expected1, to) || - MatricesAreNearlyEqual(expected2, to)) + Transform expected = from; + EXPECT_TRUE(MatricesAreNearlyEqual(expected, to)) << "axis: " << index << ", i: " << i; } } @@ -972,36 +967,41 @@ to = Transform(); to.Skew(0.0, 45.0); to.Blend(from, 0.25); - EXPECT_ROW1_NEAR(1.0823489449280947471976333, - 0.0464370719145053845178239, - 0.0, - 0.0, - to, - LOOSE_ERROR_THRESHOLD); - EXPECT_ROW2_NEAR(0.2152925909665224513123150, - 0.9541702441750861130032035, - 0.0, - 0.0, - to, - LOOSE_ERROR_THRESHOLD); + EXPECT_LT(1.0, to.matrix().get(0, 0)); + EXPECT_GT(1.5, to.matrix().get(0, 0)); + EXPECT_LT(0.0, to.matrix().get(0, 1)); + EXPECT_GT(0.5, to.matrix().get(0, 1)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(0, 2)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(0, 3)); + + EXPECT_LT(0.0, to.matrix().get(1, 0)); + EXPECT_GT(0.5, to.matrix().get(1, 0)); + EXPECT_LT(0.0, to.matrix().get(1, 1)); + EXPECT_GT(1.0, to.matrix().get(1, 1)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(1, 2)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(1, 3)); + EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to); EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to); to = Transform(); to.Skew(0.0, 45.0); to.Blend(from, 0.5); - EXPECT_ROW1_NEAR(1.1152212925809066312865525, - 0.0676495144007326631996335, - 0.0, - 0.0, - to, - LOOSE_ERROR_THRESHOLD); - EXPECT_ROW2_NEAR(0.4619397844342648662419037, - 0.9519009045724774464858342, - 0.0, - 0.0, - to, - LOOSE_ERROR_THRESHOLD); + + EXPECT_LT(1.0, to.matrix().get(0, 0)); + EXPECT_GT(1.5, to.matrix().get(0, 0)); + EXPECT_LT(0.0, to.matrix().get(0, 1)); + EXPECT_GT(0.5, to.matrix().get(0, 1)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(0, 2)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(0, 3)); + + EXPECT_LT(0.0, to.matrix().get(1, 0)); + EXPECT_GT(1.0, to.matrix().get(1, 0)); + EXPECT_LT(0.0, to.matrix().get(1, 1)); + EXPECT_GT(1.0, to.matrix().get(1, 1)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(1, 2)); + EXPECT_FLOAT_EQ(0.0, to.matrix().get(1, 3)); + EXPECT_ROW3_EQ(0.0f, 0.0f, 1.0f, 0.0f, to); EXPECT_ROW4_EQ(0.0f, 0.0f, 0.0f, 1.0f, to); @@ -1270,11 +1270,15 @@ EXPECT_EQ(0.0, decomp.translate[i]); EXPECT_EQ(1.0, decomp.scale[i]); EXPECT_EQ(0.0, decomp.skew[i]); - EXPECT_EQ(0.0, decomp.quaternion[i]); EXPECT_EQ(0.0, decomp.perspective[i]); } - EXPECT_EQ(1.0, decomp.quaternion[3]); EXPECT_EQ(1.0, decomp.perspective[3]); + + EXPECT_EQ(0.0, decomp.quaternion.x()); + EXPECT_EQ(0.0, decomp.quaternion.y()); + EXPECT_EQ(0.0, decomp.quaternion.z()); + EXPECT_EQ(1.0, decomp.quaternion.w()); + Transform identity; Transform composed = ComposeTransform(decomp); EXPECT_TRUE(MatricesAreNearlyEqual(identity, composed)); @@ -1295,7 +1299,7 @@ EXPECT_FLOAT_EQ(decomp.translate[0], degrees * 2); EXPECT_FLOAT_EQ(decomp.translate[1], -degrees * 3); double rotation = - std::acos(SkMScalarToDouble(decomp.quaternion[3])) * 360.0 / M_PI; + std::acos(SkMScalarToDouble(decomp.quaternion.w())) * 360.0 / M_PI; while (rotation < 0.0) rotation += 360.0; while (rotation > 360.0)
diff --git a/ui/gfx/transform_util.cc b/ui/gfx/transform_util.cc index 96e02724..2dd322fa 100644 --- a/ui/gfx/transform_util.cc +++ b/ui/gfx/transform_util.cc
@@ -56,46 +56,6 @@ return SkDoubleToMScalar(std::floor(SkMScalarToDouble(n) + 0.5)); } -// Taken from http://www.w3.org/TR/css3-transforms/. -bool Slerp(SkMScalar out[4], - const SkMScalar q1[4], - const SkMScalar q2[4], - double progress) { - double product = Dot<4>(q1, q2); - - // Clamp product to -1.0 <= product <= 1.0. - product = std::min(std::max(product, -1.0), 1.0); - - const double epsilon = 1e-5; - if (std::abs(product - 1.0) < epsilon) { - for (int i = 0; i < 4; ++i) - out[i] = q1[i]; - return true; - } - - // TODO(vmpstr): In case the product is -1, the vectors are exactly opposite - // of each other. In this case, it's technically not correct to just pick one - // of the vectors, we instead need to pick how to interpolate. However, the - // spec isn't clear on this. If we don't handle the -1 case explicitly, it - // results in inf and nans however, which is worse. See crbug.com/506543 for - // more discussion. - if (std::abs(product + 1.0) < epsilon) { - for (int i = 0; i < 4; ++i) - out[i] = q1[i]; - return true; - } - - double denom = std::sqrt(1.0 - product * product); - double theta = std::acos(product); - double w = std::sin(progress * theta) * (1.0 / denom); - - double scale1 = std::cos(progress * theta) - product * w; - double scale2 = w; - Combine<4>(out, q1, q2, scale1, scale2); - - return true; -} - // Returns false if the matrix cannot be normalized. bool Normalize(SkMatrix44& m) { if (m.get(3, 3) == 0.0) @@ -135,24 +95,7 @@ } SkMatrix44 BuildRotationMatrix(const DecomposedTransform& decomp) { - double x = decomp.quaternion[0]; - double y = decomp.quaternion[1]; - double z = decomp.quaternion[2]; - double w = decomp.quaternion[3]; - - SkMatrix44 matrix(SkMatrix44::kUninitialized_Constructor); - - // Implicitly calls matrix.setIdentity() - matrix.set3x3(SkDoubleToMScalar(1.0 - 2.0 * (y * y + z * z)), - SkDoubleToMScalar(2.0 * (x * y + z * w)), - SkDoubleToMScalar(2.0 * (x * z - y * w)), - SkDoubleToMScalar(2.0 * (x * y - z * w)), - SkDoubleToMScalar(1.0 - 2.0 * (x * x + z * z)), - SkDoubleToMScalar(2.0 * (y * z + x * w)), - SkDoubleToMScalar(2.0 * (x * z + y * w)), - SkDoubleToMScalar(2.0 * (y * z - x * w)), - SkDoubleToMScalar(1.0 - 2.0 * (x * x + y * y))); - return matrix; + return Transform(decomp.quaternion).matrix(); } SkMatrix44 BuildSnappedRotationMatrix(const DecomposedTransform& decomp) { @@ -282,22 +225,21 @@ scale[0] = scale[1] = scale[2] = 1.0; skew[0] = skew[1] = skew[2] = 0.0; perspective[0] = perspective[1] = perspective[2] = 0.0; - quaternion[0] = quaternion[1] = quaternion[2] = 0.0; - perspective[3] = quaternion[3] = 1.0; + perspective[3] = 1.0; } -bool BlendDecomposedTransforms(DecomposedTransform* out, - const DecomposedTransform& to, - const DecomposedTransform& from, - double progress) { +DecomposedTransform BlendDecomposedTransforms(const DecomposedTransform& to, + const DecomposedTransform& from, + double progress) { + DecomposedTransform out; double scalea = progress; double scaleb = 1.0 - progress; - Combine<3>(out->translate, to.translate, from.translate, scalea, scaleb); - Combine<3>(out->scale, to.scale, from.scale, scalea, scaleb); - Combine<3>(out->skew, to.skew, from.skew, scalea, scaleb); - Combine<4>( - out->perspective, to.perspective, from.perspective, scalea, scaleb); - return Slerp(out->quaternion, from.quaternion, to.quaternion, progress); + Combine<3>(out.translate, to.translate, from.translate, scalea, scaleb); + Combine<3>(out.scale, to.scale, from.scale, scalea, scaleb); + Combine<3>(out.skew, to.skew, from.skew, scalea, scaleb); + Combine<4>(out.perspective, to.perspective, from.perspective, scalea, scaleb); + out.quaternion = from.quaternion.Slerp(to.quaternion, progress); + return out; } // Taken from http://www.w3.org/TR/css3-transforms/. @@ -420,21 +362,22 @@ double row00 = SkMScalarToDouble(row[0][0]); double row11 = SkMScalarToDouble(row[1][1]); double row22 = SkMScalarToDouble(row[2][2]); - decomp->quaternion[0] = SkDoubleToMScalar( - 0.5 * std::sqrt(std::max(1.0 + row00 - row11 - row22, 0.0))); - decomp->quaternion[1] = SkDoubleToMScalar( - 0.5 * std::sqrt(std::max(1.0 - row00 + row11 - row22, 0.0))); - decomp->quaternion[2] = SkDoubleToMScalar( - 0.5 * std::sqrt(std::max(1.0 - row00 - row11 + row22, 0.0))); - decomp->quaternion[3] = SkDoubleToMScalar( - 0.5 * std::sqrt(std::max(1.0 + row00 + row11 + row22, 0.0))); + + decomp->quaternion.set_x(SkDoubleToMScalar( + 0.5 * std::sqrt(std::max(1.0 + row00 - row11 - row22, 0.0)))); + decomp->quaternion.set_y(SkDoubleToMScalar( + 0.5 * std::sqrt(std::max(1.0 - row00 + row11 - row22, 0.0)))); + decomp->quaternion.set_z(SkDoubleToMScalar( + 0.5 * std::sqrt(std::max(1.0 - row00 - row11 + row22, 0.0)))); + decomp->quaternion.set_w(SkDoubleToMScalar( + 0.5 * std::sqrt(std::max(1.0 + row00 + row11 + row22, 0.0)))); if (row[2][1] > row[1][2]) - decomp->quaternion[0] = -decomp->quaternion[0]; + decomp->quaternion.set_x(-decomp->quaternion.x()); if (row[0][2] > row[2][0]) - decomp->quaternion[1] = -decomp->quaternion[1]; + decomp->quaternion.set_y(-decomp->quaternion.y()); if (row[1][0] > row[0][1]) - decomp->quaternion[2] = -decomp->quaternion[2]; + decomp->quaternion.set_z(-decomp->quaternion.z()); return true; } @@ -495,23 +438,10 @@ "skew: %+0.4f %+0.4f %+0.4f\n" "perspective: %+0.4f %+0.4f %+0.4f %+0.4f\n" "quaternion: %+0.4f %+0.4f %+0.4f %+0.4f\n", - translate[0], - translate[1], - translate[2], - scale[0], - scale[1], - scale[2], - skew[0], - skew[1], - skew[2], - perspective[0], - perspective[1], - perspective[2], - perspective[3], - quaternion[0], - quaternion[1], - quaternion[2], - quaternion[3]); + translate[0], translate[1], translate[2], scale[0], scale[1], scale[2], + skew[0], skew[1], skew[2], perspective[0], perspective[1], perspective[2], + perspective[3], quaternion.x(), quaternion.y(), quaternion.z(), + quaternion.w()); } } // namespace gfx
diff --git a/ui/gfx/transform_util.h b/ui/gfx/transform_util.h index 597d877..78b7739 100644 --- a/ui/gfx/transform_util.h +++ b/ui/gfx/transform_util.h
@@ -6,6 +6,7 @@ #define UI_GFX_TRANSFORM_UTIL_H_ #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/quaternion.h" #include "ui/gfx/gfx_export.h" #include "ui/gfx/transform.h" @@ -28,7 +29,7 @@ SkMScalar scale[3]; SkMScalar skew[3]; SkMScalar perspective[4]; - SkMScalar quaternion[4]; + Quaternion quaternion; std::string ToString() const; @@ -37,12 +38,12 @@ // Interpolates the decomposed components |to| with |from| using the // routines described in http://www.w3.org/TR/css3-3d-transform/. -// |progress| is in the range [0, 1] (0 leaves |out| unchanged, and 1 -// assigns |from| to |out|). -GFX_EXPORT bool BlendDecomposedTransforms(DecomposedTransform* out, - const DecomposedTransform& to, - const DecomposedTransform& from, - double progress); +// |progress| is in the range [0, 1]. If 0 we will return |from|, if 1, we will +// return |to|. +GFX_EXPORT DecomposedTransform +BlendDecomposedTransforms(const DecomposedTransform& to, + const DecomposedTransform& from, + double progress); // Decomposes this transform into its translation, scale, skew, perspective, // and rotation components following the routines detailed in this spec:
diff --git a/ui/gfx/transform_util_unittest.cc b/ui/gfx/transform_util_unittest.cc index 907f8a8..c9fb6d1 100644 --- a/ui/gfx/transform_util_unittest.cc +++ b/ui/gfx/transform_util_unittest.cc
@@ -197,14 +197,19 @@ TEST(TransformUtilTest, BlendOppositeQuaternions) { DecomposedTransform first; DecomposedTransform second; - second.quaternion[3] = -second.quaternion[3]; + second.quaternion.set_w(-second.quaternion.w()); - DecomposedTransform result; - BlendDecomposedTransforms(&result, first, second, 0.25); - for (size_t i = 0; i < 4; ++i) { - EXPECT_TRUE(std::isfinite(result.quaternion[i])); - EXPECT_FALSE(std::isnan(result.quaternion[i])); - } + DecomposedTransform result = BlendDecomposedTransforms(first, second, 0.25); + + EXPECT_TRUE(std::isfinite(result.quaternion.x())); + EXPECT_TRUE(std::isfinite(result.quaternion.y())); + EXPECT_TRUE(std::isfinite(result.quaternion.z())); + EXPECT_TRUE(std::isfinite(result.quaternion.w())); + + EXPECT_FALSE(std::isnan(result.quaternion.x())); + EXPECT_FALSE(std::isnan(result.quaternion.y())); + EXPECT_FALSE(std::isnan(result.quaternion.z())); + EXPECT_FALSE(std::isnan(result.quaternion.w())); } } // namespace
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 5563fe2..3a44167 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc
@@ -109,6 +109,11 @@ #define EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE 0x33A6 #endif /* EGL_ANGLE_flexible_surface_compatibility */ +#ifndef EGL_ANGLE_display_robust_resource_initialization +#define EGL_ANGLE_display_robust_resource_initialization 1 +#define EGL_DISPLAY_ROBUST_RESOURCE_INITIALIZATION_ANGLE 0x3453 +#endif /* EGL_ANGLE_display_robust_resource_initialization */ + using ui::GetLastEGLErrorString; namespace gl { @@ -173,7 +178,8 @@ EGLDisplay GetPlatformANGLEDisplay(EGLNativeDisplayType native_display, EGLenum platform_type, - bool warpDevice) { + bool warpDevice, + bool robustResourceInit) { std::vector<EGLint> display_attribs; display_attribs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE); @@ -184,6 +190,11 @@ display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE); } + if (robustResourceInit) { + display_attribs.push_back(EGL_DISPLAY_ROBUST_RESOURCE_INITIALIZATION_ANGLE); + display_attribs.push_back(EGL_TRUE); + } + #if defined(USE_X11) && !defined(OS_CHROMEOS) // ANGLE_NULL doesn't use the visual, and may run without X11 where we can't // get it anyway. @@ -204,26 +215,32 @@ } EGLDisplay GetDisplayFromType(DisplayType display_type, - EGLNativeDisplayType native_display) { + EGLNativeDisplayType native_display, + bool robustResourceInit) { switch (display_type) { case DEFAULT: case SWIFT_SHADER: return eglGetDisplay(native_display); case ANGLE_D3D9: return GetPlatformANGLEDisplay(native_display, - EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, false); + EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, false, + robustResourceInit); case ANGLE_D3D11: - return GetPlatformANGLEDisplay( - native_display, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, false); + return GetPlatformANGLEDisplay(native_display, + EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, false, + robustResourceInit); case ANGLE_OPENGL: - return GetPlatformANGLEDisplay( - native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, false); + return GetPlatformANGLEDisplay(native_display, + EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE, + false, robustResourceInit); case ANGLE_OPENGLES: - return GetPlatformANGLEDisplay( - native_display, EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, false); + return GetPlatformANGLEDisplay(native_display, + EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE, + false, robustResourceInit); case ANGLE_NULL: return GetPlatformANGLEDisplay(native_display, - EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE, false); + EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE, false, + robustResourceInit); default: NOTREACHED(); return EGL_NO_DISPLAY; @@ -680,6 +697,15 @@ ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_null"); } + bool supports_robust_resource_init = + client_extensions && + ExtensionsContain(client_extensions, + "EGL_ANGLE_display_robust_resource_initialization"); + bool use_robust_resource_init = + supports_robust_resource_init && + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kUsePassthroughCmdDecoderGL); + std::vector<DisplayType> init_displays; GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl, supports_angle_null, @@ -687,8 +713,8 @@ for (size_t disp_index = 0; disp_index < init_displays.size(); ++disp_index) { DisplayType display_type = init_displays[disp_index]; - EGLDisplay display = - GetDisplayFromType(display_type, g_native_display); + EGLDisplay display = GetDisplayFromType(display_type, g_native_display, + use_robust_resource_init); if (display == EGL_NO_DISPLAY) { LOG(ERROR) << "EGL display query failed with error " << GetLastEGLErrorString();
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index ba72048a..27f49c5 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -122,6 +122,11 @@ const char kDisableDirectCompositionLayers[] = "disable-direct-composition-layers"; +// Use the Pass-through command decoder, skipping all validation and state +// tracking. Note: This is the same switch as the one in gpu_switches.cc. It's +// defined here again to avoid dependencies between dlls. +const char kUsePassthroughCmdDecoderGL[] = "use-passthrough-cmd-decoder"; + // This is the list of switches passed from this file that are passed from the // GpuProcessHost to the GPU Process. Add your switch to this list if you need // to read it in the GPU process, else don't add it. @@ -139,6 +144,7 @@ kEnableSwapBuffersWithBounds, kEnableDirectCompositionLayers, kDisableDirectCompositionLayers, + kUsePassthroughCmdDecoderGL, }; const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches = arraysize(kGLSwitchesCopiedFromGpuProcessHost);
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h index 3a1948b..4d6cf34 100644 --- a/ui/gl/gl_switches.h +++ b/ui/gl/gl_switches.h
@@ -57,6 +57,8 @@ GL_EXPORT extern const char kEnableDirectCompositionLayers[]; GL_EXPORT extern const char kDisableDirectCompositionLayers[]; +GL_EXPORT extern const char kUsePassthroughCmdDecoderGL[]; + // These flags are used by the test harness code, not passed in by users. GL_EXPORT extern const char kDisableGLDrawingForTests[]; GL_EXPORT extern const char kOverrideUseSoftwareGLForTests[];
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc index d36a2c31..6711ce93 100644 --- a/ui/native_theme/native_theme_base.cc +++ b/ui/native_theme/native_theme_base.cc
@@ -600,11 +600,11 @@ SkColor colors[3] = {startEndColors[0], startEndColors[0], startEndColors[1]}; cc::PaintFlags flags; flags.setAntiAlias(true); - flags.setShader(cc::WrapSkShader(SkGradientShader::MakeLinear( - gradient_bounds, colors, NULL, 3, SkShader::kClamp_TileMode))); + flags.setShader(cc::PaintShader::MakeLinearGradient( + gradient_bounds, colors, nullptr, 3, SkShader::kClamp_TileMode)); flags.setStyle(cc::PaintFlags::kFill_Style); canvas->drawRoundRect(skrect, borderRadius, borderRadius, flags); - flags.setShader(NULL); + flags.setShader(nullptr); // Draw the border. if (state == kHovered) @@ -681,11 +681,11 @@ flags.setStyle(cc::PaintFlags::kFill_Style); flags.setAntiAlias(true); - flags.setShader(cc::WrapSkShader(SkGradientShader::MakeLinear( - gradient_bounds, colors, NULL, 2, SkShader::kClamp_TileMode))); + flags.setShader(cc::PaintShader::MakeLinearGradient( + gradient_bounds, colors, nullptr, 2, SkShader::kClamp_TileMode)); canvas->drawRoundRect(skrect, SkIntToScalar(1), SkIntToScalar(1), flags); - flags.setShader(NULL); + flags.setShader(nullptr); if (button.has_border) { int border_alpha = state == kHovered ? 0x80 : 0x55;
diff --git a/ui/ozone/public/input_controller.cc b/ui/ozone/public/input_controller.cc index 665472d4..5aa3002 100644 --- a/ui/ozone/public/input_controller.cc +++ b/ui/ozone/public/input_controller.cc
@@ -4,6 +4,7 @@ #include "ui/ozone/public/input_controller.h" +#include "base/callback.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/macros.h" @@ -30,7 +31,7 @@ const base::TimeDelta& interval) override; void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) override; - bool SetCurrentLayoutByName(const std::string& layout_name) override; + void SetCurrentLayoutByName(const std::string& layout_name) override; void SetTouchEventLoggingEnabled(bool enabled) override; void SetTouchpadSensitivity(int value) override; void SetTapToClick(bool enabled) override; @@ -40,9 +41,9 @@ void SetMouseSensitivity(int value) override; void SetPrimaryButtonRight(bool right) override; void SetTapToClickPaused(bool state) override; - void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) override; + void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) override; void GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) override; + GetTouchEventLogReply reply) override; void SetInternalTouchpadEnabled(bool enabled) override; bool IsInternalTouchpadEnabled() const override; void SetTouchscreensEnabled(bool enabled) override; @@ -92,10 +93,8 @@ base::TimeDelta* interval) { } -bool StubInputController::SetCurrentLayoutByName( - const std::string& layout_name) { - return false; -} +void StubInputController::SetCurrentLayoutByName( + const std::string& layout_name) {} void StubInputController::SetTouchpadSensitivity(int value) { } @@ -126,13 +125,13 @@ } void StubInputController::GetTouchDeviceStatus( - const GetTouchDeviceStatusReply& reply) { - reply.Run(std::unique_ptr<std::string>(new std::string)); + GetTouchDeviceStatusReply reply) { + std::move(reply).Run(std::string()); } void StubInputController::GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) { - reply.Run(base::WrapUnique(new std::vector<base::FilePath>)); + GetTouchEventLogReply reply) { + std::move(reply).Run(std::vector<base::FilePath>()); } void StubInputController::SetInternalTouchpadEnabled(bool enabled) {
diff --git a/ui/ozone/public/input_controller.h b/ui/ozone/public/input_controller.h index 3c5e1bcb..cdec1d5 100644 --- a/ui/ozone/public/input_controller.h +++ b/ui/ozone/public/input_controller.h
@@ -10,7 +10,7 @@ #include <string> #include <vector> -#include "base/callback.h" +#include "base/callback_forward.h" #include "base/files/file_path.h" #include "base/macros.h" #include "ui/ozone/ozone_base_export.h" @@ -30,10 +30,11 @@ // script that is originally located at /opt/google/chrome/. class OZONE_BASE_EXPORT InputController { public: - typedef base::Callback<void(std::unique_ptr<std::string>)> - GetTouchDeviceStatusReply; - typedef base::Callback<void(std::unique_ptr<std::vector<base::FilePath>>)> - GetTouchEventLogReply; + using GetTouchDeviceStatusReply = + base::OnceCallback<void(const std::string&)>; + // TODO(sky): convert this to value once mojo supports move for vectors. + using GetTouchEventLogReply = + base::OnceCallback<void(const std::vector<base::FilePath>&)>; InputController() {} virtual ~InputController() {} @@ -52,7 +53,7 @@ const base::TimeDelta& interval) = 0; virtual void GetAutoRepeatRate(base::TimeDelta* delay, base::TimeDelta* interval) = 0; - virtual bool SetCurrentLayoutByName(const std::string& layout_name) = 0; + virtual void SetCurrentLayoutByName(const std::string& layout_name) = 0; // Touchpad settings. virtual void SetTouchpadSensitivity(int value) = 0; @@ -66,9 +67,9 @@ virtual void SetPrimaryButtonRight(bool right) = 0; // Touch log collection. - virtual void GetTouchDeviceStatus(const GetTouchDeviceStatusReply& reply) = 0; + virtual void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) = 0; virtual void GetTouchEventLog(const base::FilePath& out_dir, - const GetTouchEventLogReply& reply) = 0; + GetTouchEventLogReply reply) = 0; // Touchscreen log settings. virtual void SetTouchEventLoggingEnabled(bool enabled) = 0;
diff --git a/ui/views/color_chooser/color_chooser_view.cc b/ui/views/color_chooser/color_chooser_view.cc index 3eb3970..df8d0cf 100644 --- a/ui/views/color_chooser/color_chooser_view.cc +++ b/ui/views/color_chooser/color_chooser_view.cc
@@ -105,8 +105,8 @@ else points[1].iset(0, rect.height() + 1); cc::PaintFlags flags; - flags.setShader(cc::WrapSkShader(SkGradientShader::MakeLinear( - points, colors, NULL, 2, SkShader::kClamp_TileMode))); + flags.setShader(cc::PaintShader::MakeLinearGradient( + points, colors, nullptr, 2, SkShader::kClamp_TileMode)); canvas->DrawRect(rect, flags); }
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm index e9c1dd6..c7e4cd4ac 100644 --- a/ui/views/controls/scrollbar/cocoa_scroll_bar.mm +++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -258,9 +258,9 @@ gradient_bounds[1].set(track_rect.right(), track_rect.y()); } cc::PaintFlags gradient; - gradient.setShader(cc::WrapSkShader(SkGradientShader::MakeLinear( + gradient.setShader(cc::PaintShader::MakeLinearGradient( gradient_bounds, kScrollerTrackGradientColors, nullptr, - arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode))); + arraysize(kScrollerTrackGradientColors), SkShader::kClamp_TileMode)); canvas->DrawRect(track_rect, gradient); // Draw the inner border: top if horizontal, left if vertical.
diff --git a/ui/views/view.cc b/ui/views/view.cc index e62c3951..6d1e20b 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -1863,10 +1863,9 @@ decomp.translate[1]); result.append(bounds_buffer); - base::snprintf(bounds_buffer, - arraysize(bounds_buffer), + base::snprintf(bounds_buffer, arraysize(bounds_buffer), "\\n rotation: %3.2f", - std::acos(decomp.quaternion[3]) * 360.0 / M_PI); + std::acos(decomp.quaternion.w()) * 360.0 / M_PI); result.append(bounds_buffer); base::snprintf(bounds_buffer,