diff --git a/DEPS b/DEPS index 6a93a209..837694af 100644 --- a/DEPS +++ b/DEPS
@@ -44,7 +44,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '403eccb02dc501ac8f04a1e856e5c2094afb6b57', + 'v8_revision': '228237cf81b29d4f3b67aa8bd8172442726b4d1f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -64,7 +64,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'c62980ec7539fa5ae2065ba5f287aada3a814173', + 'pdfium_revision': '02759102cf998c9e937b3b65b64ed6b4c3b104bc', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -96,7 +96,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '852f85163d54de6b721860a94ae23c608a3efa64', + 'catapult_revision': 'da3aa694af9729a870e1837d7cbeebb38bd64063', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -224,7 +224,7 @@ Var('chromium_git') + '/native_client/src/third_party/scons-2.0.1.git' + '@' + '1c1550e17fc26355d08627fbdec13d8291227067', 'src/third_party/webrtc': - Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '61e42daeed24f321ca66a0a566c53e39485dcd39', # commit position 15323 + Var('chromium_git') + '/external/webrtc/trunk/webrtc.git' + '@' + '42ad2d474da82fbcb90a432d463a765dee22fad1', # commit position 15358 'src/third_party/openmax_dl': Var('chromium_git') + '/external/webrtc/deps/third_party/openmax.git' + '@' + Var('openmax_dl_revision'),
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc index 5c4d9578..067e238 100644 --- a/ash/wm/toplevel_window_event_handler.cc +++ b/ash/wm/toplevel_window_event_handler.cc
@@ -5,7 +5,9 @@ #include "ash/wm/toplevel_window_event_handler.h" #include "ash/aura/wm_window_aura.h" +#include "ash/common/wm/window_state.h" #include "ash/shell.h" +#include "ash/wm/window_state_aura.h" #include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "ui/aura/client/cursor_client.h" @@ -87,11 +89,19 @@ base::MessageLoop* loop = base::MessageLoop::current(); base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop); + // Disable window position auto management while dragging and restore it + // aftrewards. + wm::WindowState* window_state = wm::GetWindowState(source); + const bool window_position_managed = window_state->window_position_managed(); + window_state->set_window_position_managed(false); + run_loop.Run(); if (!weak_ptr) return aura::client::MOVE_CANCELED; + window_state->set_window_position_managed(window_position_managed); + in_move_loop_ = false; return result == wm::WmToplevelWindowEventHandler::DragResult::SUCCESS ? aura::client::MOVE_SUCCESSFUL
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc index 06610b6..ba89155 100644 --- a/ash/wm/toplevel_window_event_handler_unittest.cc +++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -113,6 +113,67 @@ namespace { +void ContinueAndCompleteDrag(ui::test::EventGenerator* generator, + wm::WindowState* window_state, + aura::Window* window) { + ASSERT_TRUE(window->HasCapture()); + ASSERT_FALSE(window_state->window_position_managed()); + generator->DragMouseBy(100, 100); + generator->ReleaseLeftButton(); +} + +} // namespace + +// Tests dragging restores expected window position auto manage property +// correctly. +TEST_F(ToplevelWindowEventHandlerTest, WindowPositionAutoManagement) { + std::unique_ptr<aura::Window> w1(CreateWindow(HTNOWHERE)); + const gfx::Size size = w1->bounds().size(); + wm::WindowState* window_state = ash::wm::GetWindowState(w1.get()); + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), w1.get()); + + // Explicitly enable window position auto management, and expect it to be + // restored after drag completes. + window_state->set_window_position_managed(true); + generator.PressLeftButton(); + aura::client::WindowMoveClient* move_client = + aura::client::GetWindowMoveClient(w1->GetRootWindow()); + // generator.PressLeftButton(); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ContinueAndCompleteDrag, base::Unretained(&generator), + base::Unretained(window_state), base::Unretained(w1.get()))); + EXPECT_EQ(aura::client::MOVE_SUCCESSFUL, + move_client->RunMoveLoop(w1.get(), gfx::Vector2d(100, 100), + aura::client::WINDOW_MOVE_SOURCE_MOUSE)); + // Window position auto manage property should be restored to true. + EXPECT_TRUE(window_state->window_position_managed()); + // Position should have been offset by 100,100. + EXPECT_EQ("100,100", w1->bounds().origin().ToString()); + // Size should remain the same. + EXPECT_EQ(size.ToString(), w1->bounds().size().ToString()); + + // Explicitly disable window position auto management, and expect it to be + // restored after drag completes. + window_state->set_window_position_managed(false); + generator.PressLeftButton(); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::Bind(&ContinueAndCompleteDrag, base::Unretained(&generator), + base::Unretained(window_state), base::Unretained(w1.get()))); + EXPECT_EQ(aura::client::MOVE_SUCCESSFUL, + move_client->RunMoveLoop(w1.get(), gfx::Vector2d(100, 100), + aura::client::WINDOW_MOVE_SOURCE_MOUSE)); + // Window position auto manage property should be restored to true. + EXPECT_FALSE(window_state->window_position_managed()); + // Position should have been offset by 100,100. + EXPECT_EQ("200,200", w1->bounds().origin().ToString()); + // Size should remain the same. + EXPECT_EQ(size.ToString(), w1->bounds().size().ToString()); +} + +namespace { + class CancelDragObserver : public aura::WindowObserver { public: CancelDragObserver() {}
diff --git a/base/android/jni_generator/BUILD.gn b/base/android/jni_generator/BUILD.gn index 1741e51..12c0c39 100644 --- a/base/android/jni_generator/BUILD.gn +++ b/base/android/jni_generator/BUILD.gn
@@ -11,7 +11,7 @@ "jni_generator.py", "jni_generator_tests.py", "java/src/org/chromium/example/jni_generator/SampleForTests.java", - "golden_sample_for_tests_jni.h", + "SampleForTests_jni.golden", ] outputs = [ _stamp,
diff --git a/base/android/jni_generator/golden_sample_for_tests_jni.h b/base/android/jni_generator/SampleForTests_jni.golden similarity index 94% rename from base/android/jni_generator/golden_sample_for_tests_jni.h rename to base/android/jni_generator/SampleForTests_jni.golden index 94fc6b0..6fdced2 100644 --- a/base/android/jni_generator/golden_sample_for_tests_jni.h +++ b/base/android/jni_generator/SampleForTests_jni.golden
@@ -50,19 +50,17 @@ jcaller, const base::android::JavaParamRef<jstring>& param); -extern "C" __attribute__((visibility("default"))) -jlong Java_org_chromium_example_jni_1generator_SampleForTests_nativeInit(JNIEnv* +JNI_GENERATOR_EXPORT jlong + Java_org_chromium_example_jni_1generator_SampleForTests_nativeInit(JNIEnv* env, jobject jcaller, jstring param) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller), base::android::JavaParamRef<jstring>(env, param)); } -extern "C" __attribute__((visibility("default"))) -void +JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeDestroy(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeCPPClass) { CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CHECK_NATIVE_PTR(env, jcaller, native, "Destroy"); @@ -73,8 +71,7 @@ static jdouble GetDoubleFunction(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jdouble +JNI_GENERATOR_EXPORT jdouble Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetDoubleFunction(JNIEnv* env, jobject jcaller) { return GetDoubleFunction(env, base::android::JavaParamRef<jobject>(env, @@ -84,8 +81,7 @@ static jfloat GetFloatFunction(JNIEnv* env, const base::android::JavaParamRef<jclass>& jcaller); -extern "C" __attribute__((visibility("default"))) -jfloat +JNI_GENERATOR_EXPORT jfloat Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetFloatFunction(JNIEnv* env, jclass jcaller) { return GetFloatFunction(env, base::android::JavaParamRef<jclass>(env, @@ -96,8 +92,7 @@ base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jobject>& rect); -extern "C" __attribute__((visibility("default"))) -void +JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeSetNonPODDatatype(JNIEnv* env, jobject jcaller, jobject rect) { @@ -108,19 +103,16 @@ static base::android::ScopedJavaLocalRef<jobject> GetNonPODDatatype(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jobject +JNI_GENERATOR_EXPORT jobject Java_org_chromium_example_jni_1generator_SampleForTests_nativeGetNonPODDatatype(JNIEnv* env, jobject jcaller) { return GetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env, jcaller)).Release(); } -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethod(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeCPPClass) { CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0); @@ -128,11 +120,9 @@ jcaller)); } -extern "C" __attribute__((visibility("default"))) -jdouble +JNI_GENERATOR_EXPORT jdouble Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethodOtherP0(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativePtr) { CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); @@ -141,11 +131,9 @@ jcaller)); } -extern "C" __attribute__((visibility("default"))) -void +JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeAddStructB(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeCPPClass, jobject b) { CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); @@ -154,11 +142,9 @@ jcaller), base::android::JavaParamRef<jobject>(env, b)); } -extern "C" __attribute__((visibility("default"))) -void +JNI_GENERATOR_EXPORT void Java_org_chromium_example_jni_1generator_SampleForTests_nativeIterateAndDoSomethingWithStructB(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeCPPClass) { CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB"); @@ -166,11 +152,9 @@ base::android::JavaParamRef<jobject>(env, jcaller)); } -extern "C" __attribute__((visibility("default"))) -jstring +JNI_GENERATOR_EXPORT jstring Java_org_chromium_example_jni_1generator_SampleForTests_nativeReturnAString(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeCPPClass) { CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", NULL); @@ -181,8 +165,7 @@ static jint GetInnerIntFunction(JNIEnv* env, const base::android::JavaParamRef<jclass>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_00024InnerClass_nativeGetInnerIntFunction(JNIEnv* env, jclass jcaller) { return GetInnerIntFunction(env, base::android::JavaParamRef<jclass>(env,
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index 428c493..0173a2c 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py
@@ -1031,9 +1031,7 @@ 'P0_TYPE': native.p0_type, }) template = Template("""\ -extern "C" __attribute__((visibility("default"))) -${RETURN} ${STUB_NAME}(JNIEnv* env, - ${PARAMS_IN_STUB}) { +JNI_GENERATOR_EXPORT ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { ${PROFILING_ENTERED_NATIVE} ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); @@ -1044,8 +1042,7 @@ template = Template(""" static ${RETURN_DECLARATION} ${NAME}(JNIEnv* env, ${PARAMS}); -extern "C" __attribute__((visibility("default"))) -${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { +JNI_GENERATOR_EXPORT ${RETURN} ${STUB_NAME}(JNIEnv* env, ${PARAMS_IN_STUB}) { ${PROFILING_ENTERED_NATIVE} return ${NAME}(${PARAMS_IN_CALL})${POST_CALL}; }
diff --git a/base/android/jni_generator/jni_generator_helper.h b/base/android/jni_generator/jni_generator_helper.h index 56a2ec8..4c159c0 100644 --- a/base/android/jni_generator/jni_generator_helper.h +++ b/base/android/jni_generator/jni_generator_helper.h
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - #ifndef BASE_ANDROID_JNI_GENERATOR_JNI_GENERATOR_HELPER_H_ #define BASE_ANDROID_JNI_GENERATOR_JNI_GENERATOR_HELPER_H_ @@ -11,26 +10,37 @@ #include "base/android/jni_android.h" #include "base/android/scoped_java_ref.h" #include "base/logging.h" +#include "build/build_config.h" // Project-specific macros used by the header files generated by // jni_generator.py. Different projects can then specify their own // implementation for this file. #define CHECK_NATIVE_PTR(env, jcaller, native_ptr, method_name, ...) \ - DCHECK(native_ptr) << method_name; + DCHECK(native_ptr) << method_name; -#define CHECK_CLAZZ(env, jcaller, clazz, ...) \ - DCHECK(clazz); +#define CHECK_CLAZZ(env, jcaller, clazz, ...) DCHECK(clazz); + +#if defined(ARCH_CPU_X86) +// Dalvik JIT generated code doesn't guarantee 16-byte stack alignment on +// x86 - use force_align_arg_pointer to realign the stack at the JNI +// boundary. crbug.com/655248 +#define JNI_GENERATOR_EXPORT \ + extern "C" __attribute__((visibility("default"), force_align_arg_pointer)) +#else +#define JNI_GENERATOR_EXPORT extern "C" __attribute__((visibility("default"))) +#endif namespace jni_generator { - inline void HandleRegistrationError(JNIEnv* env, jclass clazz, - const char* filename) { - LOG(ERROR) << "RegisterNatives failed in " << filename; - } +inline void HandleRegistrationError(JNIEnv* env, + jclass clazz, + const char* filename) { + LOG(ERROR) << "RegisterNatives failed in " << filename; +} - inline void CheckException(JNIEnv* env) { - base::android::CheckException(env); - } +inline void CheckException(JNIEnv* env) { + base::android::CheckException(env); +} } // namespace jni_generator
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index 9c066ce..022f043 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -834,7 +834,7 @@ content = file(os.path.join(script_dir, 'java/src/org/chromium/example/jni_generator/SampleForTests.java') ).read() - golden_file = os.path.join(script_dir, 'golden_sample_for_tests_jni.h') + golden_file = os.path.join(script_dir, 'SampleForTests_jni.golden') golden_content = file(golden_file).read() jni_from_java = jni_generator.JNIFromJavaSource( content, 'org/chromium/example/jni_generator/SampleForTests',
diff --git a/base/android/jni_generator/testInnerClassNatives.golden b/base/android/jni_generator/testInnerClassNatives.golden index fc68bc8..68ed943 100644 --- a/base/android/jni_generator/testInnerClassNatives.golden +++ b/base/android/jni_generator/testInnerClassNatives.golden
@@ -34,8 +34,8 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject +JNI_GENERATOR_EXPORT jint + Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); }
diff --git a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden b/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden index 554b37a..0d7b93e 100644 --- a/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden +++ b/base/android/jni_generator/testInnerClassNativesBothInnerAndOuter.golden
@@ -35,16 +35,16 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, jobject jcaller) { +JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, + jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); } static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, +JNI_GENERATOR_EXPORT jint + Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); }
diff --git a/base/android/jni_generator/testInnerClassNativesMultiple.golden b/base/android/jni_generator/testInnerClassNativesMultiple.golden index 9ad94db8..8f37c68 100644 --- a/base/android/jni_generator/testInnerClassNativesMultiple.golden +++ b/base/android/jni_generator/testInnerClassNativesMultiple.golden
@@ -39,8 +39,8 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject +JNI_GENERATOR_EXPORT jint + Java_org_chromium_TestJni_00024MyInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); } @@ -48,8 +48,8 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, +JNI_GENERATOR_EXPORT jint + Java_org_chromium_TestJni_00024MyOtherInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); }
diff --git a/base/android/jni_generator/testMultipleJNIAdditionalImport.golden b/base/android/jni_generator/testMultipleJNIAdditionalImport.golden index bf4679c0..dfeebc11 100644 --- a/base/android/jni_generator/testMultipleJNIAdditionalImport.golden +++ b/base/android/jni_generator/testMultipleJNIAdditionalImport.golden
@@ -32,8 +32,8 @@ const base::android::JavaParamRef<jobject>& callback1, const base::android::JavaParamRef<jobject>& callback2); -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* env, jclass jcaller, +JNI_GENERATOR_EXPORT void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* + env, jclass jcaller, jobject callback1, jobject callback2) { return DoSomething(env, base::android::JavaParamRef<jclass>(env, jcaller),
diff --git a/base/android/jni_generator/testNativeExportsOnlyOption.golden b/base/android/jni_generator/testNativeExportsOnlyOption.golden index 901816c9..6a50619 100644 --- a/base/android/jni_generator/testNativeExportsOnlyOption.golden +++ b/base/android/jni_generator/testNativeExportsOnlyOption.golden
@@ -27,11 +27,9 @@ } // namespace // Step 2: method stubs. -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeStaticMethod(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeTest, jint arg1) { Test* native = reinterpret_cast<Test*>(nativeTest); @@ -40,11 +38,9 @@ jcaller), arg1); } -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_nativeMethod(JNIEnv* - env, - jobject jcaller, + env, jobject jcaller, jlong nativeTest, jint arg1) { Test* native = reinterpret_cast<Test*>(nativeTest); @@ -56,8 +52,7 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_00024MyInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); @@ -66,8 +61,7 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint +JNI_GENERATOR_EXPORT jint Java_org_chromium_example_jni_1generator_SampleForTests_00024MyOtherInnerClass_nativeInit(JNIEnv* env, jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller));
diff --git a/base/android/jni_generator/testNatives.golden b/base/android/jni_generator/testNatives.golden index e2f64cd..2399cd7 100644 --- a/base/android/jni_generator/testNatives.golden +++ b/base/android/jni_generator/testNatives.golden
@@ -30,13 +30,12 @@ static jint Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, jobject jcaller) { +JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeInit(JNIEnv* env, + jobject jcaller) { return Init(env, base::android::JavaParamRef<jobject>(env, jcaller)); } -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, +JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, jobject jcaller, jint nativeChromeBrowserProvider) { ChromeBrowserProvider* native = @@ -46,9 +45,8 @@ jcaller)); } -extern "C" __attribute__((visibility("default"))) -jlong Java_org_chromium_TestJni_nativeAddBookmark(JNIEnv* env, - jobject jcaller, +JNI_GENERATOR_EXPORT jlong Java_org_chromium_TestJni_nativeAddBookmark(JNIEnv* + env, jobject jcaller, jint nativeChromeBrowserProvider, jstring url, jstring title, @@ -66,8 +64,8 @@ env, const base::android::JavaParamRef<jclass>& jcaller, const base::android::JavaParamRef<jstring>& url); -extern "C" __attribute__((visibility("default"))) -jstring Java_org_chromium_TestJni_nativeGetDomainAndRegistry(JNIEnv* env, jclass +JNI_GENERATOR_EXPORT jstring + Java_org_chromium_TestJni_nativeGetDomainAndRegistry(JNIEnv* env, jclass jcaller, jstring url) { return GetDomainAndRegistry(env, base::android::JavaParamRef<jclass>(env, @@ -79,8 +77,8 @@ const base::android::JavaParamRef<jbyteArray>& state, jint tab_index); -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_TestJni_nativeCreateHistoricalTabFromState(JNIEnv* env, +JNI_GENERATOR_EXPORT void + Java_org_chromium_TestJni_nativeCreateHistoricalTabFromState(JNIEnv* env, jclass jcaller, jbyteArray state, jint tab_index) { @@ -93,9 +91,9 @@ env, const base::android::JavaParamRef<jobject>& jcaller, const base::android::JavaParamRef<jobject>& view); -extern "C" __attribute__((visibility("default"))) -jbyteArray Java_org_chromium_TestJni_nativeGetStateAsByteArray(JNIEnv* env, - jobject jcaller, +JNI_GENERATOR_EXPORT jbyteArray + Java_org_chromium_TestJni_nativeGetStateAsByteArray(JNIEnv* env, jobject + jcaller, jobject view) { return GetStateAsByteArray(env, base::android::JavaParamRef<jobject>(env, jcaller), base::android::JavaParamRef<jobject>(env, view)).Release(); @@ -105,9 +103,9 @@ GetAutofillProfileGUIDs(JNIEnv* env, const base::android::JavaParamRef<jclass>& jcaller); -extern "C" __attribute__((visibility("default"))) -jobjectArray Java_org_chromium_TestJni_nativeGetAutofillProfileGUIDs(JNIEnv* - env, jclass jcaller) { +JNI_GENERATOR_EXPORT jobjectArray + Java_org_chromium_TestJni_nativeGetAutofillProfileGUIDs(JNIEnv* env, jclass + jcaller) { return GetAutofillProfileGUIDs(env, base::android::JavaParamRef<jclass>(env, jcaller)).Release(); } @@ -117,8 +115,8 @@ jint sessionId, const base::android::JavaParamRef<jobjectArray>& results); -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_TestJni_nativeSetRecognitionResults(JNIEnv* env, jobject +JNI_GENERATOR_EXPORT void + Java_org_chromium_TestJni_nativeSetRecognitionResults(JNIEnv* env, jobject jcaller, jint sessionId, jobjectArray results) { @@ -127,9 +125,9 @@ results)); } -extern "C" __attribute__((visibility("default"))) -jlong Java_org_chromium_TestJni_nativeAddBookmarkFromAPI(JNIEnv* env, - jobject jcaller, +JNI_GENERATOR_EXPORT jlong + Java_org_chromium_TestJni_nativeAddBookmarkFromAPI(JNIEnv* env, jobject + jcaller, jint nativeChromeBrowserProvider, jstring url, jobject created, @@ -156,8 +154,8 @@ jcaller, const base::android::JavaParamRef<jstring>& find); -extern "C" __attribute__((visibility("default"))) -jint Java_org_chromium_TestJni_nativeFindAll(JNIEnv* env, jobject jcaller, +JNI_GENERATOR_EXPORT jint Java_org_chromium_TestJni_nativeFindAll(JNIEnv* env, + jobject jcaller, jstring find) { return FindAll(env, base::android::JavaParamRef<jobject>(env, jcaller), base::android::JavaParamRef<jstring>(env, find)); @@ -166,16 +164,14 @@ static base::android::ScopedJavaLocalRef<jobject> GetInnerClass(JNIEnv* env, const base::android::JavaParamRef<jclass>& jcaller); -extern "C" __attribute__((visibility("default"))) -jobject Java_org_chromium_TestJni_nativeGetInnerClass(JNIEnv* env, jclass - jcaller) { +JNI_GENERATOR_EXPORT jobject + Java_org_chromium_TestJni_nativeGetInnerClass(JNIEnv* env, jclass jcaller) { return GetInnerClass(env, base::android::JavaParamRef<jclass>(env, jcaller)).Release(); } -extern "C" __attribute__((visibility("default"))) -jobject Java_org_chromium_TestJni_nativeQueryBitmap(JNIEnv* env, - jobject jcaller, +JNI_GENERATOR_EXPORT jobject Java_org_chromium_TestJni_nativeQueryBitmap(JNIEnv* + env, jobject jcaller, jint nativeChromeBrowserProvider, jobjectArray projection, jstring selection, @@ -191,9 +187,8 @@ base::android::JavaParamRef<jstring>(env, sortOrder)).Release(); } -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_TestJni_nativeGotOrientation(JNIEnv* env, - jobject jcaller, +JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeGotOrientation(JNIEnv* + env, jobject jcaller, jint nativeDataFetcherImplAndroid, jdouble alpha, jdouble beta, @@ -210,9 +205,9 @@ base::android::JavaParamRef<jclass>& jcaller, const base::android::JavaParamRef<jthrowable>& e); -extern "C" __attribute__((visibility("default"))) -jthrowable Java_org_chromium_TestJni_nativeMessWithJavaException(JNIEnv* env, - jclass jcaller, +JNI_GENERATOR_EXPORT jthrowable + Java_org_chromium_TestJni_nativeMessWithJavaException(JNIEnv* env, jclass + jcaller, jthrowable e) { return MessWithJavaException(env, base::android::JavaParamRef<jclass>(env, jcaller), base::android::JavaParamRef<jthrowable>(env, e)).Release();
diff --git a/base/android/jni_generator/testNativesLong.golden b/base/android/jni_generator/testNativesLong.golden index 9dddf2fe4..12a153e 100644 --- a/base/android/jni_generator/testNativesLong.golden +++ b/base/android/jni_generator/testNativesLong.golden
@@ -26,8 +26,7 @@ } // namespace // Step 2: method stubs. -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, +JNI_GENERATOR_EXPORT void Java_org_chromium_TestJni_nativeDestroy(JNIEnv* env, jobject jcaller, jlong nativeChromeBrowserProvider) { ChromeBrowserProvider* native =
diff --git a/base/android/jni_generator/testSingleJNIAdditionalImport.golden b/base/android/jni_generator/testSingleJNIAdditionalImport.golden index cd11925..1f5ac11 100644 --- a/base/android/jni_generator/testSingleJNIAdditionalImport.golden +++ b/base/android/jni_generator/testSingleJNIAdditionalImport.golden
@@ -31,8 +31,8 @@ jcaller, const base::android::JavaParamRef<jobject>& callback); -extern "C" __attribute__((visibility("default"))) -void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* env, jclass jcaller, +JNI_GENERATOR_EXPORT void Java_org_chromium_foo_Foo_nativeDoSomething(JNIEnv* + env, jclass jcaller, jobject callback) { return DoSomething(env, base::android::JavaParamRef<jclass>(env, jcaller), base::android::JavaParamRef<jobject>(env, callback));
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py index 7b346cf..926f275f 100755 --- a/build/android/gyp/javac.py +++ b/build/android/gyp/javac.py
@@ -4,6 +4,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import distutils.spawn import optparse import os import shutil @@ -319,6 +320,13 @@ for arg in options.bootclasspath: bootclasspath += build_utils.ParseGnList(arg) options.bootclasspath = bootclasspath + if options.java_version == '1.8' and options.bootclasspath: + # Android's boot jar doesn't contain all java 8 classes. + # See: https://github.com/evant/gradle-retrolambda/issues/23. + javac_path = os.path.realpath(distutils.spawn.find_executable('javac')) + jdk_dir = os.path.dirname(os.path.dirname(javac_path)) + rt_jar = os.path.join(jdk_dir, 'jre', 'lib', 'rt.jar') + options.bootclasspath.append(rt_jar) classpath = [] for arg in options.classpath:
diff --git a/build/android/gyp/retrolambda.py b/build/android/gyp/retrolambda.py new file mode 100755 index 0000000..158ed52 --- /dev/null +++ b/build/android/gyp/retrolambda.py
@@ -0,0 +1,68 @@ +#!/usr/bin/env python +# +# Copyright 2016 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 argparse +import os +import shutil +import sys +import tempfile + +from util import build_utils + + +_SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), + '..', '..', '..')) +_RETROLAMBDA_JAR_PATH = os.path.normpath(os.path.join( + _SRC_ROOT, 'third_party', 'retrolambda', 'retrolambda-2.3.0.jar')) + + +def _OnStaleMd5(input_jar, output_jar, classpath, android_sdk_jar): + with build_utils.TempDir() as temp_dir: + build_utils.ExtractAll(input_jar, path=temp_dir) + cmd = [ + 'java', + '-Dretrolambda.inputDir=' + temp_dir, + '-Dretrolambda.classpath=' + + ':'.join([temp_dir] + classpath + [android_sdk_jar]), + '-javaagent:' + _RETROLAMBDA_JAR_PATH, + '-jar', + _RETROLAMBDA_JAR_PATH, + ] + + build_utils.CheckOutput(cmd, print_stdout=False) + build_utils.ZipDir(output_jar + '.tmp', temp_dir) + shutil.move(output_jar + '.tmp', output_jar) + + +def main(): + args = build_utils.ExpandFileArgs(sys.argv[1:]) + parser = argparse.ArgumentParser() + build_utils.AddDepfileOption(parser) + parser.add_argument('--input-jar', required=True, + help='Jar input path to include .class files from.') + parser.add_argument('--output-jar', required=True, + help='Jar output path.') + parser.add_argument('--classpath', required=True, + help='Classpath.') + parser.add_argument('--android-sdk-jar', required=True, + help='Android sdk jar path.') + options = parser.parse_args(args) + + options.classpath = build_utils.ParseGnList(options.classpath) + input_paths = options.classpath + [options.input_jar] + output_paths = [options.output_jar] + + build_utils.CallAndWriteDepfileIfStale( + lambda: _OnStaleMd5(options.input_jar, options.output_jar, + options.classpath, options.android_sdk_jar), + options, + input_paths=input_paths, + input_strings=[], + output_paths=output_paths) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/build/config/android/config.gni b/build/config/android/config.gni index 74c66118..d5948f2 100644 --- a/build/config/android/config.gni +++ b/build/config/android/config.gni
@@ -132,7 +132,7 @@ # Required for Android M+ due to SELinux policies (stronger sandboxing). disable_incremental_isolated_processes = false - # Speed up incremental compiles by compiling only changed files. + # Speeds up incremental compiles by compiling only changed files. enable_incremental_javac = false # Adds intrumentation to each function. Writes a file with the order that @@ -142,6 +142,10 @@ # Builds secondary abi for APKs, supports build 32-bit arch as secondary # abi in 64-bit Monochrome and WebView. build_apk_secondary_abi = true + + # Enables java8 language features (via retrolambda). + # work-in-progress (http://crbug.com/642600) + use_java8 = false } # We need a second declare_args block to make sure we are using the overridden
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index f08b6cd3..27b736f3 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -418,7 +418,7 @@ } } -# Generates a script in the output bin directory which runs the test +# Generates a script in the build bin directory which runs the test # target using the test runner script in build/android/test_runner.py. template("test_runner_script") { testonly = true @@ -823,10 +823,10 @@ } } - # Generates a script in the output bin.java directory to run a java binary. + # Generates a script in the build bin directory to run a java binary. # # Variables - # main_class: The class containing the progam entry point. + # main_class: The class containing the program entry point. # jar_path: The path to the jar to run. # script_name: Name of the script to generate. # build_config: Path to .build_config for the jar (contains classpath). @@ -1004,9 +1004,6 @@ _input_jar_path = invoker.input_jar_path _output_jar_path = invoker.output_jar_path - _proguard_preprocess = - defined(invoker.proguard_preprocess) && invoker.proguard_preprocess - _jar_excluded_patterns = [] if (defined(invoker.jar_excluded_patterns)) { _jar_excluded_patterns = invoker.jar_excluded_patterns @@ -1015,56 +1012,65 @@ invoker.strip_resource_classes _filter_jar = _jar_excluded_patterns != [] || _strip_resource_classes + _proguard_preprocess = + defined(invoker.proguard_preprocess) && invoker.proguard_preprocess + _enable_assert = defined(invoker.supports_android) && invoker.supports_android && (is_java_debug || dcheck_always_on) - assert(_enable_assert || true) # Mark used. + + _retrolambda = defined(invoker.supports_android) && + invoker.supports_android && use_java8 + + _deps = [] + _previous_output_jar = _input_jar_path if (_filter_jar) { _filter_target = "${target_name}__filter" + _filter_input_jar = _previous_output_jar + _filter_output_jar = "$target_out_dir/$target_name-filtered.jar" - _filter_jar_path = "$target_out_dir/$target_name-filtered.jar" action(_filter_target) { script = "//build/android/gyp/jar.py" - forward_variables_from(invoker, - [ - "deps", - "public_deps", - ]) + deps = _deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + if (defined(invoker.public_deps)) { + public_deps = invoker.public_deps + } inputs = [ _build_config, - _input_jar_path, + _filter_input_jar, ] outputs = [ - _filter_jar_path, + _filter_output_jar, ] args = [ "--input-jar", - rebase_path(_input_jar_path, root_build_dir), + rebase_path(_filter_input_jar, root_build_dir), "--jar-path", - rebase_path(_filter_jar_path, root_build_dir), + rebase_path(_filter_output_jar, root_build_dir), "--excluded-classes=$_jar_excluded_patterns", ] if (_strip_resource_classes) { args += [ "--strip-resource-classes-for=@FileArg($_rebased_build_config:javac:resource_packages)" ] } } + + _deps = [] + _deps = [ ":$_filter_target" ] + _previous_output_jar = _filter_output_jar } if (_proguard_preprocess) { - _output_jar_target = "${target_name}__proguard_process" - _proguard_output_jar = _output_jar_path + _proguard_target = "${target_name}__proguard_process" + _proguard_input_jar = _previous_output_jar + _proguard_output_jar = "$target_out_dir/$target_name-proguarded.jar" _proguard_config_path = invoker.proguard_preprocess_config - proguard(_output_jar_target) { - if (_filter_jar) { - _proguard_input_jar = _filter_jar_path - deps = [ - ":$_filter_target", - ] - } else { - _proguard_input_jar = _input_jar_path - deps = [] - } + + proguard(_proguard_target) { + deps = _deps if (defined(invoker.deps)) { deps += invoker.deps } @@ -1088,20 +1094,23 @@ "--classpath=@FileArg($_rebased_build_config:javac:classpath)", ] } - } else if (_enable_assert) { - _output_jar_target = "${target_name}__assert" - _assert_output_jar = _output_jar_path - action(_output_jar_target) { - script = "$root_out_dir/bin/helper/java_assertion_enabler" + + _deps = [] + _deps = [ ":$_proguard_target" ] + _previous_output_jar = _proguard_output_jar + } + + if (_enable_assert) { + _assert_target = "${target_name}__assert" + _assert_input_jar = _previous_output_jar + _assert_output_jar = "$target_out_dir/$target_name-asserted.jar" + + action(_assert_target) { + script = "$root_build_dir/bin/helper/java_assertion_enabler" deps = [ "//build/android/java_assertion_enabler($default_toolchain)", ] - if (_filter_jar) { - _assert_input_jar = _filter_jar_path - deps += [ ":$_filter_target" ] - } else { - _assert_input_jar = _input_jar_path - } + deps += _deps if (defined(invoker.deps)) { deps += invoker.deps } @@ -1119,31 +1128,65 @@ rebase_path(_assert_output_jar, root_build_dir), ] } - } else { - _output_jar_target = "${target_name}__copy" - copy(_output_jar_target) { - if (_filter_jar) { - _copy_input_jar = _filter_jar_path - public_deps = [ - ":$_filter_target", - ] - } else { - _copy_input_jar = _input_jar_path - public_deps = [] - } + + _deps = [] + _deps = [ ":$_assert_target" ] + _previous_output_jar = _assert_output_jar + } + + if (_retrolambda) { + _retrolambda_target = "${target_name}__retrolambda" + _retrolambda_input_jar = _previous_output_jar + _retrolambda_output_jar = "$target_out_dir/$target_name-retrolambda.jar" + + android_sdk_jar = "$android_sdk/android.jar" + action(_retrolambda_target) { + script = "//build/android/gyp/retrolambda.py" + deps = _deps if (defined(invoker.deps)) { - deps = invoker.deps + deps += invoker.deps } if (defined(invoker.public_deps)) { - public_deps += invoker.public_deps + public_deps = invoker.public_deps } - sources = [ - _copy_input_jar, + inputs = [ + _build_config, + _retrolambda_input_jar, ] outputs = [ - _output_jar_path, + _retrolambda_output_jar, + ] + args = [ + "--input-jar", + rebase_path(_retrolambda_input_jar, root_build_dir), + "--output-jar", + rebase_path(_retrolambda_output_jar, root_build_dir), + "--classpath=@FileArg($_rebased_build_config:javac:classpath)", + "--android-sdk-jar", + rebase_path(android_sdk_jar, root_build_dir), ] } + + _deps = [] + _deps = [ ":$_retrolambda_target" ] + _previous_output_jar = _retrolambda_output_jar + } + + _output_jar_target = "${target_name}__copy" + copy(_output_jar_target) { + deps = _deps + if (defined(invoker.deps)) { + deps += invoker.deps + } + if (defined(invoker.public_deps)) { + public_deps = invoker.public_deps + } + sources = [ + _previous_output_jar, + ] + outputs = [ + _output_jar_path, + ] } group(target_name) { @@ -2083,7 +2126,9 @@ rebase_path(_android_sdk_ijar, root_build_dir) args += [ "--bootclasspath=$_rebased_android_sdk_ijar" ] } - if (_supports_android) { + if (use_java8) { + args += [ "--java-version=1.8" ] + } else if (_supports_android) { args += [ "--java-version=1.7" ] } foreach(e, _manifest_entries) {
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 89197fa..0f18914 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -1160,6 +1160,9 @@ # will be added to the javac classpath. # jar_path: Path to the prebuilt jar. # jar_dep: Target that builds jar_path (optional). + # main_class: When specified, a wrapper script is created within + # $root_build_dir/bin to launch the binary with the given class as the + # entrypoint. # output_name: File name for the output .jar (not including extension). # Defaults to the input .jar file name. # proguard_preprocess: If true, proguard preprocessing will be run. This can
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java index 99cd55d..fdeb00f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
@@ -473,6 +473,9 @@ } private void startMarginAnimation(boolean enter, boolean showIncognito) { + // Any outstanding animations must be cancelled to avoid race condition. + cancelAnimation(this, Property.INNER_MARGIN_PERCENT); + float start = mInnerMarginPercent; float end = enter && showIncognito ? 1.0f : 0.0f; if (start != end) { @@ -481,6 +484,9 @@ } private void startYOffsetAnimation(boolean enter) { + // Any outstanding animations must be cancelled to avoid race condition. + cancelAnimation(this, Property.STACK_OFFSET_Y_PERCENT); + float start = mStackOffsetYPercent; float end = enter ? 1.f : 0.f; if (start != end) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java index d98be03c..d58f31f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationService.java
@@ -51,13 +51,9 @@ * Chrome gets killed. */ public class DownloadNotificationService extends Service { - static final String EXTRA_DOWNLOAD_NOTIFICATION_ID = "DownloadNotificationId"; static final String EXTRA_DOWNLOAD_GUID = "DownloadGuid"; - static final String EXTRA_DOWNLOAD_FILE_NAME = "DownloadFileName"; static final String EXTRA_DOWNLOAD_FILE_PATH = "DownloadFilePath"; static final String EXTRA_NOTIFICATION_DISMISSED = "NotificationDismissed"; - static final String EXTRA_DOWNLOAD_IS_OFF_THE_RECORD = "DownloadIsOffTheRecord"; - static final String EXTRA_DOWNLOAD_IS_OFFLINE_PAGE = "DownloadIsOfflinePage"; static final String EXTRA_IS_SUPPORTED_MIME_TYPE = "IsSupportedMimeType"; static final String ACTION_DOWNLOAD_CANCEL = "org.chromium.chrome.browser.download.DOWNLOAD_CANCEL"; @@ -297,12 +293,12 @@ isOffTheRecord, canDownloadWhileMetered, downloadGuid, fileName, itemType, true)); if (startTime > 0) builder.setWhen(startTime); Intent cancelIntent = buildActionIntent( - ACTION_DOWNLOAD_CANCEL, notificationId, downloadGuid, fileName, isOfflinePage); + ACTION_DOWNLOAD_CANCEL, downloadGuid, fileName, isOfflinePage); builder.addAction(R.drawable.btn_close_white, mContext.getResources().getString(R.string.download_notification_cancel_button), buildPendingIntent(cancelIntent, notificationId)); Intent pauseIntent = buildActionIntent( - ACTION_DOWNLOAD_PAUSE, notificationId, downloadGuid, fileName, isOfflinePage); + ACTION_DOWNLOAD_PAUSE, downloadGuid, fileName, isOfflinePage); builder.addAction(R.drawable.ic_media_control_pause, mContext.getResources().getString(R.string.download_notification_pause_button), buildPendingIntent(pauseIntent, notificationId)); @@ -362,8 +358,7 @@ NotificationCompat.Builder builder = buildNotification( android.R.drawable.ic_media_pause, entry.fileName, contentText); Intent cancelIntent = buildActionIntent( - ACTION_DOWNLOAD_CANCEL, entry.notificationId, entry.downloadGuid, entry.fileName, - entry.isOfflinePage()); + ACTION_DOWNLOAD_CANCEL, entry.downloadGuid, entry.fileName, entry.isOfflinePage()); Intent dismissIntent = new Intent(cancelIntent); dismissIntent.putExtra(EXTRA_NOTIFICATION_DISMISSED, true); builder.setDeleteIntent(buildPendingIntent(dismissIntent, entry.notificationId)); @@ -371,9 +366,7 @@ mContext.getResources().getString(R.string.download_notification_cancel_button), buildPendingIntent(cancelIntent, entry.notificationId)); Intent resumeIntent = buildActionIntent( - ACTION_DOWNLOAD_RESUME, entry.notificationId, entry.downloadGuid, entry.fileName, - entry.isOfflinePage()); - resumeIntent.putExtra(EXTRA_DOWNLOAD_IS_OFF_THE_RECORD, entry.isOffTheRecord); + ACTION_DOWNLOAD_RESUME, entry.downloadGuid, entry.fileName, entry.isOfflinePage()); builder.addAction(R.drawable.ic_get_app_white_24dp, mContext.getResources().getString(R.string.download_notification_resume_button), buildPendingIntent(resumeIntent, entry.notificationId)); @@ -407,8 +400,7 @@ mContext.getPackageName(), DownloadBroadcastReceiver.class.getName()); Intent intent; if (isOfflinePage) { - intent = buildActionIntent(ACTION_DOWNLOAD_OPEN, notificationId, downloadGuid, fileName, - isOfflinePage); + intent = buildActionIntent(ACTION_DOWNLOAD_OPEN, downloadGuid, fileName, isOfflinePage); } else { intent = new Intent(DownloadManager.ACTION_NOTIFICATION_CLICKED); long[] idArray = {systemDownloadId}; @@ -490,22 +482,17 @@ /** * Helper method to build an download action Intent from the provided information. * @param action Download action to perform. - * @param notificationId ID of the notification. * @param downloadGuid GUID of the download. * @param fileName Name of the download file. * @param isOfflinePage Whether the intent is for offline page download. */ private Intent buildActionIntent( - String action, int notificationId, String downloadGuid, String fileName, - boolean isOfflinePage) { + String action, String downloadGuid, String fileName, boolean isOfflinePage) { ComponentName component = new ComponentName( mContext.getPackageName(), DownloadBroadcastReceiver.class.getName()); Intent intent = new Intent(action); intent.setComponent(component); - intent.putExtra(EXTRA_DOWNLOAD_NOTIFICATION_ID, notificationId); intent.putExtra(EXTRA_DOWNLOAD_GUID, downloadGuid); - intent.putExtra(EXTRA_DOWNLOAD_FILE_NAME, fileName); - intent.putExtra(EXTRA_DOWNLOAD_IS_OFFLINE_PAGE, isOfflinePage); return intent; } @@ -560,19 +547,7 @@ private DownloadSharedPreferenceEntry getDownloadEntryFromIntent(Intent intent) { if (intent.getAction() == ACTION_DOWNLOAD_RESUME_ALL) return null; String guid = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_GUID); - DownloadSharedPreferenceEntry entry = getDownloadSharedPreferenceEntry(guid); - if (entry != null) return entry; - int notificationId = IntentUtils.safeGetIntExtra( - intent, EXTRA_DOWNLOAD_NOTIFICATION_ID, -1); - String fileName = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_FILE_NAME); - boolean metered = DownloadManagerService.isActiveNetworkMetered(mContext); - boolean isOffTheRecord = IntentUtils.safeGetBooleanExtra( - intent, EXTRA_DOWNLOAD_IS_OFF_THE_RECORD, false); - boolean isOfflinePage = IntentUtils.safeGetBooleanExtra( - intent, EXTRA_DOWNLOAD_IS_OFFLINE_PAGE, false); - return new DownloadSharedPreferenceEntry(notificationId, isOffTheRecord, metered, guid, - fileName, isOfflinePage ? DownloadSharedPreferenceEntry.ITEM_TYPE_OFFLINE_PAGE - : DownloadSharedPreferenceEntry.ITEM_TYPE_DOWNLOAD, true); + return getDownloadSharedPreferenceEntry(guid); } /** @@ -582,6 +557,7 @@ */ private void handleDownloadOperation(final Intent intent) { final DownloadSharedPreferenceEntry entry = getDownloadEntryFromIntent(intent); + if (entry == null) return; if (intent.getAction() == ACTION_DOWNLOAD_PAUSE) { // If browser process already goes away, the download should have already paused. Do // nothing in that case. @@ -708,16 +684,7 @@ && !ACTION_DOWNLOAD_OPEN.equals(intent.getAction())) { return false; } - if (!intent.hasExtra(EXTRA_DOWNLOAD_NOTIFICATION_ID) - || !intent.hasExtra(EXTRA_DOWNLOAD_FILE_NAME) - || !intent.hasExtra(EXTRA_DOWNLOAD_GUID)) { - return false; - } - final int notificationId = - IntentUtils.safeGetIntExtra(intent, EXTRA_DOWNLOAD_NOTIFICATION_ID, -1); - if (notificationId == -1) return false; - final String fileName = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_FILE_NAME); - if (fileName == null) return false; + if (!intent.hasExtra(EXTRA_DOWNLOAD_GUID)) return false; final String guid = IntentUtils.safeGetStringExtra(intent, EXTRA_DOWNLOAD_GUID); if (!DownloadSharedPreferenceEntry.isValidGUID(guid)) return false; return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java index b82a9099..3f34f3a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAServiceClient.java
@@ -18,6 +18,7 @@ import android.os.Message; import android.os.Messenger; import android.os.RemoteException; +import android.os.StrictMode; import android.util.Log; import org.chromium.base.Callback; @@ -180,8 +181,16 @@ boolean connect() { if (mService != null) Log.e(TAG, "Already connected."); Intent intent = new Intent(GSA_SERVICE).setPackage(GSAState.SEARCH_INTENT_PACKAGE); - return mContext.bindService( - intent, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND); + + // Third-party modifications to the framework lead to StrictMode violations in + // Context#bindService(). See crbug.com/670195. + StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); + try { + return mContext.bindService( + intent, mConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND); + } finally { + StrictMode.setThreadPolicy(oldPolicy); + } } /**
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 81b674be..e135107 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -6530,7 +6530,7 @@ </message> <message name="IDS_FLAGS_ENABLE_IME_MENU_NAME" desc="Name of the about: flag for enabling opt-in IME menu."> Enable opt-in IME menu - </message> + </message> <message name="IDS_FLAGS_ENABLE_IME_MENU_DESCRIPTION" desc="Description of the about: flag for enabling opt-in IME menu."> Enable access to the new IME menu in the Language Settings page. </message> @@ -6584,4 +6584,34 @@ <message name="IDS_PRINT_JOB_NOTIFICATION_GET_HELP_BUTTON" desc="Text on the button for the user to get help about the current print job."> Get help </message> + + <!-- RequestPin dialog messages --> + <message name="IDS_REQUEST_PIN_DIALOG_HEADER" desc="The text displayed in the certificate provider PIN request dialog."> + "<ph name="EXTENSION_NAME">$1<ex>My Extension</ex></ph>" is requesting your <ph name="CODE_TYPE">$2<ex>PIN</ex></ph> + </message> + <message name="IDS_REQUEST_PIN_DIALOG_PROCESSING" desc="The text displayed while the certificate provider API is waiting for response from extension."> + Processing request... + </message> + <message name="IDS_REQUEST_PIN_DIALOG_INVALID_PIN_ERROR" desc="The error message displayed in the certificate provider PIN request dialog when an invalid PIN was entered."> + Invalid PIN. + </message> + <message name="IDS_REQUEST_PIN_DIALOG_INVALID_PUK_ERROR" desc="The error message displayed in the certificate provider PIN request dialog when an invalid PUK was entered."> + Invalid PUK. + </message> + <message name="IDS_REQUEST_PIN_DIALOG_MAX_ATTEMPTS_EXCEEDED_ERROR" desc="The error message displayed in the certificate provider PIN request dialog when maximum allowed attempts exceeded."> + Maximum allowed attempts exceeded. + </message> + <message name="IDS_REQUEST_PIN_DIALOG_UNKNOWN_ERROR" desc="The error message displayed in the certificate provider PIN request dialog when unknown error occurred in extension code."> + Unknown error. + </message> + <message name="IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT" desc="The text displayed in the certificate provider PIN request dialog about the number of attempts left"> + Attempts left: $1 + </message> + <message name="IDS_REQUEST_PIN_DIALOG_PIN" desc="The Provider Identification Number abbreviation"> + PIN + </message> + <message name="IDS_REQUEST_PIN_DIALOG_PUK" desc="The Personal Unlocking Key (as used in mobile phones) abbreviation"> + PUK + </message> + </grit-part>
diff --git a/chrome/app/mash/mash_runner.cc b/chrome/app/mash/mash_runner.cc index b9a99a6..c1beac6 100644 --- a/chrome/app/mash/mash_runner.cc +++ b/chrome/app/mash/mash_runner.cc
@@ -105,12 +105,13 @@ // When launching the browser process, ensure that we don't inherit the // --mash flag so it proceeds with the normal content/browser startup path. - base::CommandLine::StringVector argv(command_line->argv()); - auto iter = - std::find(argv.begin(), argv.end(), FILE_PATH_LITERAL("--mash")); - if (iter != argv.end()) - argv.erase(iter); - *command_line = base::CommandLine(argv); + // Eliminate all copies in case the developer passed more than one. + base::CommandLine::StringVector new_argv; + for (const base::CommandLine::StringType& arg : command_line->argv()) { + if (arg != FILE_PATH_LITERAL("--mash")) + new_argv.push_back(arg); + } + *command_line = base::CommandLine(new_argv); } DISALLOW_COPY_AND_ASSIGN(NativeRunnerDelegateImpl);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 59393a2..f0bebec 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2007,6 +2007,7 @@ deps += [ "//chrome/browser/safe_browsing:chunk_proto", "//chrome/common/safe_browsing:proto", + "//components/safe_browsing/common:common", "//components/safe_browsing_db:metadata_proto", ] if (safe_browsing_mode == 1) {
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index 5b4967e..5a63b9f 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -351,6 +351,9 @@ } - (void)sendEvent:(NSEvent*)event { + base::debug::ScopedCrashKey crash_key( + crash_keys::mac::kNSEvent, base::SysNSStringToUTF8([event description])); + base::mac::CallWithEHFrame(^{ switch (event.type) { case NSLeftMouseDown:
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index e75a72c..fc3ef093 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -303,6 +303,8 @@ "certificate_provider/certificate_provider_service_factory.h", "certificate_provider/certificate_requests.cc", "certificate_provider/certificate_requests.h", + "certificate_provider/pin_dialog_manager.cc", + "certificate_provider/pin_dialog_manager.h", "certificate_provider/sign_requests.cc", "certificate_provider/sign_requests.h", "certificate_provider/thread_safe_certificate_map.cc", @@ -1273,6 +1275,8 @@ "ui/low_disk_notification.h", "ui/mobile_config_ui.cc", "ui/mobile_config_ui.h", + "ui/request_pin_view.cc", + "ui/request_pin_view.h", "ui/screen_capture_notification_ui_chromeos.cc", "ui/screen_capture_notification_ui_chromeos.h", "upgrade_detector_chromeos.cc",
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc index 806cac9..6726c97 100644 --- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc +++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.cc
@@ -400,6 +400,8 @@ for (auto callback : sign_requests_.RemoveAllRequests(extension_id)) callback.Run(net::ERR_FAILED, std::vector<uint8_t>()); + + pin_dialog_manager_.ExtensionUnloaded(extension_id); } void CertificateProviderService::GetCertificatesFromExtensions(
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h index dada1f225..41550f35 100644 --- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h +++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service.h
@@ -19,6 +19,7 @@ #include "base/threading/thread_checker.h" #include "chrome/browser/chromeos/certificate_provider/certificate_info.h" #include "chrome/browser/chromeos/certificate_provider/certificate_requests.h" +#include "chrome/browser/chromeos/certificate_provider/pin_dialog_manager.h" #include "chrome/browser/chromeos/certificate_provider/sign_requests.h" #include "chrome/browser/chromeos/certificate_provider/thread_safe_certificate_map.h" #include "components/keyed_service/core/keyed_service.h" @@ -150,6 +151,8 @@ // corresponding notification of the ExtensionRegistry is triggered. void OnExtensionUnloaded(const std::string& extension_id); + PinDialogManager* pin_dialog_manager() { return &pin_dialog_manager_; } + private: class CertKeyProviderImpl; class CertificateProviderImpl; @@ -191,6 +194,10 @@ // the net::ClientKeyStore singleton. std::unique_ptr<CertKeyProviderImpl> cert_key_provider_; + // The object to manage the dialog displayed when requestPin is called by the + // extension. + PinDialogManager pin_dialog_manager_; + // State about all pending sign requests. certificate_provider::SignRequests sign_requests_;
diff --git a/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc index 2edf5e7..3da1d9a 100644 --- a/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc +++ b/chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.cc
@@ -112,6 +112,8 @@ return false; api_cp::SignRequest request; + service_->pin_dialog_manager()->AddSignRequestId(extension_id, request_id); + request.sign_request_id = request_id; switch (hash) { case net::SSLPrivateKey::Hash::MD5_SHA1: request.hash = api_cp::HASH_MD5_SHA1;
diff --git a/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.cc b/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.cc new file mode 100644 index 0000000..fbc943e --- /dev/null +++ b/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.cc
@@ -0,0 +1,186 @@ +// Copyright 2016 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/certificate_provider/pin_dialog_manager.h" + +#include "ash/shell.h" +#include "base/strings/string16.h" +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_window.h" +#include "ui/aura/window.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/views/window/dialog_client_view.h" +#include "ui/views/window/dialog_delegate.h" + +namespace { + +gfx::NativeWindow GetBrowserParentWindow() { + if (chromeos::LoginDisplayHost::default_host()) { + return chromeos::LoginDisplayHost::default_host()->GetNativeWindow(); + } + + Browser* browser = + chrome::FindTabbedBrowser(ProfileManager::GetPrimaryUserProfile(), true); + if (browser) { + return browser->window()->GetNativeWindow(); + } + + return nullptr; +} + +} // namespace + +namespace chromeos { + +// Define timeout for issued sign_request_id. +const int SIGN_REQUEST_ID_TIMEOUT_MINS = 10; + +PinDialogManager::PinDialogManager() : weak_factory_(this) {} + +PinDialogManager::~PinDialogManager() { + // Close the active dialog if present to avoid leaking callbacks. + if (active_pin_dialog_) { + CloseDialog(active_dialog_extension_id_); + } +} + +void PinDialogManager::AddSignRequestId(const std::string& extension_id, + int sign_request_id) { + ExtensionNameRequestIdPair key(extension_id, sign_request_id); + // Cache the ID with current timestamp. + base::Time current_time = base::Time::Now(); + sign_request_times_[key] = current_time; +} + +PinDialogManager::RequestPinResponse PinDialogManager::ShowPinDialog( + const std::string& extension_id, + const std::string& extension_name, + int sign_request_id, + RequestPinView::RequestPinCodeType code_type, + RequestPinView::RequestPinErrorType error_type, + int attempts_left, + const RequestPinView::RequestPinCallback& callback) { + bool accept_input = (attempts_left != 0); + // If active dialog exists already, we need to make sure it belongs to the + // same extension and the user submitted some input. + if (active_pin_dialog_ != nullptr) { + DCHECK(!active_dialog_extension_id_.empty()); + if (extension_id != active_dialog_extension_id_) { + return OTHER_FLOW_IN_PROGRESS; + } + + // Extension requests a PIN without having received any input from its + // previous request. Reject the new request. + if (!active_pin_dialog_->IsLocked()) { + return DIALOG_DISPLAYED_ALREADY; + } + + // Set the new callback to be used by the view. + active_pin_dialog_->SetCallback(callback); + active_pin_dialog_->SetDialogParameters(code_type, error_type, + attempts_left, accept_input); + active_pin_dialog_->GetDialogClientView()->UpdateDialogButtons(); + return SUCCESS; + } + + // Check the validity of sign_request_id + ExtensionNameRequestIdPair key(extension_id, sign_request_id); + if (sign_request_times_.find(key) == sign_request_times_.end()) { + return INVALID_ID; + } + + base::Time current_time = base::Time::Now(); + if ((current_time - sign_request_times_[key]).InMinutes() > + SIGN_REQUEST_ID_TIMEOUT_MINS) { + return INVALID_ID; + } + + active_dialog_extension_id_ = extension_id; + active_pin_dialog_ = new RequestPinView(extension_name, code_type, + attempts_left, callback, this); + + gfx::NativeWindow parent = GetBrowserParentWindow(); + gfx::NativeWindow context = + parent ? nullptr : ash::Shell::GetPrimaryRootWindow(); + active_window_ = views::DialogDelegate::CreateDialogWidget(active_pin_dialog_, + context, parent); + active_window_->Show(); + + return SUCCESS; +} + +void PinDialogManager::OnPinDialogInput() { + last_response_closed_[active_dialog_extension_id_] = false; +} + +void PinDialogManager::OnPinDialogClosed() { + last_response_closed_[active_dialog_extension_id_] = true; + // |active_pin_dialog_| is managed by |active_window_|. This local copy of + // the pointer is reset here to allow a new dialog to be created when a new + // request comes. + active_pin_dialog_ = nullptr; +} + +PinDialogManager::StopPinRequestResponse PinDialogManager::UpdatePinDialog( + const std::string& extension_id, + RequestPinView::RequestPinErrorType error_type, + bool accept_input, + const RequestPinView::RequestPinCallback& callback) { + if (active_pin_dialog_ == nullptr || + extension_id != active_dialog_extension_id_) { + return NO_ACTIVE_DIALOG; + } + + if (!active_pin_dialog_->IsLocked()) { + return NO_USER_INPUT; + } + + active_pin_dialog_->SetCallback(callback); + active_pin_dialog_->SetDialogParameters( + RequestPinView::RequestPinCodeType::UNCHANGED, error_type, -1, + accept_input); + active_pin_dialog_->GetDialogClientView()->UpdateDialogButtons(); + return STOPPED; +} + +bool PinDialogManager::LastPinDialogClosed(const std::string& extension_id) { + return last_response_closed_[extension_id]; +} + +bool PinDialogManager::CloseDialog(const std::string& extension_id) { + if (extension_id != active_dialog_extension_id_ || + active_pin_dialog_ == nullptr) { + LOG(ERROR) << "StopPinRequest called by unexpected extension: " + << extension_id; + return false; + } + + // Close the window. |active_pin_dialog_| gets deleted inside Close(). + active_window_->Close(); + active_pin_dialog_ = nullptr; + + return true; +} + +void PinDialogManager::ExtensionUnloaded(const std::string& extension_id) { + if (active_pin_dialog_ && active_dialog_extension_id_ == extension_id) { + CloseDialog(extension_id); + } + + last_response_closed_[extension_id] = false; + + for (auto it = sign_request_times_.cbegin(); + it != sign_request_times_.cend();) { + if (it->first.first == extension_id) { + sign_request_times_.erase(it++); + } else { + ++it; + } + } +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.h b/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.h new file mode 100644 index 0000000..6babe06 --- /dev/null +++ b/chrome/browser/chromeos/certificate_provider/pin_dialog_manager.h
@@ -0,0 +1,122 @@ +// Copyright 2016 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_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_ +#define CHROME_BROWSER_CHROMEOS_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_ + +#include <map> +#include <string> +#include <unordered_map> +#include <utility> + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "base/time/time.h" +#include "chrome/browser/chromeos/ui/request_pin_view.h" +#include "ui/views/widget/widget.h" + +namespace chromeos { + +// Manages the state of the dialog that requests the PIN from user. Used by the +// extensions that need to request the PIN. Implemented as requirement for +// crbug.com/612886 +class PinDialogManager : RequestPinView::Delegate { + public: + enum RequestPinResponse { + SUCCESS, + INVALID_ID, + OTHER_FLOW_IN_PROGRESS, + DIALOG_DISPLAYED_ALREADY + }; + + enum StopPinRequestResponse { STOPPED, NO_ACTIVE_DIALOG, NO_USER_INPUT }; + + PinDialogManager(); + ~PinDialogManager(); + + // Stores internally the |signRequestId| along with current timestamp. + void AddSignRequestId(const std::string& extension_id, int sign_request_id); + + // Creates a new RequestPinView object and displays it in a dialog or reuses + // the old dialog if active one exists just updating the parameters. + // |extension_id| - the ID of the extension requesting the dialog. + // |extension_name| - the name of the extension requesting the dialog. + // |sign_request_id| - the ID given by Chrome when the extension was asked to + // sign the data. It should be a valid, not expired ID at the time the + // extension is requesting PIN the first time. + // |code_type| - the type of input requested: either "PIN" or "PUK". + // |error_type| - the error template to be displayed inside the dialog. If + // NONE, no error is displayed. + // |attempts_left| - the number of attempts the user has to try the code. It + // is informational only, and enforced on Chrome side only in case it's + // zero. In that case the textfield is disabled and the user can't provide + // any input to extension. If -1 the textfield from the dialog is enabled + // but no information about the attepts left is not given to the user. + // |callback| - used to notify about the user input in the text_field from the + // dialog. + // Returns SUCCESS if the dialog is displayed and extension owns it. Otherwise + // the specific error is returned. + RequestPinResponse ShowPinDialog( + const std::string& extension_id, + const std::string& extension_name, + int sign_request_id, + RequestPinView::RequestPinCodeType code_type, + RequestPinView::RequestPinErrorType error_type, + int attempts_left, + const RequestPinView::RequestPinCallback& callback); + + // chromeos::RequestPinView::Delegate overrides. + void OnPinDialogInput() override; + void OnPinDialogClosed() override; + + // Updates the existing dialog with new error message. Uses |callback| with + // empty string when user closes the dialog. Returns whether the provided + // |extension_id| matches the extension owning the active dialog. + PinDialogManager::StopPinRequestResponse UpdatePinDialog( + const std::string& extension_id, + RequestPinView::RequestPinErrorType error_type, + bool accept_input, + const RequestPinView::RequestPinCallback& callback); + + // Returns whether the last PIN dialog from this extension was closed by the + // user. + bool LastPinDialogClosed(const std::string& extension_id); + + // Called when extension calls the stopPinRequest method. The active dialog is + // closed if the |extension_id| matches the |active_dialog_extension_id_|. + // Returns whether the dialog was closed. + bool CloseDialog(const std::string& extension_id); + + // Resets the manager data related to the extension. + void ExtensionUnloaded(const std::string& extension_id); + + RequestPinView* active_view_for_testing() { return active_pin_dialog_; } + views::Widget* active_window_for_testing() { return active_window_; } + + private: + using ExtensionNameRequestIdPair = std::pair<std::string, int>; + + // Tells whether user closed the last request PIN dialog issued by an + // extension. The extension_id is the key and value is true if user closed the + // dialog. Used to determine if the limit of dialogs rejected by the user has + // been exceeded. + std::unordered_map<std::string, bool> last_response_closed_; + + // The map with extension_id and sign request id issued by Chrome as key while + // the time when the id was generated is the value. + std::map<ExtensionNameRequestIdPair, base::Time> sign_request_times_; + + // There can be only one active dialog to request the PIN at some point in + // time. Owned by |active_window_|. + RequestPinView* active_pin_dialog_ = nullptr; + std::string active_dialog_extension_id_; + views::Widget* active_window_ = nullptr; + + base::WeakPtrFactory<PinDialogManager> weak_factory_; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_
diff --git a/chrome/browser/chromeos/ui/request_pin_view.cc b/chrome/browser/chromeos/ui/request_pin_view.cc new file mode 100644 index 0000000..c89c4cb --- /dev/null +++ b/chrome/browser/chromeos/ui/request_pin_view.cc
@@ -0,0 +1,262 @@ +// Copyright 2016 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/ui/request_pin_view.h" + +#include <stddef.h> + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/options/passphrase_textfield.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/grit/theme_resources.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/events/event.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/layout/grid_layout.h" +#include "ui/views/layout/layout_constants.h" +#include "ui/views/widget/widget.h" +#include "ui/views/window/dialog_client_view.h" + +namespace chromeos { + +RequestPinView::RequestPinView(const std::string& extension_name, + RequestPinView::RequestPinCodeType code_type, + int attempts_left, + const RequestPinCallback& callback, + Delegate* delegate) + : callback_(callback), delegate_(delegate), weak_ptr_factory_(this) { + DCHECK(code_type != RequestPinCodeType::UNCHANGED); + DCHECK(delegate); + Init(); + SetExtensionName(extension_name); + const bool accept_input = (attempts_left != 0); + SetDialogParameters(code_type, RequestPinErrorType::NONE, attempts_left, + accept_input); +} + +// When the parent window is closed while the dialog is active, this object is +// destroyed without triggering Accept or Cancel. If the callback_ wasn't called +// it needs to send the response. +RequestPinView::~RequestPinView() { + if (!callback_.is_null()) { + base::ResetAndReturn(&callback_).Run(base::string16()); + } + + delegate_->OnPinDialogClosed(); +} + +void RequestPinView::ContentsChanged(views::Textfield* sender, + const base::string16& new_contents) { + GetDialogClientView()->UpdateDialogButtons(); +} + +bool RequestPinView::Cancel() { + // Destructor will be called after this which notifies the delegate. + return true; +} + +bool RequestPinView::Accept() { + DCHECK(!callback_.is_null()); + + if (!textfield_->enabled()) { + return true; + } + DCHECK(!textfield_->text().empty()); + + error_label_->SetVisible(true); + error_label_->SetText( + l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_PROCESSING)); + error_label_->SetTooltipText(error_label_->text()); + error_label_->SetEnabledColor(SK_ColorGRAY); + error_label_->SizeToPreferredSize(); + // The |textfield_| and OK button become disabled, but the user still can + // close the dialog. + SetAcceptInput(false); + base::ResetAndReturn(&callback_).Run(textfield_->text()); + GetDialogClientView()->UpdateDialogButtons(); + delegate_->OnPinDialogInput(); + + return false; +} + +base::string16 RequestPinView::GetWindowTitle() const { + return window_title_; +} + +views::View* RequestPinView::GetInitiallyFocusedView() { + return textfield_; +} + +bool RequestPinView::IsDialogButtonEnabled(ui::DialogButton button) const { + switch (button) { + case ui::DialogButton::DIALOG_BUTTON_CANCEL: + return true; + case ui::DialogButton::DIALOG_BUTTON_OK: + if (callback_.is_null()) { + return false; + } + // Not locked but the |textfield_| is not enabled. It's just a + // notification to the user and [OK] button can be used to close the + // dialog. + if (!textfield_->enabled()) { + return true; + } + return textfield_->text().size() > 0; + case ui::DialogButton::DIALOG_BUTTON_NONE: + return true; + } + + NOTREACHED(); + return true; +} + +bool RequestPinView::IsLocked() { + return callback_.is_null(); +} + +void RequestPinView::SetCallback(const RequestPinCallback& callback) { + DCHECK(callback_.is_null()); + callback_ = callback; +} + +void RequestPinView::SetDialogParameters( + RequestPinView::RequestPinCodeType code_type, + RequestPinView::RequestPinErrorType error_type, + int attempts_left, + bool accept_input) { + SetErrorMessage(error_type, attempts_left); + SetAcceptInput(accept_input); + + switch (code_type) { + case RequestPinCodeType::PIN: + code_type_ = l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_PIN); + break; + case RequestPinCodeType::PUK: + code_type_ = l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_PUK); + break; + case RequestPinCodeType::UNCHANGED: + break; + } + + UpdateHeaderText(); +} + +void RequestPinView::SetExtensionName(const std::string& extension_name) { + window_title_ = base::ASCIIToUTF16(extension_name); + UpdateHeaderText(); +} + +void RequestPinView::UpdateHeaderText() { + int label_text_id = IDS_REQUEST_PIN_DIALOG_HEADER; + base::string16 label_text = + l10n_util::GetStringFUTF16(label_text_id, window_title_, code_type_); + header_label_->SetText(label_text); + header_label_->SizeToPreferredSize(); +} + +void RequestPinView::Init() { + views::GridLayout* layout = views::GridLayout::CreatePanel(this); + SetLayoutManager(layout); + + int column_view_set_id = 0; + views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id); + + column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + layout->StartRow(0, column_view_set_id); + + // Infomation label. + int label_text_id = IDS_REQUEST_PIN_DIALOG_HEADER; + base::string16 label_text = l10n_util::GetStringUTF16(label_text_id); + header_label_ = new views::Label(label_text); + header_label_->SetEnabled(true); + layout->AddView(header_label_); + + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + + column_view_set_id++; + column_set = layout->AddColumnSet(column_view_set_id); + column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 100, + views::GridLayout::USE_PREF, 0, 0); + + // Textfield to enter the PIN/PUK. + layout->StartRow(0, column_view_set_id); + textfield_ = new PassphraseTextfield(); + textfield_->set_controller(this); + textfield_->SetEnabled(true); + layout->AddView(textfield_); + + layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); + + column_view_set_id++; + column_set = layout->AddColumnSet(column_view_set_id); + column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1, + views::GridLayout::USE_PREF, 0, 0); + + // Error label. + layout->StartRow(0, column_view_set_id); + error_label_ = new views::Label(); + error_label_->SetVisible(false); + error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + layout->AddView(error_label_); +} + +void RequestPinView::SetAcceptInput(bool accept_input) { + if (accept_input) { + textfield_->SetEnabled(true); + textfield_->SetBackgroundColor(SK_ColorWHITE); + textfield_->RequestFocus(); + } else { + textfield_->SetEnabled(false); + textfield_->SetBackgroundColor(SK_ColorGRAY); + } +} + +void RequestPinView::SetErrorMessage(RequestPinErrorType error_type, + int attempts_left) { + base::string16 error_message; + switch (error_type) { + case RequestPinErrorType::INVALID_PIN: + error_message = + l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_INVALID_PIN_ERROR); + break; + case RequestPinErrorType::INVALID_PUK: + error_message = + l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_INVALID_PUK_ERROR); + break; + case RequestPinErrorType::MAX_ATTEMPTS_EXCEEDED: + error_message = l10n_util::GetStringUTF16( + IDS_REQUEST_PIN_DIALOG_MAX_ATTEMPTS_EXCEEDED_ERROR); + break; + case RequestPinErrorType::UNKNOWN_ERROR: + error_message = + l10n_util::GetStringUTF16(IDS_REQUEST_PIN_DIALOG_UNKNOWN_ERROR); + break; + case RequestPinErrorType::NONE: + if (attempts_left < 0) { + error_label_->SetVisible(false); + return; + } + break; + } + + if (attempts_left >= 0) { + error_message.append(l10n_util::GetStringFUTF16( + IDS_REQUEST_PIN_DIALOG_ATTEMPTS_LEFT, + base::ASCIIToUTF16(std::to_string(attempts_left)))); + } + + error_label_->SetVisible(true); + error_label_->SetText(error_message); + error_label_->SetTooltipText(error_message); + error_label_->SetEnabledColor(SK_ColorRED); + error_label_->SizeToPreferredSize(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/ui/request_pin_view.h b/chrome/browser/chromeos/ui/request_pin_view.h new file mode 100644 index 0000000..2884a75f --- /dev/null +++ b/chrome/browser/chromeos/ui/request_pin_view.h
@@ -0,0 +1,145 @@ +// Copyright 2016 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_UI_REQUEST_PIN_VIEW_H_ +#define CHROME_BROWSER_CHROMEOS_UI_REQUEST_PIN_VIEW_H_ + +#include <memory> +#include <string> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "base/strings/string16.h" +#include "ui/base/ui_base_types.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/controls/textfield/textfield_controller.h" +#include "ui/views/view.h" +#include "ui/views/window/dialog_delegate.h" + +namespace views { +class Label; +} + +namespace chromeos { + +// A dialog box for requesting PIN code. Instances of this class are managed by +// PinDialogManager. +class RequestPinView : public views::DialogDelegateView, + public views::TextfieldController { + public: + enum RequestPinCodeType { PIN, PUK, UNCHANGED }; + + enum RequestPinErrorType { + NONE, + INVALID_PIN, + INVALID_PUK, + MAX_ATTEMPTS_EXCEEDED, + UNKNOWN_ERROR + }; + + class Delegate { + public: + // Notification when user closes the PIN dialog. + virtual void OnPinDialogClosed() = 0; + + // Notification when the user provided input to dialog. + virtual void OnPinDialogInput() = 0; + }; + + // Used to send the PIN/PUK entered by the user in the textfield to the + // extension that asked for the code. + using RequestPinCallback = base::Callback<void(const base::string16&)>; + + // Creates the view to be embeded in the dialog that requests the PIN/PUK. + // |extension_name| - the name of the extension making the request. Displayed + // in the title and in the header of the view. + // |code_type| - the type of code requested, PIN or PUK. UNCHANGED is not + // accepted here. + // |attempts_left| - the number of attempts user has to try the code. When + // zero the textfield is disabled and user cannot provide any input. When + // -1 the user is allowed to provide the input and no information about + // the attepts left is displayed in the view. + // |callback| - used to send the value of the PIN/PUK the user entered. + // |delegate| - used to notify that dialog was closed. Cannot be null. + RequestPinView(const std::string& extension_name, + RequestPinCodeType code_type, + int attempts_left, + const RequestPinCallback& callback, + Delegate* delegate); + ~RequestPinView() override; + + // views::TextfieldController + void ContentsChanged(views::Textfield* sender, + const base::string16& new_contents) override; + + // views::DialogDelegateView + bool Cancel() override; + bool Accept() override; + base::string16 GetWindowTitle() const override; + views::View* GetInitiallyFocusedView() override; + bool IsDialogButtonEnabled(ui::DialogButton button) const override; + + // Returns whether the view is locked while waiting the extension to process + // the user input data. + bool IsLocked(); + + // Set the new callback to be used when user will provide the input. The old + // callback must be used and reset to null at this point. + void SetCallback(const RequestPinCallback& callback); + + // |code_type| - specifies whether the user is asked to enter PIN or PUK. If + // UNCHANGED value is provided, the dialog displays the same value that + // was last set. + // |error_type| - the error template to be displayed in red in the dialog. If + // NONE, no error is displayed. + // |attempts_left| - included in the view as the number of attepts user can + // have to enter correct code. + // |accept_input| - specifies whether the textfield is enabled. If disabled + // the user is unable to provide input. + void SetDialogParameters(RequestPinCodeType code_type, + RequestPinErrorType error_type, + int attempts_left, + bool accept_input); + + // Set the name of extension that is using this view. The name is included in + // the header text displayed by the view. + void SetExtensionName(const std::string& extension_name); + + views::Textfield* textfield_for_testing() { return textfield_; } + views::Label* error_label_for_testing() { return error_label_; } + + private: + // This initializes the view, with all the UI components. + void Init(); + void SetAcceptInput(bool accept_input); + void SetErrorMessage(RequestPinErrorType error_type, int attempts_left); + // Updates the header text |header_label_| based on values from + // |window_title_| and |code_type_|. + void UpdateHeaderText(); + + // Used to send the input when the view is not locked. If user closes the + // view, the provided input is empty. The |callback_| must be reset to null + // after being used, allowing to check that it was used when a new callback is + // set. + RequestPinCallback callback_; + + // Owned by the caller. + Delegate* delegate_ = nullptr; + + base::string16 window_title_; + views::Label* header_label_ = nullptr; + base::string16 code_type_; + views::Textfield* textfield_ = nullptr; + views::Label* error_label_ = nullptr; + + base::WeakPtrFactory<RequestPinView> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(RequestPinView); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_UI_REQUEST_PIN_VIEW_H_
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc index cdf49c4..8d1a2bb 100644 --- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc +++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -19,10 +19,35 @@ #include "net/cert/x509_certificate.h" #include "net/ssl/ssl_private_key.h" -namespace extensions { +namespace api_cp = extensions::api::certificate_provider; +namespace api_cpi = extensions::api::certificate_provider_internal; -namespace api_cp = api::certificate_provider; -namespace api_cpi = api::certificate_provider_internal; +namespace { + +chromeos::RequestPinView::RequestPinErrorType GetErrorTypeForView( + api_cp::PinRequestErrorType error_type) { + switch (error_type) { + case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_INVALID_PIN: + return chromeos::RequestPinView::RequestPinErrorType::INVALID_PIN; + case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_INVALID_PUK: + return chromeos::RequestPinView::RequestPinErrorType::INVALID_PUK; + case api_cp::PinRequestErrorType:: + PIN_REQUEST_ERROR_TYPE_MAX_ATTEMPTS_EXCEEDED: + return chromeos::RequestPinView::RequestPinErrorType:: + MAX_ATTEMPTS_EXCEEDED; + case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_UNKNOWN_ERROR: + return chromeos::RequestPinView::RequestPinErrorType::UNKNOWN_ERROR; + case api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_NONE: + return chromeos::RequestPinView::RequestPinErrorType::NONE; + } + + NOTREACHED(); + return chromeos::RequestPinView::RequestPinErrorType::NONE; +} + +} // namespace + +namespace extensions { namespace { @@ -33,8 +58,17 @@ const char kErrorAborted[] = "Request was aborted."; const char kErrorTimeout[] = "Request timed out, reply rejected."; +// requestPin constants. +const char kNoActiveDialog[] = "No active dialog from extension."; +const char kInvalidId[] = "Invalid signRequestId"; +const char kOtherFlowInProgress[] = "Other flow in progress"; +const char kPreviousDialogActive[] = "Previous request not finished"; +const char kNoUserInput[] = "No user input received"; + } // namespace +const int api::certificate_provider::kMaxClosedDialogsPer10Mins = 2; + CertificateProviderInternalReportCertificatesFunction:: ~CertificateProviderInternalReportCertificatesFunction() {} @@ -148,6 +182,152 @@ return true; } +CertificateProviderStopPinRequestFunction:: + ~CertificateProviderStopPinRequestFunction() {} + +ExtensionFunction::ResponseAction +CertificateProviderStopPinRequestFunction::Run() { + std::unique_ptr<api_cp::RequestPin::Params> params( + api_cp::RequestPin::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + chromeos::CertificateProviderService* const service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + if (params->details.error_type == + api_cp::PinRequestErrorType::PIN_REQUEST_ERROR_TYPE_NONE) { + bool dialog_closed = + service->pin_dialog_manager()->CloseDialog(extension_id()); + if (!dialog_closed) { + // This might happen if the user closed the dialog while extension was + // processing the input. + return RespondNow(Error(kNoActiveDialog)); + } + + return RespondNow(NoArguments()); + } + + // Extension provided an error, which means it intends to notify the user with + // the error and not allow any more input. + chromeos::RequestPinView::RequestPinErrorType error_type = + GetErrorTypeForView(params->details.error_type); + chromeos::PinDialogManager::StopPinRequestResponse update_response = + service->pin_dialog_manager()->UpdatePinDialog( + extension()->id(), error_type, + false, // Don't accept any input. + base::Bind(&CertificateProviderStopPinRequestFunction::DialogClosed, + this)); + switch (update_response) { + case chromeos::PinDialogManager::StopPinRequestResponse::NO_ACTIVE_DIALOG: + return RespondNow(Error(kNoActiveDialog)); + case chromeos::PinDialogManager::StopPinRequestResponse::NO_USER_INPUT: + return RespondNow(Error(kNoUserInput)); + case chromeos::PinDialogManager::StopPinRequestResponse::STOPPED: + return RespondLater(); + } + + NOTREACHED(); + return RespondLater(); +} + +void CertificateProviderStopPinRequestFunction::DialogClosed( + const base::string16& value) { + chromeos::CertificateProviderService* const service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + + Respond(NoArguments()); + service->pin_dialog_manager()->OnPinDialogClosed(); +} + +CertificateProviderRequestPinFunction:: + ~CertificateProviderRequestPinFunction() {} + +bool CertificateProviderRequestPinFunction::ShouldSkipQuotaLimiting() const { + chromeos::CertificateProviderService* const service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + + return !service->pin_dialog_manager()->LastPinDialogClosed(extension_id()); +} + +void CertificateProviderRequestPinFunction::GetQuotaLimitHeuristics( + extensions::QuotaLimitHeuristics* heuristics) const { + QuotaLimitHeuristic::Config short_limit_config = { + api::certificate_provider::kMaxClosedDialogsPer10Mins, + base::TimeDelta::FromMinutes(10)}; + heuristics->push_back(base::MakeUnique<QuotaService::TimedLimit>( + short_limit_config, new QuotaLimitHeuristic::SingletonBucketMapper(), + "MAX_PIN_DIALOGS_CLOSED_PER_10_MINUTES")); +} + +ExtensionFunction::ResponseAction CertificateProviderRequestPinFunction::Run() { + std::unique_ptr<api_cp::RequestPin::Params> params( + api_cp::RequestPin::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + api_cp::PinRequestType pin_request_type = + params->details.request_type == + api_cp::PinRequestType::PIN_REQUEST_TYPE_NONE + ? api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN + : params->details.request_type; + + chromeos::RequestPinView::RequestPinErrorType error_type = + GetErrorTypeForView(params->details.error_type); + + chromeos::RequestPinView::RequestPinCodeType code_type = + (pin_request_type == api_cp::PinRequestType::PIN_REQUEST_TYPE_PIN) + ? chromeos::RequestPinView::RequestPinCodeType::PIN + : chromeos::RequestPinView::RequestPinCodeType::PUK; + + chromeos::CertificateProviderService* const service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + + int attempts_left = + params->details.attempts_left ? *params->details.attempts_left : -1; + chromeos::PinDialogManager::RequestPinResponse result = + service->pin_dialog_manager()->ShowPinDialog( + extension()->id(), extension()->name(), + params->details.sign_request_id, code_type, error_type, attempts_left, + base::Bind(&CertificateProviderRequestPinFunction::OnInputReceived, + this)); + switch (result) { + case chromeos::PinDialogManager::RequestPinResponse::SUCCESS: + return RespondLater(); + case chromeos::PinDialogManager::RequestPinResponse::INVALID_ID: + return RespondNow(Error(kInvalidId)); + case chromeos::PinDialogManager::RequestPinResponse::OTHER_FLOW_IN_PROGRESS: + return RespondNow(Error(kOtherFlowInProgress)); + case chromeos::PinDialogManager::RequestPinResponse:: + DIALOG_DISPLAYED_ALREADY: + return RespondNow(Error(kPreviousDialogActive)); + } + + NOTREACHED(); + return RespondNow(Error(kPreviousDialogActive)); +} + +void CertificateProviderRequestPinFunction::OnInputReceived( + const base::string16& value) { + std::unique_ptr<base::ListValue> create_results(new base::ListValue()); + chromeos::CertificateProviderService* const service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + browser_context()); + DCHECK(service); + if (!value.empty()) { + api::certificate_provider::PinResponseDetails details; + details.user_input.reset(new std::string(value.begin(), value.end())); + create_results->Append(details.ToValue()); + } + + Respond(ArgumentList(std::move(create_results))); +} + CertificateProviderInternalReportSignatureFunction:: ~CertificateProviderInternalReportSignatureFunction() {}
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h index bc4ec19..1f4686b 100644 --- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h +++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h
@@ -17,6 +17,10 @@ namespace api { namespace certificate_provider { +// The maximum number of times per 10 minutes, extension is allowed to show PIN +// dialog again after user closed the previous one. +extern const int kMaxClosedDialogsPer10Mins; + struct CertificateInfo; } } @@ -45,6 +49,30 @@ CERTIFICATEPROVIDERINTERNAL_REPORTSIGNATURE); }; +class CertificateProviderRequestPinFunction : public UIThreadExtensionFunction { + private: + ~CertificateProviderRequestPinFunction() override; + ResponseAction Run() override; + bool ShouldSkipQuotaLimiting() const override; + void GetQuotaLimitHeuristics( + extensions::QuotaLimitHeuristics* heuristics) const override; + void OnInputReceived(const base::string16& value); + + DECLARE_EXTENSION_FUNCTION("certificateProvider.requestPin", + CERTIFICATEPROVIDER_REQUESTPIN); +}; + +class CertificateProviderStopPinRequestFunction + : public UIThreadExtensionFunction { + private: + ~CertificateProviderStopPinRequestFunction() override; + ResponseAction Run() override; + void DialogClosed(const base::string16& value); + + DECLARE_EXTENSION_FUNCTION("certificateProvider.stopPinRequest", + CERTIFICATEPROVIDER_STOPPINREQUEST); +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_CERTIFICATE_PROVIDER_CERTIFICATE_PROVIDER_API_H_
diff --git a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc index 407f6a9..bd24b95 100644 --- a/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc +++ b/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc
@@ -18,6 +18,9 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h" +#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h" +#include "chrome/browser/extensions/api/certificate_provider/certificate_provider_api.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/ui_test_utils.h" @@ -32,11 +35,16 @@ #include "content/public/test/test_utils.h" #include "crypto/rsa_private_key.h" #include "extensions/common/extension.h" +#include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/boringssl/src/include/openssl/evp.h" #include "third_party/boringssl/src/include/openssl/rsa.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" using testing::Return; using testing::_; @@ -121,6 +129,41 @@ return res; } +// Enters the code in the ShowPinDialog window and pushes the OK event. +void EnterCode(chromeos::CertificateProviderService* service, + const base::string16& code) { + chromeos::RequestPinView* view = + service->pin_dialog_manager()->active_view_for_testing(); + view->textfield_for_testing()->SetText(code); + view->Accept(); + base::RunLoop().RunUntilIdle(); +} + +// Enters the valid code for extensions from local example folders, in the +// ShowPinDialog window and waits for the window to close. The extension code +// is expected to send "Success" message after the validation and request to +// stopPinRequest is done. +void EnterCorrectPin(chromeos::CertificateProviderService* service) { + ExtensionTestMessageListener listener("Success", false); + EnterCode(service, base::ASCIIToUTF16("1234")); + ASSERT_TRUE(listener.WaitUntilSatisfied()); +} + +// Enters an invalid code for extensions from local example folders, in the +// ShowPinDialog window and waits for the window to update with the error. The +// extension code is expected to send "Invalid PIN" message after the validation +// and the new requestPin (with the error) is done. +void EnterWrongPin(chromeos::CertificateProviderService* service) { + ExtensionTestMessageListener listener("Invalid PIN", false); + EnterCode(service, base::ASCIIToUTF16("567")); + ASSERT_TRUE(listener.WaitUntilSatisfied()); + + // Check that we have an error message displayed. + chromeos::RequestPinView* view = + service->pin_dialog_manager()->active_view_for_testing(); + EXPECT_EQ(SK_ColorRED, view->error_label_for_testing()->enabled_color()); +} + class CertificateProviderApiTest : public ExtensionApiTest { public: CertificateProviderApiTest() {} @@ -157,6 +200,27 @@ policy::MockConfigurationPolicyProvider provider_; }; +class CertificateProviderRequestPinTest : public CertificateProviderApiTest { + public: + // Loads certificate_provider extension from |folder| and |file_name|. + // Returns the CertificateProviderService object from browser context. + chromeos::CertificateProviderService* LoadRequestPinExtension( + const std::string& folder, + const std::string& file_name) { + const base::FilePath extension_path = + test_data_dir_.AppendASCII("certificate_provider/" + folder); + const extensions::Extension* const extension = + LoadExtension(extension_path); + chromeos::CertificateProviderService* service = + chromeos::CertificateProviderServiceFactory::GetForBrowserContext( + profile()); + service->pin_dialog_manager()->AddSignRequestId(extension->id(), 123); + ui_test_utils::NavigateToURL(browser(), + extension->GetResourceURL(file_name)); + return service; + } +}; + } // namespace IN_PROC_BROWSER_TEST_F(CertificateProviderApiTest, Basic) { @@ -268,3 +332,99 @@ EXPECT_TRUE(result); } } + +// User enters the correct PIN. +IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, ShowPinDialogAccept) { + chromeos::CertificateProviderService* service = + LoadRequestPinExtension("request_pin", "basic.html"); + + // Enter the valid PIN. + EnterCorrectPin(service); + + // The view should be set to nullptr when the window is closed. + EXPECT_EQ(service->pin_dialog_manager()->active_view_for_testing(), nullptr); +} + +// User closes the dialog kMaxClosedDialogsPer10Mins times, and the extension +// should be blocked from showing it again. +IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, ShowPinDialogClose) { + chromeos::CertificateProviderService* service = + LoadRequestPinExtension("request_pin", "basic.html"); + + views::Widget* window = + service->pin_dialog_manager()->active_window_for_testing(); + for (int i = 0; + i < extensions::api::certificate_provider::kMaxClosedDialogsPer10Mins; + i++) { + ExtensionTestMessageListener listener("User closed the dialog", false); + window->Close(); + ASSERT_TRUE(listener.WaitUntilSatisfied()); + window = service->pin_dialog_manager()->active_window_for_testing(); + } + + ExtensionTestMessageListener close_listener("User closed the dialog", true); + window->Close(); + ASSERT_TRUE(close_listener.WaitUntilSatisfied()); + close_listener.Reply("GetLastError"); + ExtensionTestMessageListener last_error_listener( + "This request exceeds the MAX_PIN_DIALOGS_CLOSED_PER_10_MINUTES quota.", + false); + ASSERT_TRUE(last_error_listener.WaitUntilSatisfied()); + EXPECT_EQ(service->pin_dialog_manager()->active_view_for_testing(), nullptr); +} + +// User enters a wrong PIN first and a correct PIN on the second try. +IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, + ShowPinDialogWrongPin) { + chromeos::CertificateProviderService* service = + LoadRequestPinExtension("request_pin", "basic.html"); + EnterWrongPin(service); + + // The window should be active. + EXPECT_EQ( + service->pin_dialog_manager()->active_window_for_testing()->IsVisible(), + true); + EXPECT_NE(service->pin_dialog_manager()->active_view_for_testing(), nullptr); + + // Enter the valid PIN. + EnterCorrectPin(service); + + // The view should be set to nullptr when the window is closed. + EXPECT_EQ(service->pin_dialog_manager()->active_view_for_testing(), nullptr); +} + +// User enters wrong PIN three times. +IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, + ShowPinDialogWrongPinThreeTimes) { + chromeos::CertificateProviderService* service = + LoadRequestPinExtension("request_pin", "basic.html"); + for (int i = 0; i < 3; i++) { + EnterWrongPin(service); + } + + chromeos::RequestPinView* view = + service->pin_dialog_manager()->active_view_for_testing(); + + // The textfield has to be disabled, as extension does not allow input now. + EXPECT_EQ(view->textfield_for_testing()->enabled(), false); + + // Close the dialog. + ExtensionTestMessageListener listener("No attempt left", false); + service->pin_dialog_manager()->active_window_for_testing()->Close(); + ASSERT_TRUE(listener.WaitUntilSatisfied()); + EXPECT_EQ(service->pin_dialog_manager()->active_view_for_testing(), nullptr); +} + +// User closes the dialog while the extension is processing the request. +IN_PROC_BROWSER_TEST_F(CertificateProviderRequestPinTest, + ShowPinDialogCloseWhileProcessing) { + chromeos::CertificateProviderService* service = + LoadRequestPinExtension("request_pin", "basic_lock.html"); + + EnterCode(service, base::ASCIIToUTF16("123")); + service->pin_dialog_manager()->active_window_for_testing()->Close(); + base::RunLoop().RunUntilIdle(); + + // The view should be set to nullptr when the window is closed. + EXPECT_EQ(service->pin_dialog_manager()->active_view_for_testing(), nullptr); +}
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 662c9e7b..958a4958 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -251,6 +251,32 @@ return value; } +// This function is for forwarding metrics usage pref changes to the metrics +// service on the appropriate thread. +// TODO(gayane): Reduce the frequency of posting tasks from IO to UI thread. +void UpdateMetricsUsagePrefsOnUIThread(const std::string& service_name, + int message_size, + bool is_cellular) { + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind([](const std::string& service_name, + int message_size, + bool is_cellular) { + // Some unit tests use IOThread but do not initialize + // MetricsService. In that case it's fine to skip the update. + auto metrics_service = g_browser_process->metrics_service(); + if (metrics_service) { + metrics_service->UpdateMetricsUsagePrefs(service_name, + message_size, + is_cellular); + } + }, + service_name, + message_size, + is_cellular)); +} + } // namespace class SystemURLRequestContextGetter : public net::URLRequestContextGetter { @@ -405,14 +431,6 @@ if (value) value->GetAsBoolean(&http_09_on_non_default_ports_enabled_); - // Some unit tests use IOThread but do not initialize MetricsService. In that - // case it is fine not to have |metrics_data_use_forwarder_|. - if (g_browser_process->metrics_service()) { - // Callback for updating data use prefs should be obtained on UI thread. - metrics_data_use_forwarder_ = - g_browser_process->metrics_service()->GetDataUseForwardingCallback(); - } - chrome_browser_net::SetGlobalSTHDistributor( std::unique_ptr<net::ct::STHDistributor>(new net::ct::STHDistributor())); @@ -531,7 +549,7 @@ globals_->system_network_delegate = globals_->data_use_ascriber->CreateNetworkDelegate( - std::move(chrome_network_delegate), metrics_data_use_forwarder_); + std::move(chrome_network_delegate), GetMetricsDataUseForwarder()); globals_->host_resolver = CreateGlobalHostResolver(net_log_); @@ -1078,7 +1096,6 @@ return context; } -const metrics::UpdateUsagePrefCallbackType& -IOThread::GetMetricsDataUseForwarder() { - return metrics_data_use_forwarder_; +metrics::UpdateUsagePrefCallbackType IOThread::GetMetricsDataUseForwarder() { + return base::Bind(&UpdateMetricsUsagePrefsOnUIThread); }
diff --git a/chrome/browser/io_thread.h b/chrome/browser/io_thread.h index 78102bb..c958b64 100644 --- a/chrome/browser/io_thread.h +++ b/chrome/browser/io_thread.h
@@ -239,7 +239,7 @@ base::TimeTicks creation_time() const; // Returns the callback for updating data use prefs. - const metrics::UpdateUsagePrefCallbackType& GetMetricsDataUseForwarder(); + metrics::UpdateUsagePrefCallbackType GetMetricsDataUseForwarder(); // Registers the |observer| for new STH notifications. void RegisterSTHObserver(net::ct::STHObserver* observer); @@ -399,10 +399,6 @@ const base::TimeTicks creation_time_; - // Callback for updating data use prefs which needs to be initialized on UI - // thread and passed to |DataUseNetworkDelegate|. - metrics::UpdateUsagePrefCallbackType metrics_data_use_forwarder_; - base::WeakPtrFactory<IOThread> weak_factory_; DISALLOW_COPY_AND_ASSIGN(IOThread);
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc index dcb8b86..afa66a9 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -217,11 +217,12 @@ content::ResourceType ResourcePrefetchPredictor::GetResourceType( content::ResourceType resource_type, const std::string& mime_type) { - // Restricts content::RESOURCE_TYPE_{PREFETCH,SUB_RESOURCE} to a small set of - // mime types, because these resource types don't communicate how the + // Restricts content::RESOURCE_TYPE_{PREFETCH,SUB_RESOURCE,XHR} to a small set + // of mime types, because these resource types don't communicate how the // resources will be used. if (resource_type == content::RESOURCE_TYPE_PREFETCH || - resource_type == content::RESOURCE_TYPE_SUB_RESOURCE) { + resource_type == content::RESOURCE_TYPE_SUB_RESOURCE || + resource_type == content::RESOURCE_TYPE_XHR) { return GetResourceTypeFromMimeType(mime_type, content::RESOURCE_TYPE_LAST_TYPE); }
diff --git a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc index 4ad1343e..bf1e160 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor_unittest.cc
@@ -1163,6 +1163,12 @@ content::RESOURCE_TYPE_PREFETCH, "application/font-woff")); EXPECT_TRUE(ResourcePrefetchPredictor::IsHandledResourceType( content::RESOURCE_TYPE_PREFETCH, "font/woff2")); + EXPECT_FALSE(ResourcePrefetchPredictor::IsHandledResourceType( + content::RESOURCE_TYPE_XHR, "")); + EXPECT_FALSE(ResourcePrefetchPredictor::IsHandledResourceType( + content::RESOURCE_TYPE_XHR, "bogus/mime-type")); + EXPECT_TRUE(ResourcePrefetchPredictor::IsHandledResourceType( + content::RESOURCE_TYPE_XHR, "application/javascript")); } TEST_F(ResourcePrefetchPredictorTest, ShouldRecordRequestMainFrame) {
diff --git a/chrome/browser/printing/pdf_to_emf_converter.cc b/chrome/browser/printing/pdf_to_emf_converter.cc index 0a0eb09..fb0be32 100644 --- a/chrome/browser/printing/pdf_to_emf_converter.cc +++ b/chrome/browser/printing/pdf_to_emf_converter.cc
@@ -340,7 +340,7 @@ if (!utility_process_host_ || !pdf) return OnFailed(); // Should reply with OnPageCount(). - Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Start( + Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_, print_text_with_gdi)); }
diff --git a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc index 034580a..3260bb9c 100644 --- a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc +++ b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
@@ -335,25 +335,25 @@ // Converts the PDF to a PNG file so that the layout test can do an image // diff on this image and a reference image. void PdfToPng() { - std::string pdf_data; - ASSERT_TRUE(base::ReadFileToString(pdf_file_save_path_, &pdf_data)); - int num_pages; double max_width_in_points = 0; - void* pdf_handle = nullptr; + std::vector<uint8_t> bitmap_data; + double total_height_in_pixels = 0; + std::string pdf_data; + + ASSERT_TRUE(base::ReadFileToString(pdf_file_save_path_, &pdf_data)); ASSERT_TRUE(chrome_pdf::GetPDFDocInfo(pdf_data.data(), pdf_data.size(), - &num_pages, &max_width_in_points, - &pdf_handle)); + &num_pages, &max_width_in_points)); + ASSERT_GT(num_pages, 0); double max_width_in_pixels = ConvertUnitDouble(max_width_in_points, kPointsPerInch, kDpi); - std::vector<uint8_t> bitmap_data; - double total_height_in_pixels = 0; for (int i = 0; i < num_pages; ++i) { double width_in_points, height_in_points; ASSERT_TRUE(chrome_pdf::GetPDFPageSizeByIndex( - pdf_handle, i, &width_in_points, &height_in_points)); + pdf_data.data(), pdf_data.size(), i, &width_in_points, + &height_in_points)); double width_in_pixels = ConvertUnitDouble( width_in_points, kPointsPerInch, kDpi); @@ -384,8 +384,9 @@ settings.area.size().GetArea()); ASSERT_TRUE(chrome_pdf::RenderPDFPageToBitmap( - pdf_handle, i, page_bitmap_data.data(), settings.area.size().width(), - settings.area.size().height(), settings.dpi, settings.autorotate)); + pdf_data.data(), pdf_data.size(), i, page_bitmap_data.data(), + settings.area.size().width(), settings.area.size().height(), + settings.dpi, settings.autorotate)); FillPng(&page_bitmap_data, width_in_pixels, max_width_in_pixels, settings.area.size().height()); bitmap_data.insert(bitmap_data.end(), @@ -393,7 +394,6 @@ page_bitmap_data.end()); } - chrome_pdf::ReleasePDFHandle(pdf_handle); CreatePng(bitmap_data, max_width_in_pixels, total_height_in_pixels); }
diff --git a/chrome/browser/resources/settings/people_page/import_data_dialog.html b/chrome/browser/resources/settings/people_page/import_data_dialog.html index b3a0420..dbe888f5 100644 --- a/chrome/browser/resources/settings/people_page/import_data_dialog.html +++ b/chrome/browser/resources/settings/people_page/import_data_dialog.html
@@ -34,7 +34,7 @@ width: 100%; } </style> - <dialog is="cr-dialog" id="dialog"> + <dialog is="cr-dialog" id="dialog" ignore-popstate> <div class="title">$i18n{importTitle}</div> <div class="body"> <div hidden$="[[!hasImportStatus_(
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc index caed578f..ca88541 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -21,8 +21,8 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/pref_names.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc index bbe5c1a..c1af322 100644 --- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -20,9 +20,9 @@ #include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/test_database_manager.h" #include "content/public/browser/navigation_entry.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc index b6ffc666..df4e6e5 100644 --- a/chrome/browser/safe_browsing/client_side_detection_service.cc +++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -22,9 +22,9 @@ #include "chrome/common/pref_names.h" #include "chrome/common/safe_browsing/client_model.pb.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "components/data_use_measurement/core/data_use_user_data.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h"
diff --git a/chrome/browser/safe_browsing/client_side_model_loader.cc b/chrome/browser/safe_browsing/client_side_model_loader.cc index 91bbddf..5519b4108 100644 --- a/chrome/browser/safe_browsing/client_side_model_loader.cc +++ b/chrome/browser/safe_browsing/client_side_model_loader.cc
@@ -16,11 +16,11 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/safe_browsing/protocol_manager.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/safe_browsing/client_model.pb.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "components/data_use_measurement/core/data_use_user_data.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/variations/variations_associated_data.h" #include "net/http/http_response_headers.h" #include "net/http/http_status_code.h" @@ -195,7 +195,7 @@ void ModelLoader::ScheduleFetch(int64_t delay_ms) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSbDisableAutoUpdate)) + safe_browsing::switches::kSbDisableAutoUpdate)) return; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE,
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc index 4d882c2..1aa5e7f 100644 --- a/chrome/browser/safe_browsing/download_protection_service.cc +++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -40,7 +40,6 @@ #include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome/common/safe_browsing/csd.pb.h" @@ -52,6 +51,7 @@ #include "components/google/core/browser/google_util.h" #include "components/history/core/browser/history_service.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/download_item.h" @@ -1538,11 +1538,12 @@ void DownloadProtectionService::ParseManualBlacklistFlag() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (!command_line->HasSwitch(switches::kSbManualDownloadBlacklist)) + if (!command_line->HasSwitch( + safe_browsing::switches::kSbManualDownloadBlacklist)) return; - std::string flag_val = - command_line->GetSwitchValueASCII(switches::kSbManualDownloadBlacklist); + std::string flag_val = command_line->GetSwitchValueASCII( + safe_browsing::switches::kSbManualDownloadBlacklist); for (const std::string& hash_hex : base::SplitString( flag_val, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) { std::vector<uint8_t> bytes; @@ -1551,7 +1552,7 @@ std::string(bytes.begin(), bytes.end())); } else { LOG(FATAL) << "Bad sha256 hex value '" << hash_hex << "' found in --" - << switches::kSbManualDownloadBlacklist; + << safe_browsing::switches::kSbManualDownloadBlacklist; } } }
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc index ab42fed4..1b44858b 100644 --- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -33,13 +33,13 @@ #include "chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.h" #include "chrome/browser/safe_browsing/local_database_manager.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/safe_browsing/binary_feature_extractor.h" #include "chrome/common/safe_browsing/csd.pb.h" #include "chrome/common/safe_browsing/file_type_policies_test_util.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_service.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "components/safe_browsing_db/test_database_manager.h" @@ -2252,7 +2252,7 @@ blacklisted_hash_ = std::string(bytes.begin(), bytes.end()); base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - switches::kSbManualDownloadBlacklist, + safe_browsing::switches::kSbManualDownloadBlacklist, blacklisted_hash_hex_); DownloadProtectionServiceTest::SetUp();
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc index 181c88b..49b194f1 100644 --- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc +++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder_unittest.cc
@@ -32,7 +32,6 @@ #include "chrome/browser/history/web_history_service_factory.h" #include "chrome/browser/prefs/browser_prefs.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/common/chrome_constants.h" #include "chrome/common/pref_names.h" #include "chrome/common/safe_browsing/csd.pb.h" #include "chrome/test/base/testing_browser_process.h"
diff --git a/chrome/browser/safe_browsing/local_database_manager.cc b/chrome/browser/safe_browsing/local_database_manager.cc index 47a05bb..615a7b60 100644 --- a/chrome/browser/safe_browsing/local_database_manager.cc +++ b/chrome/browser/safe_browsing/local_database_manager.cc
@@ -28,11 +28,11 @@ #include "chrome/browser/safe_browsing/safe_browsing_database.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/ui_manager.h" -#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "components/safe_browsing_db/util.h" #include "components/safe_browsing_db/v4_protocol_manager_util.h" @@ -287,20 +287,20 @@ DCHECK(sb_service_.get() != NULL); base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); - enable_download_protection_ = - !cmdline->HasSwitch(switches::kSbDisableDownloadProtection); + enable_download_protection_ = !cmdline->HasSwitch( + safe_browsing::switches::kSbDisableDownloadProtection); // We only download the csd-whitelist if client-side phishing detection is // enabled. enable_csd_whitelist_ = - !cmdline->HasSwitch(switches::kDisableClientSidePhishingDetection); + !cmdline->HasSwitch(::switches::kDisableClientSidePhishingDetection); // We download the download-whitelist if download protection is enabled. enable_download_whitelist_ = enable_download_protection_; // TODO(kalman): there really shouldn't be a flag for this. - enable_extension_blacklist_ = - !cmdline->HasSwitch(switches::kSbDisableExtensionBlacklist); + enable_extension_blacklist_ = !cmdline->HasSwitch( + safe_browsing::switches::kSbDisableExtensionBlacklist); // The client-side IP blacklist feature is tightly integrated with client-side // phishing protection for now.
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index a5aa510..b755372d 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -29,14 +29,14 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/safe_browsing/ping_manager.h" #include "chrome/browser/safe_browsing/ui_manager.h" -#include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/safe_browsing/file_type_policies.h" -#include "chrome/common/url_constants.h" #include "components/prefs/pref_change_registrar.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_constants.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/safe_browsing_prefs.h" #include "components/safe_browsing_db/v4_get_hash_protocol_manager.h" @@ -269,7 +269,7 @@ base::FilePath path; bool result = PathService::Get(chrome::DIR_USER_DATA, &path); DCHECK(result); - return path.Append(chrome::kSafeBrowsingBaseFilename); + return path.Append(safe_browsing::kSafeBrowsingBaseFilename); } @@ -470,8 +470,8 @@ base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); config.disable_auto_update = - cmdline->HasSwitch(switches::kSbDisableAutoUpdate) || - cmdline->HasSwitch(switches::kDisableBackgroundNetworking); + cmdline->HasSwitch(safe_browsing::switches::kSbDisableAutoUpdate) || + cmdline->HasSwitch(::switches::kDisableBackgroundNetworking); config.url_prefix = kSbDefaultURLPrefix; config.backup_connect_error_url_prefix = kSbBackupConnectErrorURLPrefix; config.backup_http_error_url_prefix = kSbBackupHttpErrorURLPrefix; @@ -485,7 +485,7 @@ base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); return V4ProtocolConfig( GetProtocolConfigClientName(), - cmdline->HasSwitch(switches::kDisableBackgroundNetworking), + cmdline->HasSwitch(::switches::kDisableBackgroundNetworking), google_apis::GetAPIKey(), SafeBrowsingProtocolManagerHelper::Version()); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc index cafd60320..de76e8f 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service_browsertest.cc
@@ -43,13 +43,13 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_paths.h" -#include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/bookmarks/browser/startup_task_runner_service.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "components/safe_browsing_db/database_manager.h" #include "components/safe_browsing_db/metadata.pb.h" #include "components/safe_browsing_db/test_database_manager.h" @@ -545,7 +545,7 @@ // Makes sure the auto update is not triggered during the test. // This test will fill up the database using testing prefixes // and urls. - command_line->AppendSwitch(switches::kSbDisableAutoUpdate); + command_line->AppendSwitch(safe_browsing::switches::kSbDisableAutoUpdate); #if defined(OS_CHROMEOS) command_line->AppendSwitch( chromeos::switches::kIgnoreUserProfileMappingForTests);
diff --git a/chrome/browser/safe_browsing/threat_details.cc b/chrome/browser/safe_browsing/threat_details.cc index faba4da..d134b30 100644 --- a/chrome/browser/safe_browsing/threat_details.cc +++ b/chrome/browser/safe_browsing/threat_details.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/threat_details_cache.h" #include "chrome/browser/safe_browsing/threat_details_history.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h"
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc index 331ebda..301048e 100644 --- a/chrome/browser/safe_browsing/threat_details_unittest.cc +++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
@@ -18,11 +18,11 @@ #include "chrome/browser/safe_browsing/threat_details_history.h" #include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" #include "components/history/core/browser/history_backend.h" #include "components/history/core/browser/history_service.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/test/web_contents_tester.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 49a9555c..d6f6705 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -3220,6 +3220,7 @@ sources += [ "app_list/arc/arc_app_context_menu.cc", "app_list/arc/arc_app_context_menu.h", + "app_list/arc/arc_app_dialog.h", "app_list/arc/arc_app_icon.cc", "app_list/arc/arc_app_icon.h", "app_list/arc/arc_app_icon_loader.cc", @@ -3260,6 +3261,7 @@ "ash/launcher/arc_launcher_context_menu.h", "ash/launcher/launcher_arc_app_updater.cc", "ash/launcher/launcher_arc_app_updater.h", + "views/arc_app_dialog_view.cc", ] } if (is_desktop_linux) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc b/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc index ea1dd53e..961673c4 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_context_menu.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/ui/app_list/arc/arc_app_context_menu.h" +#include "base/bind.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/app_context_menu_delegate.h" #include "chrome/browser/ui/app_list/app_list_controller_delegate.h" +#include "chrome/browser/ui/app_list/arc/arc_app_dialog.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" #include "chrome/browser/ui/ash/launcher/arc_app_window_launcher_controller.h" @@ -82,7 +84,7 @@ ArcAppWindowLauncherController::GetShelfAppIdFromArcAppId(app_id())); break; case UNINSTALL: - UninstallPackage(); + arc::ShowArcAppUninstallDialog(profile(), controller(), app_id()); break; case SHOW_APP_INFO: ShowPackageInfo(); @@ -92,23 +94,6 @@ } } -void ArcAppContextMenu::UninstallPackage() { - ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile()); - DCHECK(arc_prefs); - std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = - arc_prefs->GetApp(app_id()); - if (!app_info) { - VLOG(2) << "Package being uninstalled does not exist: " << app_id() << "."; - return; - } - if (app_info->shortcut) { - // for shortcut we just remove the shortcut instead of the package - arc_prefs->RemoveApp(app_id()); - } else { - arc::UninstallPackage(app_info->package_name); - } -} - void ArcAppContextMenu::ShowPackageInfo() { const ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile()); DCHECK(arc_prefs);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_context_menu.h b/chrome/browser/ui/app_list/arc/arc_app_context_menu.h index 2cf39f4..e57352b 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_context_menu.h +++ b/chrome/browser/ui/app_list/arc/arc_app_context_menu.h
@@ -34,7 +34,6 @@ private: void IsAppOpen(); - void UninstallPackage(); void ShowPackageInfo(); DISALLOW_COPY_AND_ASSIGN(ArcAppContextMenu);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_dialog.h b/chrome/browser/ui/app_list/arc/arc_app_dialog.h new file mode 100644 index 0000000..e6e5476 --- /dev/null +++ b/chrome/browser/ui/app_list/arc/arc_app_dialog.h
@@ -0,0 +1,31 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_DIALOG_H_ +#define CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_DIALOG_H_ + +#include <string> + +#include "base/callback.h" + +class AppListControllerDelegate; +class Profile; + +namespace arc { + +// Shows a dialog for user to confirm uninstallation of Arc app. +// Currently, Arc app can only be manually uninstalled from AppList. But it +// would be simple to enable the dialog to shown from other source. +void ShowArcAppUninstallDialog(Profile* profile, + AppListControllerDelegate* controller, + const std::string& app_id); + +// Test purpose methods. +bool IsArcAppDialogViewAliveForTest(); + +bool CloseAppDialogViewAndConfirmForTest(bool confirm); + +} // namespace arc + +#endif // CHROME_BROWSER_UI_APP_LIST_ARC_ARC_APP_DIALOG_H_
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc index 12b6727..2477258 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -12,6 +12,7 @@ #include "base/json/json_writer.h" #include "base/synchronization/waitable_event.h" #include "base/values.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" #include "chrome/browser/ui/ash/launcher/arc_app_deferred_launcher_controller.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" @@ -392,6 +393,22 @@ app_instance->UninstallPackage(package_name); } +void UninstallArcApp(const std::string& app_id, Profile* profile) { + ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile); + DCHECK(arc_prefs); + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = + arc_prefs->GetApp(app_id); + if (!app_info) { + VLOG(2) << "Package being uninstalled does not exist: " << app_id << "."; + return; + } + // For shortcut we just remove the shortcut instead of the package. + if (app_info->shortcut) + arc_prefs->RemoveApp(app_id); + else + UninstallPackage(app_info->package_name); +} + void RemoveCachedIcon(const std::string& icon_resource_id) { VLOG(2) << "Removing icon " << icon_resource_id;
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h index 389a0537..103f208 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_utils.h +++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -11,6 +11,8 @@ #include "components/arc/common/app.mojom.h" #include "ui/gfx/geometry/rect.h" +class Profile; + namespace content { class BrowserContext; } @@ -70,6 +72,9 @@ // Uninstalls the package in ARC. void UninstallPackage(const std::string& package_name); +// Uninstalls Arc app or removes shortcut. +void UninstallArcApp(const std::string& app_id, Profile* profile); + // Removes cached app shortcut icon in ARC. void RemoveCachedIcon(const std::string& icon_resource_id);
diff --git a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm index 44c9f59..1373245 100644 --- a/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm +++ b/chrome/browser/ui/cocoa/fullscreen/fullscreen_toolbar_controller.mm
@@ -106,12 +106,12 @@ case FullscreenToolbarStyle::TOOLBAR_NONE: return kHideFraction; case FullscreenToolbarStyle::TOOLBAR_HIDDEN: - if ([self mustShowFullscreenToolbar]) - return kShowFraction; - if (animationController_->IsAnimationRunning()) return animationController_->GetToolbarFractionFromProgress(); + if ([self mustShowFullscreenToolbar]) + return kShowFraction; + return [menubarTracker_ menubarFraction]; } }
diff --git a/chrome/browser/ui/views/arc_app_dialog_view.cc b/chrome/browser/ui/views/arc_app_dialog_view.cc new file mode 100644 index 0000000..e18be654 --- /dev/null +++ b/chrome/browser/ui/views/arc_app_dialog_view.cc
@@ -0,0 +1,292 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/app_list/arc/arc_app_dialog.h" + +#include "base/bind.h" +#include "base/macros.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/extensions/extension_util.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" +#include "chrome/browser/ui/app_list/arc/arc_app_icon_loader.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ui/native_window_tracker.h" +#include "chrome/grit/generated_resources.h" +#include "components/constrained_window/constrained_window_views.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/ui_base_types.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/layout_constants.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/window/dialog_delegate.h" + +namespace arc { + +namespace { + +const int kRightColumnWidth = 210; +const int kIconSize = 64; + +using ArcAppConfirmCallback = + base::Callback<void(const std::string& app_id, Profile* profile)>; + +class ArcAppDialogView : public views::DialogDelegateView, + public AppIconLoaderDelegate { + public: + ArcAppDialogView(Profile* profile, + AppListControllerDelegate* controller, + const std::string& app_id, + const base::string16& window_title, + const base::string16& heading_text, + const base::string16& confirm_button_text, + const base::string16& cancel_button_text, + ArcAppConfirmCallback confirm_callback); + ~ArcAppDialogView() override; + + // Public method used for test only. + void ConfirmOrCancelForTest(bool confirm); + + private: + // views::WidgetDelegate: + base::string16 GetWindowTitle() const override; + void DeleteDelegate() override; + ui::ModalType GetModalType() const override; + + // views::View: + gfx::Size GetPreferredSize() const override; + void Layout() override; + + // views::DialogDelegate: + base::string16 GetDialogButtonLabel(ui::DialogButton button) const override; + bool Accept() override; + + // AppIconLoaderDelegate: + void OnAppImageUpdated(const std::string& app_id, + const gfx::ImageSkia& image) override; + + // Constructs and shows the modal dialog widget. + void Show(); + + bool initial_setup_ = true; + + views::ImageView* icon_view_ = nullptr; + views::Label* heading_view_ = nullptr; + + std::unique_ptr<ArcAppIconLoader> icon_loader_; + + Profile* const profile_; + + AppListControllerDelegate* controller_; + + gfx::NativeWindow parent_; + + // Tracks whether |parent_| got destroyed. + std::unique_ptr<NativeWindowTracker> parent_window_tracker_; + + const std::string app_id_; + const base::string16 window_title_; + const base::string16 confirm_button_text_; + const base::string16 cancel_button_text_; + ArcAppConfirmCallback confirm_callback_; + + DISALLOW_COPY_AND_ASSIGN(ArcAppDialogView); +}; + +// Browertest use only. Global pointer of ArcAppDialogView which is shown. +ArcAppDialogView* g_current_arc_app_dialog_view = nullptr; + +ArcAppDialogView::ArcAppDialogView(Profile* profile, + AppListControllerDelegate* controller, + const std::string& app_id, + const base::string16& window_title, + const base::string16& heading_text, + const base::string16& confirm_button_text, + const base::string16& cancel_button_text, + ArcAppConfirmCallback confirm_callback) + : profile_(profile), + controller_(controller), + app_id_(app_id), + window_title_(window_title), + confirm_button_text_(confirm_button_text), + cancel_button_text_(cancel_button_text), + confirm_callback_(confirm_callback) { + DCHECK(controller); + parent_ = controller_->GetAppListWindow(); + if (parent_) + parent_window_tracker_ = NativeWindowTracker::Create(parent_); + + icon_view_ = new views::ImageView(); + icon_view_->SetImageSize(gfx::Size(kIconSize, kIconSize)); + AddChildView(icon_view_); + + heading_view_ = new views::Label(heading_text); + heading_view_->SetMultiLine(true); + heading_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT); + heading_view_->SetAllowCharacterBreak(true); + AddChildView(heading_view_); + + icon_loader_.reset(new ArcAppIconLoader(profile_, kIconSize, this)); + // The dialog will show once the icon is loaded. + icon_loader_->FetchImage(app_id_); +} + +ArcAppDialogView::~ArcAppDialogView() { + DCHECK_EQ(this, g_current_arc_app_dialog_view); + g_current_arc_app_dialog_view = nullptr; +} + +void ArcAppDialogView::ConfirmOrCancelForTest(bool confirm) { + if (confirm) + Accept(); + else + Cancel(); + GetWidget()->Close(); +} + +base::string16 ArcAppDialogView::GetWindowTitle() const { + return window_title_; +} + +void ArcAppDialogView::DeleteDelegate() { + if (controller_) + controller_->OnCloseChildDialog(); + DialogDelegateView::DeleteDelegate(); +} + +ui::ModalType ArcAppDialogView::GetModalType() const { + return ui::MODAL_TYPE_WINDOW; +} + +// TODO(lgcheng@) The code below is copied from +// ExtensionUninstallDialogDelegateView sizing and layout code. Use +// LayoutManager to relace these manual layout. See crbug.com/670110. +gfx::Size ArcAppDialogView::GetPreferredSize() const { + int width = kRightColumnWidth; + width += kIconSize; + width += views::kButtonHEdgeMarginNew * 2; + width += views::kRelatedControlHorizontalSpacing; + + int height = views::kPanelVertMargin * 2; + height += heading_view_->GetHeightForWidth(kRightColumnWidth); + + return gfx::Size(width, + std::max(height, kIconSize + views::kPanelVertMargin * 2)); +} + +void ArcAppDialogView::Layout() { + int x = views::kButtonHEdgeMarginNew; + int y = views::kPanelVertMargin; + + heading_view_->SizeToFit(kRightColumnWidth); + + if (heading_view_->height() <= kIconSize) { + icon_view_->SetBounds(x, y, kIconSize, kIconSize); + x += kIconSize; + x += views::kRelatedControlHorizontalSpacing; + + heading_view_->SetX(x); + heading_view_->SetY(y + (kIconSize - heading_view_->height()) / 2); + } else { + icon_view_->SetBounds(x, y + (heading_view_->height() - kIconSize) / 2, + kIconSize, kIconSize); + x += kIconSize; + x += views::kRelatedControlHorizontalSpacing; + + heading_view_->SetX(x); + heading_view_->SetY(y); + } +} + +base::string16 ArcAppDialogView::GetDialogButtonLabel( + ui::DialogButton button) const { + return button == ui::DIALOG_BUTTON_CANCEL ? cancel_button_text_ + : confirm_button_text_; +} + +bool ArcAppDialogView::Accept() { + confirm_callback_.Run(app_id_, profile_); + return true; +} + +void ArcAppDialogView::OnAppImageUpdated(const std::string& app_id, + const gfx::ImageSkia& image) { + DCHECK_EQ(app_id, app_id_); + DCHECK(!image.isNull()); + + icon_view_->SetImage(image); + + if (initial_setup_) + Show(); +} + +void ArcAppDialogView::Show() { + initial_setup_ = false; + + // The parent window was killed before the icon was loaded. + if (parent_ && parent_window_tracker_->WasNativeWindowClosed()) { + Cancel(); + DialogDelegateView::DeleteDelegate(); + return; + } + + if (controller_) + controller_->OnShowChildDialog(); + + g_current_arc_app_dialog_view = this; + constrained_window::CreateBrowserModalDialogViews(this, parent_)->Show(); +} + +} // namespace + +void ShowArcAppUninstallDialog(Profile* profile, + AppListControllerDelegate* controller, + const std::string& app_id) { + ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile); + DCHECK(arc_prefs); + std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = + arc_prefs->GetApp(app_id); + + if (!app_info) + return; + + bool is_shortcut = app_info->shortcut; + + base::string16 window_title = l10n_util::GetStringUTF16( + is_shortcut ? IDS_EXTENSION_UNINSTALL_PROMPT_TITLE + : IDS_APP_UNINSTALL_PROMPT_TITLE); + + base::string16 heading_text = base::UTF8ToUTF16(l10n_util::GetStringFUTF8( + is_shortcut ? IDS_EXTENSION_UNINSTALL_PROMPT_HEADING + : IDS_ARC_APP_UNINSTALL_PROMPT_HEADING, + base::UTF8ToUTF16(app_info->name))); + + base::string16 confirm_button_text = l10n_util::GetStringUTF16( + is_shortcut ? IDS_EXTENSION_PROMPT_UNINSTALL_BUTTON + : IDS_EXTENSION_PROMPT_UNINSTALL_APP_BUTTON); + + base::string16 cancel_button_text = l10n_util::GetStringUTF16(IDS_CANCEL); + + new ArcAppDialogView(profile, controller, app_id, window_title, heading_text, + confirm_button_text, cancel_button_text, + base::Bind(UninstallArcApp)); +} + +bool IsArcAppDialogViewAliveForTest() { + return g_current_arc_app_dialog_view != nullptr; +} + +bool CloseAppDialogViewAndConfirmForTest(bool confirm) { + if (!g_current_arc_app_dialog_view) + return false; + + g_current_arc_app_dialog_view->ConfirmOrCancelForTest(confirm); + return true; +} + +} // namespace arc
diff --git a/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc b/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc new file mode 100644 index 0000000..3fd3dc4 --- /dev/null +++ b/chrome/browser/ui/views/arc_app_dialog_view_browsertest.cc
@@ -0,0 +1,183 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/app_list/arc/arc_app_dialog.h" + +#include "base/command_line.h" +#include "base/macros.h" +#include "chrome/browser/chromeos/arc/arc_session_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" +#include "chrome/browser/ui/app_list/app_list_service.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" +#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" +#include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chromeos/chromeos_switches.h" +#include "components/arc/arc_bridge_service.h" +#include "components/arc/common/app.mojom.h" +#include "components/arc/test/fake_app_instance.h" +#include "content/public/test/test_utils.h" + +namespace arc { + +class ArcAppUninstallDialogViewBrowserTest : public InProcessBrowserTest { + public: + ArcAppUninstallDialogViewBrowserTest() {} + + // InProcessBrowserTest: + ~ArcAppUninstallDialogViewBrowserTest() override {} + + void SetUpAppInstance() { + profile_ = browser()->profile(); + + base::CommandLine::ForCurrentProcess()->AppendSwitch( + chromeos::switches::kEnableArc); + + // A valid |arc_app_list_prefs_| is needed for the Arc bridge service and + // the Arc session manager. + arc_app_list_pref_ = ArcAppListPrefs::Get(profile_); + if (!arc_app_list_pref_) { + ArcAppListPrefsFactory::GetInstance()->RecreateServiceInstanceForTesting( + profile_); + } + + DCHECK(ArcBridgeService::Get()); + ArcSessionManager* session_manager = ArcSessionManager::Get(); + DCHECK(session_manager); + ArcSessionManager::DisableUIForTesting(); + session_manager->OnPrimaryUserProfilePrepared(profile_); + session_manager->EnableArc(); + + arc_app_list_pref_ = ArcAppListPrefs::Get(profile_); + DCHECK(arc_app_list_pref_); + + base::RunLoop run_loop; + arc_app_list_pref_->SetDefaltAppsReadyCallback(run_loop.QuitClosure()); + run_loop.Run(); + + app_instance_.reset(new arc::FakeAppInstance(arc_app_list_pref_)); + arc_app_list_pref_->app_instance_holder()->SetInstance(app_instance_.get()); + + // In this setup, we have one app and one shortcut which share one package. + mojom::AppInfo app; + app.name = base::StringPrintf("Fake App %d", 0); + app.package_name = base::StringPrintf("fake.package.%d", 0); + app.activity = base::StringPrintf("fake.app.%d.activity", 0); + app.sticky = false; + app_instance_->SendRefreshAppList(std::vector<mojom::AppInfo>(1, app)); + + mojom::ShortcutInfo shortcut; + shortcut.name = base::StringPrintf("Fake Shortcut %d", 0); + shortcut.package_name = base::StringPrintf("fake.package.%d", 0); + shortcut.intent_uri = base::StringPrintf("Fake Shortcut uri %d", 0); + app_instance_->SendInstallShortcut(shortcut); + + mojom::ArcPackageInfo package; + package.package_name = base::StringPrintf("fake.package.%d", 0); + package.package_version = 0; + package.last_backup_android_id = 0; + package.last_backup_time = 0; + package.sync = false; + app_instance_->SendRefreshPackageList( + std::vector<mojom::ArcPackageInfo>(1, package)); + } + + void TearDownOnMainThread() override { + ArcSessionManager::Get()->Shutdown(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + // Ensures the ArcAppDialogView is destoryed. + void TearDown() override { ASSERT_FALSE(IsArcAppDialogViewAliveForTest()); } + + ArcAppListPrefs* arc_app_list_pref() { return arc_app_list_pref_; } + + FakeAppInstance* instance() { return app_instance_.get(); } + + private: + ArcAppListPrefs* arc_app_list_pref_ = nullptr; + + Profile* profile_ = nullptr; + + std::unique_ptr<arc::FakeAppInstance> app_instance_; + + DISALLOW_COPY_AND_ASSIGN(ArcAppUninstallDialogViewBrowserTest); +}; + +// User confirms/cancels Arc app uninstall. Note that the shortcut is removed +// when the app and the package are uninstalled since the shortcut and the app +// share same package. +IN_PROC_BROWSER_TEST_F(ArcAppUninstallDialogViewBrowserTest, + UserConfirmsUninstall) { + SetUpAppInstance(); + + std::vector<std::string> app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 2u); + std::string package_name = base::StringPrintf("fake.package.%d", 0); + std::string app_activity = base::StringPrintf("fake.app.%d.activity", 0); + std::string app_id = + arc_app_list_pref()->GetAppId(package_name, app_activity); + + AppListService* service = AppListService::Get(); + ASSERT_TRUE(service); + service->ShowForProfile(browser()->profile()); + AppListControllerDelegate* controller(service->GetControllerDelegate()); + ASSERT_TRUE(controller); + ShowArcAppUninstallDialog(browser()->profile(), controller, app_id); + content::RunAllPendingInMessageLoop(); + + EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(false)); + content::RunAllPendingInMessageLoop(); + app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 2u); + + ShowArcAppUninstallDialog(browser()->profile(), controller, app_id); + content::RunAllPendingInMessageLoop(); + + EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(true)); + content::RunAllPendingInMessageLoop(); + app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 0u); + controller->DismissView(); +} + +// User confirms/cancels Arc app shortcut removal. Note that the app is not +// uninstalled when the shortcut is removed. +IN_PROC_BROWSER_TEST_F(ArcAppUninstallDialogViewBrowserTest, + UserConfirmsUninstallShortcut) { + SetUpAppInstance(); + + std::vector<std::string> app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 2u); + std::string package_name = base::StringPrintf("fake.package.%d", 0); + std::string intent_uri = base::StringPrintf("Fake Shortcut uri %d", 0); + std::string app_id = arc_app_list_pref()->GetAppId(package_name, intent_uri); + + AppListService* service = AppListService::Get(); + ASSERT_TRUE(service); + service->ShowForProfile(browser()->profile()); + AppListControllerDelegate* controller(service->GetControllerDelegate()); + ASSERT_TRUE(controller); + ShowArcAppUninstallDialog(browser()->profile(), controller, app_id); + content::RunAllPendingInMessageLoop(); + + EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(false)); + content::RunAllPendingInMessageLoop(); + app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 2u); + + ShowArcAppUninstallDialog(browser()->profile(), controller, app_id); + content::RunAllPendingInMessageLoop(); + + EXPECT_TRUE(CloseAppDialogViewAndConfirmForTest(true)); + content::RunAllPendingInMessageLoop(); + app_ids = arc_app_list_pref()->GetAppIds(); + EXPECT_EQ(app_ids.size(), 1u); + controller->DismissView(); +} + +} // namespace arc
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 52d3b4b..3cecca312 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -86,10 +86,6 @@ const int kMaximizedWindowInset = 10; // DIPs. #if defined(USE_ASH) -void SetWindowPositionManaged(gfx::NativeWindow window, bool value) { - ash::wm::GetWindowState(window)->set_window_position_managed(value); -} - // Returns true if |tab_strip| browser window is docked. bool IsDockedOrSnapped(const TabStrip* tab_strip) { DCHECK(tab_strip); @@ -98,9 +94,6 @@ return window_state->IsDocked() || window_state->IsSnapped(); } #else -void SetWindowPositionManaged(gfx::NativeWindow window, bool value) { -} - bool IsDockedOrSnapped(const TabStrip* tab_strip) { return false; } @@ -137,18 +130,6 @@ (*rects)[i].set_x((*rects)[i].x() + x_offset); } -// WidgetObserver implementation that resets the window position managed -// property on Show. -// We're forced to do this here since BrowserFrameAsh resets the 'window -// position managed' property during a show and we need the property set to -// false before WorkspaceLayoutManager sees the visibility change. -class WindowPositionManagedUpdater : public views::WidgetObserver { - public: - void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override { - SetWindowPositionManaged(widget->GetNativeWindow(), false); - } -}; - // EscapeTracker installs an event monitor and runs a callback when it receives // the escape key. class EscapeTracker : public ui::EventHandler { @@ -236,7 +217,6 @@ if (move_loop_widget_) { if (added_observer_to_move_loop_widget_) move_loop_widget_->RemoveObserver(this); - SetWindowPositionManaged(move_loop_widget_->GetNativeWindow(), true); } if (source_tabstrip_) @@ -616,10 +596,6 @@ else target_tabstrip->GetWidget()->SetCapture(attached_tabstrip_); - // The window is going away. Since the drag is still on going we don't want - // that to effect the position of any windows. - SetWindowPositionManaged(browser_widget->GetNativeWindow(), false); - #if !defined(OS_LINUX) || defined(OS_CHROMEOS) // EndMoveLoop is going to snap the window back to its original location. // Hide it so users don't see this. Hiding a window in Linux aura causes @@ -1059,10 +1035,7 @@ AdjustBrowserAndTabBoundsForDrag(last_tabstrip_width, point_in_screen, &drag_bounds); - WindowPositionManagedUpdater updater; - dragged_widget->AddObserver(&updater); browser->window()->Show(); - dragged_widget->RemoveObserver(&updater); dragged_widget->SetVisibilityChangedAnimationsEnabled(true); // Activate may trigger a focus loss, destroying us. { @@ -1113,7 +1086,7 @@ return; if (move_loop_widget_) { move_loop_widget_->RemoveObserver(this); - move_loop_widget_ = NULL; + move_loop_widget_ = nullptr; } is_dragging_window_ = false; waiting_for_run_loop_to_exit_ = false; @@ -1353,11 +1326,6 @@ if (is_dragging_window_) { waiting_for_run_loop_to_exit_ = true; - if (type == NORMAL || (type == TAB_DESTROYED && drag_data_.size() > 1)) { - SetWindowPositionManaged(GetAttachedBrowserWidget()->GetNativeWindow(), - true); - } - // End the nested drag loop. GetAttachedBrowserWidget()->EndMoveLoop(); } @@ -1768,7 +1736,6 @@ create_params.initial_bounds = new_bounds; Browser* browser = new Browser(create_params); is_dragging_new_browser_ = true; - SetWindowPositionManaged(browser->window()->GetNativeWindow(), false); // If the window is created maximized then the bounds we supplied are ignored. // We need to reset them again so they are honored. browser->window()->SetBounds(new_bounds);
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 10d8081..0ad1004 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -9,7 +9,9 @@ #include <algorithm> #include "base/bind.h" +#include "base/bind_helpers.h" #include "base/callback.h" +#include "base/callback_helpers.h" #include "base/command_line.h" #include "base/location.h" #include "base/macros.h" @@ -796,18 +798,55 @@ } #endif +// Encapsulates waiting for the browser window to become maximized. This is +// needed for example on Chrome desktop linux, where window maximization is done +// asynchronously as an event received from a different process. +class MaximizedBrowserWindowWaiter { + public: + explicit MaximizedBrowserWindowWaiter(BrowserWindow* window) + : window_(window) {} + ~MaximizedBrowserWindowWaiter() = default; + + // Blocks until the browser window becomes maximized. + void Wait() { + if (CheckMaximized()) + return; + + base::RunLoop run_loop; + quit_ = run_loop.QuitClosure(); + run_loop.Run(); + } + + private: + bool CheckMaximized() { + if (!window_->IsMaximized()) { + base::MessageLoop::current()->task_runner()->PostTask( + FROM_HERE, base::Bind( + base::IgnoreResult(&MaximizedBrowserWindowWaiter::CheckMaximized), + base::Unretained(this))); + return false; + } + + // Quit the run_loop to end the wait. + if (!quit_.is_null()) + base::ResetAndReturn(&quit_).Run(); + return true; + } + + // The browser window observed by this waiter. + BrowserWindow* window_; + + // The waiter's RunLoop quit closure. + base::Closure quit_; + + DISALLOW_COPY_AND_ASSIGN(MaximizedBrowserWindowWaiter); +}; + } // namespace -#if defined(OS_CHROMEOS) || defined(OS_LINUX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 -#define MAYBE_DetachToOwnWindow DISABLED_DetachToOwnWindow -#else -#define MAYBE_DetachToOwnWindow DetachToOwnWindow -#endif // Drags from browser to separate window and releases mouse. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - MAYBE_DetachToOwnWindow) { + DetachToOwnWindow) { const gfx::Rect initial_bounds(browser()->window()->GetBounds()); // Add another tab. AddTabAndResetBrowser(browser()); @@ -860,9 +899,13 @@ EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); } -#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MACOSX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 +#if defined(OS_LINUX) || defined(OS_MACOSX) +// TODO(afakhry,varkha): Disabled on Linux as it fails on the bot because +// setting the window bounds to the work area bounds in +// DesktopWindowTreeHostX11::SetBounds() always insets it by one pixel in both +// width and height. This results in considering the source browser window not +// being full size, and the test is not as expected. +// crbug.com/626761, crbug.com/331924. // TODO(tapted,mblsha): Disabled as the Mac IsMaximized() behavior is not // consistent with other platforms. crbug.com/603562 #define MAYBE_DetachFromFullsizeWindow DISABLED_DetachFromFullsizeWindow @@ -923,6 +966,7 @@ // Only second window should be maximized. EXPECT_FALSE(browser()->window()->IsMaximized()); + MaximizedBrowserWindowWaiter(new_browser->window()).Wait(); EXPECT_TRUE(new_browser->window()->IsMaximized()); // The tab strip should no longer have capture because the drag was ended and @@ -931,9 +975,7 @@ EXPECT_FALSE(tab_strip2->GetWidget()->HasCapture()); } -#if defined(OS_CHROMEOS) || defined(OS_LINUX) || defined(OS_MACOSX) -// TODO(sky,sad): Disabled as it fails due to resize locks with a real -// compositor. crbug.com/331924 +#if defined(OS_MACOSX) // TODO(tapted,mblsha): Disabled as the Mac IsMaximized() behavior is not // consistent with other platforms. crbug.com/603562 #define MAYBE_DetachToOwnWindowFromMaximizedWindow \ @@ -947,6 +989,7 @@ MAYBE_DetachToOwnWindowFromMaximizedWindow) { // Maximize the initial browser window. browser()->window()->Maximize(); + MaximizedBrowserWindowWaiter(browser()->window()).Wait(); ASSERT_TRUE(browser()->window()->IsMaximized()); // Add another tab. @@ -990,6 +1033,7 @@ new_browser->window()->GetNativeWindow())); // The new window should be maximized. + MaximizedBrowserWindowWaiter(new_browser->window()).Wait(); EXPECT_TRUE(new_browser->window()->IsMaximized()); } @@ -2429,7 +2473,7 @@ // Drags from browser to separate window, docks that window and releases mouse. IN_PROC_BROWSER_TEST_P(DetachToBrowserTabDragControllerTest, - DISABLED_DetachToDockedWindowFromMaximizedWindow) { + DetachToDockedWindowFromMaximizedWindow) { // Maximize the initial browser window. browser()->window()->Maximize(); ASSERT_TRUE(browser()->window()->IsMaximized());
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn index e016c77..4b762851 100644 --- a/chrome/common/BUILD.gn +++ b/chrome/common/BUILD.gn
@@ -126,7 +126,6 @@ "render_messages.h", "resource_usage_reporter_type_converters.cc", "resource_usage_reporter_type_converters.h", - "safe_browsing/safebrowsing_messages.h", "search/instant_types.cc", "search/instant_types.h", "search/ntp_logging_events.h",
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc index ed6711e..29930ce 100644 --- a/chrome/common/chrome_constants.cc +++ b/chrome/common/chrome_constants.cc
@@ -161,8 +161,6 @@ const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[] = FPL("Protected Preferences"); const base::FilePath::CharType kReadmeFilename[] = FPL("README"); -const base::FilePath::CharType kSafeBrowsingBaseFilename[] = - FPL("Safe Browsing"); const base::FilePath::CharType kSecurePreferencesFilename[] = FPL("Secure Preferences"); const base::FilePath::CharType kServiceStateFileName[] = FPL("Service State");
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h index 8c845b5..53a3b71 100644 --- a/chrome/common/chrome_constants.h +++ b/chrome/common/chrome_constants.h
@@ -62,7 +62,6 @@ extern const base::FilePath::CharType kPreviewsOptOutDBFilename[]; extern const base::FilePath::CharType kProtectedPreferencesFilenameDeprecated[]; extern const base::FilePath::CharType kReadmeFilename[]; -extern const base::FilePath::CharType kSafeBrowsingBaseFilename[]; extern const base::FilePath::CharType kSecurePreferencesFilename[]; extern const base::FilePath::CharType kServiceStateFileName[]; extern const base::FilePath::CharType kSingletonCookieFilename[];
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc index 8dfd7855..14a1efcf 100644 --- a/chrome/common/chrome_switches.cc +++ b/chrome/common/chrome_switches.cc
@@ -820,32 +820,6 @@ // See http://crbug.com/120416 for how to remove this switch. const char kSavePageAsMHTML[] = "save-page-as-mhtml"; -// If present, safebrowsing only performs update when -// SafeBrowsingProtocolManager::ForceScheduleNextUpdate() is explicitly called. -// This is used for testing only. -const char kSbDisableAutoUpdate[] = "safebrowsing-disable-auto-update"; - -// TODO(lzheng): Remove this flag once the feature works fine -// (http://crbug.com/74848). -// -// Disables safebrowsing feature that checks download url and downloads -// content's hash to make sure the content are not malicious. -const char kSbDisableDownloadProtection[] = - "safebrowsing-disable-download-protection"; - -// Disables safebrowsing feature that checks for blacklisted extensions. -const char kSbDisableExtensionBlacklist[] = - "safebrowsing-disable-extension-blacklist"; - -// List of comma-separated sha256 hashes of executable files which the -// download-protection service should treat as "dangerous." For a file to -// show a warning, it also must be considered a dangerous filetype and not -// be whitelisted otherwise (by signature or URL) and must be on a supported -// OS. Hashes are in hex. This is used for manual testing when looking -// for ways to by-pass download protection. -const char kSbManualDownloadBlacklist[] = - "safebrowsing-manual-download-blacklist"; - // Causes the process to run as a service process. const char kServiceProcess[] = "service";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h index 61c2139d..7d12de903 100644 --- a/chrome/common/chrome_switches.h +++ b/chrome/common/chrome_switches.h
@@ -235,10 +235,6 @@ extern const char kRemoteDebuggingTargets[]; extern const char kRestoreLastSession[]; extern const char kSavePageAsMHTML[]; -extern const char kSbDisableAutoUpdate[]; -extern const char kSbDisableDownloadProtection[]; -extern const char kSbDisableExtensionBlacklist[]; -extern const char kSbManualDownloadBlacklist[]; extern const char kServiceProcess[]; extern const char kShowAppList[]; extern const char kSilentDebuggerExtensionAPI[];
diff --git a/chrome/common/chrome_utility_printing_messages.h b/chrome/common/chrome_utility_printing_messages.h index 1f374a75..f1a8ad7 100644 --- a/chrome/common/chrome_utility_printing_messages.h +++ b/chrome/common/chrome_utility_printing_messages.h
@@ -99,7 +99,7 @@ // Tell the utility process to start rendering the given PDF into a metafile. // Utility process would be alive until // ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop message. -IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Start, +IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_RenderPDFPagesToMetafiles, IPC::PlatformFileForTransit /* input_file */, printing::PdfRenderSettings /* settings */, bool /* print_text_with_gdi */)
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h index 91707a1..553c873 100644 --- a/chrome/common/common_message_generator.h +++ b/chrome/common/common_message_generator.h
@@ -11,7 +11,6 @@ #include "chrome/common/page_load_metrics/page_load_metrics_messages.h" #include "chrome/common/prerender_messages.h" #include "chrome/common/render_messages.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/common/tts_messages.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/common_param_traits_macros.h"
diff --git a/chrome/common/crash_keys.cc b/chrome/common/crash_keys.cc index 800f7045..db8e714 100644 --- a/chrome/common/crash_keys.cc +++ b/chrome/common/crash_keys.cc
@@ -82,6 +82,8 @@ const char kSendAction[] = "sendaction"; +const char kNSEvent[] = "nsevent"; + } // namespace mac #endif @@ -156,6 +158,7 @@ { mac::kNSException, kMediumSize }, { mac::kNSExceptionTrace, kMediumSize }, { mac::kSendAction, kMediumSize }, + { mac::kNSEvent, kMediumSize }, { mac::kZombie, kMediumSize }, { mac::kZombieTrace, kMediumSize }, // content/:
diff --git a/chrome/common/crash_keys.h b/chrome/common/crash_keys.h index 6f660312..a09783d 100644 --- a/chrome/common/crash_keys.h +++ b/chrome/common/crash_keys.h
@@ -130,6 +130,9 @@ // target-action. extern const char kSendAction[]; +// In the CrApplication, records information about the current event. +extern const char kNSEvent[]; + } // namespace mac #endif
diff --git a/chrome/common/extensions/api/certificate_provider.idl b/chrome/common/extensions/api/certificate_provider.idl index 4062d04..91096d3 100644 --- a/chrome/common/extensions/api/certificate_provider.idl +++ b/chrome/common/extensions/api/certificate_provider.idl
@@ -13,6 +13,21 @@ SHA512 }; + // The type of code being requested by the extension with requestPin function. + enum PinRequestType { + PIN, + PUK + }; + + // The types of errors that can be presented to the user through the + // requestPin function. + enum PinRequestErrorType { + INVALID_PIN, + INVALID_PUK, + MAX_ATTEMPTS_EXCEEDED, + UNKNOWN_ERROR + }; + [noinline_doc] dictionary CertificateInfo { // Must be the DER encoding of a X.509 certificate. Currently, only // certificates of RSA keys are supported. @@ -25,6 +40,10 @@ }; [noinline_doc] dictionary SignRequest { + // The unique ID to be used by the extension should it need to call a method + // that requires it, e.g. requestPin. + long signRequestId; + // The digest that must be signed. ArrayBuffer digest; @@ -36,6 +55,45 @@ ArrayBuffer certificate; }; + dictionary RequestPinDetails { + // The ID given by Chrome in SignRequest. + long signRequestId; + + // The type of code requested. Default is PIN. + PinRequestType? requestType; + + // The error template displayed to the user. This should be set if the + // previous request failed, to notify the user of the failure reason. + PinRequestErrorType? errorType; + + // The number of attempts left. This is provided so that any UI can present + // this information to the user. Chrome is not expected to enforce this, + // instead stopPinRequest should be called by the extension with + // errorType = MAX_ATTEMPTS_EXCEEDED when the number of pin requests is + // exceeded. + long? attemptsLeft; + }; + + dictionary StopPinRequestDetails { + // The ID given by Chrome in SignRequest. + long signRequestId; + + // The error template. If present it is displayed to user. Intended to + // contain the reason for stopping the flow if it was caused by an error, + // e.g. MAX_ATTEMPTS_EXCEEDED. + PinRequestErrorType? errorType; + }; + + dictionary PinResponseDetails { + // The code provided by the user. Empty if user closed the dialog or some + // other error occurred. + DOMString? userInput; + }; + + callback RequestPinCallback = void (optional PinResponseDetails details); + + callback StopPinRequestCallback = void (); + // The callback provided by the extension that Chrome uses to report back // rejected certificates. See <code>CertificatesCallback</code>. callback ResultCallback = void (ArrayBuffer[] rejectedCertificates); @@ -76,4 +134,25 @@ static void onSignDigestRequested(SignRequest request, SignCallback reportCallback); }; + + interface Functions { + // Requests the PIN from the user. Only one ongoing request at a time is + // allowed. The requests issued while another flow is ongoing are rejected. + // It's the extension's responsibility to try again later if another flow is + // in progress. + // |details|: Contains the details about the requested dialog. + // |callback|: Is called when the dialog is resolved with the user input, or + // when the dialog request finishes unsuccessfully (e.g. the dialog was + // canceled by the user or was not allowed to be shown). + static void requestPin(RequestPinDetails details, + RequestPinCallback callback); + + // Stops the pin request started by the $(ref:requestPin) function. + // |details|: Contains the details about the reason for stopping the + // request flow. + // |callback|: To be used by Chrome to send to the extension the status from + // their request to close PIN dialog for user. + static void stopPinRequest(StopPinRequestDetails details, + StopPinRequestCallback callback); + }; };
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index bf7505a..fe44507 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -189,6 +189,7 @@ "safe_browsing/threat_dom_details.cc", "safe_browsing/threat_dom_details.h", ] + deps += [ "//components/safe_browsing/common:common" ] if (safe_browsing_mode == 1) { sources += [ "safe_browsing/feature_extractor_clock.cc",
diff --git a/chrome/renderer/safe_browsing/DEPS b/chrome/renderer/safe_browsing/DEPS index a37ca375..ef75e4ec 100644 --- a/chrome/renderer/safe_browsing/DEPS +++ b/chrome/renderer/safe_browsing/DEPS
@@ -1,4 +1,5 @@ include_rules = [ + "+components/safe_browsing/common", "+third_party/smhasher", ]
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc index 3cd2291..704ff2e 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -13,10 +13,10 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/renderer/safe_browsing/feature_extractor_clock.h" #include "chrome/renderer/safe_browsing/phishing_classifier.h" #include "chrome/renderer/safe_browsing/scorer.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" #include "content/public/renderer/render_frame.h"
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc index 67ced46..5e5b799 100644 --- a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc +++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
@@ -8,12 +8,12 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/common/safe_browsing/csd.pb.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/renderer/safe_browsing/features.h" #include "chrome/renderer/safe_browsing/phishing_classifier.h" #include "chrome/renderer/safe_browsing/scorer.h" #include "chrome/test/base/chrome_render_view_test.h" #include "chrome/test/base/chrome_unit_test_suite.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/renderer/safe_browsing/threat_dom_details.cc b/chrome/renderer/safe_browsing/threat_dom_details.cc index c68b24f5..b2a8ed6 100644 --- a/chrome/renderer/safe_browsing/threat_dom_details.cc +++ b/chrome/renderer/safe_browsing/threat_dom_details.cc
@@ -5,8 +5,7 @@ #include "chrome/renderer/safe_browsing/threat_dom_details.h" #include "base/compiler_specific.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/renderer/render_frame.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/web/WebDocument.h"
diff --git a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc index bdd68d09..157cefc 100644 --- a/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc +++ b/chrome/renderer/safe_browsing/threat_dom_details_browsertest.cc
@@ -7,8 +7,8 @@ #include <memory> #include "base/strings/stringprintf.h" -#include "chrome/common/safe_browsing/safebrowsing_messages.h" #include "chrome/test/base/chrome_render_view_test.h" +#include "components/safe_browsing/common/safebrowsing_messages.h" #include "content/public/renderer/render_view.h" #include "net/base/escape.h" #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
diff --git a/chrome/service/service_utility_process_host.cc b/chrome/service/service_utility_process_host.cc index f2da679..24431254 100644 --- a/chrome/service/service_utility_process_host.cc +++ b/chrome/service/service_utility_process_host.cc
@@ -97,7 +97,7 @@ const printing::PdfRenderSettings& conversion_settings) { if (!temp_dir_.CreateUniqueTempDir()) return false; - return host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Start( + return host_->Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( IPC::TakePlatformFileForTransit(std::move(pdf_file)), conversion_settings, false /* print_text_with_gdi */)); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 59cfbe6f..e767d1a 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2316,6 +2316,7 @@ "../browser/extensions/api/hotword_private/hotword_private_apitest.cc", "../browser/extensions/api/vpn_provider/vpn_provider_apitest.cc", "../browser/ui/ash/launcher/arc_app_launcher_browsertest.cc", + "../browser/ui/views/arc_app_dialog_view_browsertest.cc", "../browser/ui/webui/options/chromeos/accounts_options_browsertest.cc", "../browser/ui/webui/options/chromeos/guest_mode_options_browsertest.cc", "../browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc",
diff --git a/chrome/test/base/test_launcher_utils.cc b/chrome/test/base/test_launcher_utils.cc index 81f9ca4c..8892674 100644 --- a/chrome/test/base/test_launcher_utils.cc +++ b/chrome/test/base/test_launcher_utils.cc
@@ -16,6 +16,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "components/os_crypt/os_crypt_switches.h" +#include "components/safe_browsing/common/safebrowsing_switches.h" #include "content/public/common/content_switches.h" #if defined(USE_AURA) @@ -45,7 +46,7 @@ command_line->AppendSwitchASCII(switches::kLoggingLevel, "0"); // info // Disable safebrowsing autoupdate. - command_line->AppendSwitch(switches::kSbDisableAutoUpdate); + command_line->AppendSwitch(safe_browsing::switches::kSbDisableAutoUpdate); // Don't install default apps. command_line->AppendSwitch(switches::kDisableDefaultApps);
diff --git a/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.html b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.html new file mode 100644 index 0000000..c107807 --- /dev/null +++ b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.html
@@ -0,0 +1,6 @@ +<!-- + * Copyright 2016 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. +--> +<script src="basic.js"></script>
diff --git a/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.js b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.js new file mode 100644 index 0000000..8d0d494 --- /dev/null +++ b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic.js
@@ -0,0 +1,62 @@ +// Copyright 2016 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. + +// The script requests pin and checks the input. If correct PIN (1234) is +// provided, the script requests to close the dialog and stops there. If wrong +// PIN is provided, the request is repeated until the limit of 3 bad tries is +// reached. If the dialog is closed, the request is repeated without considering +// it a wrong attempt. This allows the testing of quota limit of closed dialogs +// (3 closed dialogs per 10 minutes). +function userInputCallback(codeValue) { + if (chrome.runtime.lastError) { + // Should end up here only when quota is exceeded. + lastError = chrome.runtime.lastError.message; + return; + } + + if (attempts >= 3) { + chrome.test.sendMessage('No attempt left'); + return; + } + + if (!codeValue || !codeValue.userInput) { + chrome.certificateProvider.requestPin( + {signRequestId: 123}, userInputCallback); + chrome.test.sendMessage('User closed the dialog', function(message) { + if (message == 'GetLastError') { + chrome.test.sendMessage(lastError); + } + }); + return; + } + + var success = codeValue.userInput == '1234'; // Validate the code. + if (success) { + chrome.certificateProvider.stopPinRequest( + {signRequestId: 123}, closeCallback); + chrome.test.sendMessage(lastError == '' ? 'Success' : lastError); + } else { + attempts++; + var code = attempts < 3 ? {signRequestId: 123, errorType: 'INVALID_PIN'} : { + signRequestId: 123, + requestType: 'PUK', + errorType: 'MAX_ATTEMPTS_EXCEEDED', + attemptsLeft: 0 + }; + chrome.certificateProvider.requestPin(code, userInputCallback); + chrome.test.sendMessage(lastError == '' ? 'Invalid PIN' : lastError); + } +} + +function closeCallback() { + if (chrome.runtime.lastError != null) { + console.error('Error: ' + chrome.runtime.lastError.message); + lastError = chrome.runtime.lastError.message; + return; + } +} + +var attempts = 0; +var lastError = ''; +chrome.certificateProvider.requestPin({signRequestId: 123}, userInputCallback);
diff --git a/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.html b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.html new file mode 100644 index 0000000..b6108716 --- /dev/null +++ b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.html
@@ -0,0 +1,6 @@ +<!-- + * Copyright 2016 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. +--> +<script src="basic_lock.js"></script>
diff --git a/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.js b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.js new file mode 100644 index 0000000..738d236f --- /dev/null +++ b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/basic_lock.js
@@ -0,0 +1,14 @@ +// Copyright 2016 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. + +// The script requests pin once and never send any other request again. Used to +// test when the user closes the dialog while request is processing. +function userInputCallback(codeValue) { + if (chrome.runtime.lastError) { + console.error('Error: ' + chrome.runtime.lastError.message); + return; + } +} + +chrome.certificateProvider.requestPin({signRequestId: 123}, userInputCallback);
diff --git a/chrome/test/data/extensions/api_test/certificate_provider/request_pin/manifest.json b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/manifest.json new file mode 100644 index 0000000..bbf6d2f4 --- /dev/null +++ b/chrome/test/data/extensions/api_test/certificate_provider/request_pin/manifest.json
@@ -0,0 +1,8 @@ +{ + "name": "RequestPin tests", + "version": "0.1", + "manifest_version": 2, + "permissions": [ + "certificateProvider" + ] +}
diff --git a/chrome/utility/printing_handler.cc b/chrome/utility/printing_handler.cc index 2dc63294..7dbae1a1 100644 --- a/chrome/utility/printing_handler.cc +++ b/chrome/utility/printing_handler.cc
@@ -64,8 +64,8 @@ bool handled = true; IPC_BEGIN_MESSAGE_MAP(PrintingHandler, message) #if defined(OS_WIN) - IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Start, - OnRenderPDFPagesToMetafileStart) + IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles, + OnRenderPDFPagesToMetafile) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage, OnRenderPDFPagesToMetafileGetPage) IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop, @@ -85,7 +85,7 @@ } #if defined(OS_WIN) -void PrintingHandler::OnRenderPDFPagesToMetafileStart( +void PrintingHandler::OnRenderPDFPagesToMetafile( IPC::PlatformFileForTransit pdf_transit, const PdfRenderSettings& settings, bool print_text_with_gdi) { @@ -109,8 +109,6 @@ } void PrintingHandler::OnRenderPDFPagesToMetafileStop() { - chrome_pdf::ReleasePDFHandle(pdf_handle_); - pdf_handle_ = nullptr; ReleaseProcessIfNeeded(); } @@ -136,8 +134,6 @@ #if defined(OS_WIN) int PrintingHandler::LoadPDF(base::File pdf_file) { - DCHECK(!pdf_handle_); - int64_t length64 = pdf_file.GetLength(); if (length64 <= 0 || length64 > std::numeric_limits<int>::max()) return 0; @@ -149,7 +145,7 @@ int total_page_count = 0; if (!chrome_pdf::GetPDFDocInfo(&pdf_data_.front(), pdf_data_.size(), - &total_page_count, nullptr, &pdf_handle_)) { + &total_page_count, nullptr)) { return 0; } return total_page_count; @@ -177,7 +173,7 @@ // to StartPage. metafile.StartPage(gfx::Size(), gfx::Rect(), 1); if (!chrome_pdf::RenderPDFPageToDC( - pdf_handle_, page_number, metafile.context(), + &pdf_data_.front(), pdf_data_.size(), page_number, metafile.context(), pdf_rendering_settings_.dpi, pdf_rendering_settings_.area.x(), pdf_rendering_settings_.area.y(), pdf_rendering_settings_.area.width(), @@ -208,9 +204,8 @@ return false; int total_page_count = 0; - void* pdf_handle = nullptr; if (!chrome_pdf::GetPDFDocInfo(data.data(), data_size, &total_page_count, - nullptr, &pdf_handle)) { + nullptr)) { return false; } @@ -219,14 +214,11 @@ encoder.EncodeDocumentHeader(&pwg_header); int bytes_written = bitmap_file.WriteAtCurrentPos(pwg_header.data(), pwg_header.size()); - if (bytes_written != static_cast<int>(pwg_header.size())) { - chrome_pdf::ReleasePDFHandle(pdf_handle); + if (bytes_written != static_cast<int>(pwg_header.size())) return false; - } cloud_print::BitmapImage image(settings.area.size(), cloud_print::BitmapImage::BGRA); - bool ret = true; for (int i = 0; i < total_page_count; ++i) { int page_number = i; @@ -235,8 +227,9 @@ } if (!chrome_pdf::RenderPDFPageToBitmap( - pdf_handle, page_number, image.pixel_data(), image.size().width(), - image.size().height(), settings.dpi, settings.autorotate)) { + data.data(), data_size, page_number, image.pixel_data(), + image.size().width(), image.size().height(), settings.dpi, + settings.autorotate)) { return false; } @@ -268,19 +261,14 @@ } std::string pwg_page; - if (!encoder.EncodePage(image, header_info, &pwg_page)) { - ret = false; - break; - } + if (!encoder.EncodePage(image, header_info, &pwg_page)) + return false; bytes_written = bitmap_file.WriteAtCurrentPos(pwg_page.data(), pwg_page.size()); - if (bytes_written != static_cast<int>(pwg_page.size())) { - ret = false; - break; - } + if (bytes_written != static_cast<int>(pwg_page.size())) + return false; } - chrome_pdf::ReleasePDFHandle(pdf_handle); - return ret; + return true; } void PrintingHandler::OnGetPrinterCapsAndDefaults(
diff --git a/chrome/utility/printing_handler.h b/chrome/utility/printing_handler.h index 02696d4..99b6eeb 100644 --- a/chrome/utility/printing_handler.h +++ b/chrome/utility/printing_handler.h
@@ -34,7 +34,7 @@ private: // IPC message handlers. #if defined(OS_WIN) - void OnRenderPDFPagesToMetafileStart(IPC::PlatformFileForTransit pdf_transit, + void OnRenderPDFPagesToMetafile(IPC::PlatformFileForTransit pdf_transit, const PdfRenderSettings& settings, bool print_text_with_gdi); void OnRenderPDFPagesToMetafileGetPage( @@ -68,7 +68,6 @@ #if defined(OS_WIN) std::vector<char> pdf_data_; PdfRenderSettings pdf_rendering_settings_; - void* pdf_handle_ = nullptr; #endif DISALLOW_COPY_AND_ASSIGN(PrintingHandler);
diff --git a/chromecast/browser/cast_media_blocker.cc b/chromecast/browser/cast_media_blocker.cc index dd92cad..daeca5b 100644 --- a/chromecast/browser/cast_media_blocker.cc +++ b/chromecast/browser/cast_media_blocker.cc
@@ -11,10 +11,8 @@ namespace chromecast { namespace shell { -CastMediaBlocker::CastMediaBlocker(content::MediaSession* media_session, - content::WebContents* web_contents) +CastMediaBlocker::CastMediaBlocker(content::MediaSession* media_session) : content::MediaSessionObserver(media_session), - content::WebContentsObserver(web_contents), blocked_(false), paused_by_user_(true), suspended_(true),
diff --git a/chromecast/browser/cast_media_blocker.h b/chromecast/browser/cast_media_blocker.h index 1c3d562..58b3f99 100644 --- a/chromecast/browser/cast_media_blocker.h +++ b/chromecast/browser/cast_media_blocker.h
@@ -14,14 +14,9 @@ // This class implements a blocking mode for web applications and is used in // Chromecast internal code. Media is unblocked by default. -// -// TODO(derekjchow): Remove the inheritance from WebContentsObserver. -// See http://crbug.com/660331 -class CastMediaBlocker : public content::MediaSessionObserver, - content::WebContentsObserver { +class CastMediaBlocker : public content::MediaSessionObserver { public: - CastMediaBlocker(content::MediaSession* media_session, - content::WebContents* web_contents); + explicit CastMediaBlocker(content::MediaSession* media_session); ~CastMediaBlocker() override; // Sets if the web contents is allowed to play media or not. If media is
diff --git a/chromecast/browser/cast_media_blocker_browsertest.cc b/chromecast/browser/cast_media_blocker_browsertest.cc index 94a9ddab..5d394de96 100644 --- a/chromecast/browser/cast_media_blocker_browsertest.cc +++ b/chromecast/browser/cast_media_blocker_browsertest.cc
@@ -44,7 +44,7 @@ WaitForLoadStop(web_contents_); blocker_ = base::MakeUnique<CastMediaBlocker>( - content::MediaSession::Get(web_contents_), web_contents_); + content::MediaSession::Get(web_contents_)); } void BlockAndTestPlayerState(const std::string& media_type, bool blocked) {
diff --git a/chromecast/browser/cast_media_blocker_unittest.cc b/chromecast/browser/cast_media_blocker_unittest.cc index 8bd152e..25d8a322 100644 --- a/chromecast/browser/cast_media_blocker_unittest.cc +++ b/chromecast/browser/cast_media_blocker_unittest.cc
@@ -54,8 +54,7 @@ content::RenderViewHostTestHarness::SetUp(); media_session_ = base::MakeUnique<MockMediaSession>( content::MediaSession::Get(web_contents())); - media_blocker_ = base::MakeUnique<CastMediaBlocker>(media_session_.get(), - web_contents()); + media_blocker_ = base::MakeUnique<CastMediaBlocker>(media_session_.get()); content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(GURL("https://www.youtube.com"));
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index b625bd9..718403a 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -148,8 +148,7 @@ v8::Local<v8::Context> context = render_frame->GetWebFrame()->mainWorldScriptContext(); - // CastGinRunner manages its own lifetime. - CastGinRunner* runner = new CastGinRunner(render_frame); + CastGinRunner* runner = CastGinRunner::Get(render_frame); gin::Runner::Scope scoper(runner); // Initialize AMD API for Mojo.
diff --git a/chromecast/renderer/cast_gin_runner.cc b/chromecast/renderer/cast_gin_runner.cc index 7d9db16f..ca93bf51 100644 --- a/chromecast/renderer/cast_gin_runner.cc +++ b/chromecast/renderer/cast_gin_runner.cc
@@ -7,36 +7,45 @@ #include "content/public/renderer/render_frame.h" #include "gin/per_context_data.h" #include "third_party/WebKit/public/web/WebFrame.h" +#include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" #include "third_party/WebKit/public/web/WebScriptSource.h" namespace chromecast { namespace shell { -CastGinRunner::CastGinRunner(content::RenderFrame* render_frame) - : content::RenderFrameObserver(render_frame), - frame_(render_frame->GetWebFrame()), - context_holder_( - gin::PerContextData::From(frame_->mainWorldScriptContext()) - ->context_holder()) { +namespace { +const void* kCastContextData; +const void* kCastGinRunnerKey = static_cast<const void*>(&kCastContextData); +} + +// static +CastGinRunner* CastGinRunner::Get(content::RenderFrame* render_frame) { + DCHECK(render_frame); + blink::WebFrame* frame = render_frame->GetWebFrame(); + v8::HandleScope handle_scope(blink::mainThreadIsolate()); + gin::PerContextData* context_data = + gin::PerContextData::From(frame->mainWorldScriptContext()); + CastGinRunner* runner = + static_cast<CastGinRunner*>(context_data->GetUserData(kCastGinRunnerKey)); + return runner ? runner : new CastGinRunner(frame, context_data); +} + +CastGinRunner::CastGinRunner(blink::WebFrame* frame, + gin::PerContextData* context_data) + : frame_(frame), context_holder_(context_data->context_holder()) { DCHECK(frame_); DCHECK(context_holder_); - gin::PerContextData* context_data = - gin::PerContextData::From(frame_->mainWorldScriptContext()); - v8::Isolate::Scope isolate_scope(context_holder_->isolate()); - v8::HandleScope handle_scope(context_holder_->isolate()); - - context_data->SetUserData(kCastContextData, this); + // context_data takes ownership of this class. + context_data->SetUserData(kCastGinRunnerKey, this); // Note: this installs the runner globally. If we need to support more than // one runner at a time we'll have to revisit this. context_data->set_runner(this); } -CastGinRunner::~CastGinRunner() { - RemoveUserData(render_frame()->GetWebFrame()->mainWorldScriptContext()); -} +CastGinRunner::~CastGinRunner() {} void CastGinRunner::Run(const std::string& source, const std::string& resource_name) { @@ -56,31 +65,5 @@ return context_holder_; } -void CastGinRunner::WillReleaseScriptContext(v8::Local<v8::Context> context, - int world_id) { - RemoveUserDataFromMainWorldContext(); -} - -void CastGinRunner::DidClearWindowObject() { - RemoveUserDataFromMainWorldContext(); -} - -void CastGinRunner::OnDestruct() { - RemoveUserDataFromMainWorldContext(); -} - -void CastGinRunner::RemoveUserDataFromMainWorldContext() { - v8::HandleScope handle_scope(context_holder_->isolate()); - RemoveUserData(render_frame()->GetWebFrame()->mainWorldScriptContext()); -} - -void CastGinRunner::RemoveUserData(v8::Local<v8::Context> context) { - gin::PerContextData* context_data = gin::PerContextData::From(context); - if (!context_data) - return; - - context_data->RemoveUserData(kCastContextData); -} - } // namespace shell } // namespace chromecast
diff --git a/chromecast/renderer/cast_gin_runner.h b/chromecast/renderer/cast_gin_runner.h index 2c1115aa..ac01ab2 100644 --- a/chromecast/renderer/cast_gin_runner.h +++ b/chromecast/renderer/cast_gin_runner.h
@@ -7,27 +7,30 @@ #include "base/macros.h" #include "base/supports_user_data.h" -#include "content/public/renderer/render_frame_observer.h" #include "gin/runner.h" -namespace { -const char kCastContextData[] = "CastContextData"; -} - namespace blink { class WebFrame; } +namespace content { +class RenderFrame; +} + +namespace gin { +class PerContextData; +} + namespace chromecast { namespace shell { // Implementation of gin::Runner that forwards Runner functions to WebFrame. -class CastGinRunner : public gin::Runner, - public base::SupportsUserData::Data, - public content::RenderFrameObserver { +// This class is lazily created per RenderFrame with the Get function and it's +// lifetime is managed by the gin::PerContextData associated with the frame. +class CastGinRunner : public gin::Runner, public base::SupportsUserData::Data { public: - // Does not take ownership of ContextHolder. - CastGinRunner(content::RenderFrame* render_frame); + // Gets or creates the CastGinRunner for this RenderFrame + static CastGinRunner* Get(content::RenderFrame* render_frame); ~CastGinRunner() override; // gin:Runner implementation: @@ -39,15 +42,8 @@ v8::Local<v8::Value> argv[]) override; gin::ContextHolder* GetContextHolder() override; - // content::RenderFrameObserver implementation: - void WillReleaseScriptContext(v8::Local<v8::Context> context, - int world_id) override; - void DidClearWindowObject() override; - void OnDestruct() override; - private: - void RemoveUserDataFromMainWorldContext(); - void RemoveUserData(v8::Local<v8::Context> context); + CastGinRunner(blink::WebFrame* frame, gin::PerContextData* context_data); // Frame to execute script in. blink::WebFrame* const frame_;
diff --git a/components/cronet/android/BUILD.gn b/components/cronet/android/BUILD.gn index a15f26d..3ba8227 100644 --- a/components/cronet/android/BUILD.gn +++ b/components/cronet/android/BUILD.gn
@@ -422,6 +422,7 @@ shared_libraries = [ ":cronet" ] deps = [ + ":cronet_combine_proguard_flags", ":cronet_sample_apk_java", ":cronet_sample_apk_resources", "//base:base_java", @@ -429,15 +430,13 @@ ] run_findbugs_override = true - if (!is_java_debug) { - proguard_enabled = true - proguard_configs = [ - "proguard.cfg", - "sample/javatests/proguard.cfg", - "//base/android/proguard/chromium_apk.flags", - "//base/android/proguard/chromium_code.flags", - ] - } + proguard_enabled = true + proguard_configs = [ + "$target_gen_dir/cronet_impl_native_proguard.cfg", + "cronet_impl_common_proguard.cfg", + "sample/javatests/proguard.cfg", + "//base/android/proguard/chromium_apk.flags", + ] } # cronet_sample_test_apk_resources is identical to @@ -470,7 +469,7 @@ additional_apks = [ "//net/android:net_test_support_apk" ] run_findbugs_override = true - proguard_enabled = !is_java_debug + proguard_enabled = true } generate_jni("cronet_tests_jni_headers") { @@ -743,6 +742,7 @@ ] deps = [ + ":cronet_combine_proguard_flags", ":cronet_perf_test_apk_java", ":cronet_test_apk_java", "//base:base_java", @@ -751,10 +751,10 @@ run_findbugs_override = true proguard_enabled = true proguard_configs = [ - "proguard.cfg", + "$target_gen_dir/cronet_impl_native_proguard.cfg", + "cronet_impl_common_proguard.cfg", "test/javaperftests/proguard.cfg", "//base/android/proguard/chromium_apk.flags", - "//base/android/proguard/chromium_code.flags", ] } @@ -1021,8 +1021,11 @@ "$root_out_dir/lib.java/components/cronet/android/cronet_api.jar", "$root_out_dir/lib.java/components/cronet/android/cronet_impl_common_java.jar", "$root_out_dir/lib.java/components/cronet/android/cronet_impl_platform_java.jar", + "$target_gen_dir/cronet_impl_native_proguard.cfg", "//AUTHORS", "//chrome/VERSION", + "cronet_impl_common_proguard.cfg", + "cronet_impl_platform_proguard.cfg", ] outputs = [ "$_package_dir/{{source_file_part}}", @@ -1030,6 +1033,7 @@ deps = [ ":cronet_api_java", + ":cronet_combine_proguard_flags", ":cronet_impl_common_java", ":cronet_impl_platform_java", ] @@ -1038,14 +1042,15 @@ action("cronet_combine_proguard_flags") { script = "//components/cronet/tools/generate_proguard_file.py" outputs = [ - "$_package_dir/proguard.cfg", + "$target_gen_dir/cronet_impl_native_proguard.cfg", ] - args = [ "--output-file", - rebase_path("$_package_dir/proguard.cfg", root_build_dir), + rebase_path("$target_gen_dir/cronet_impl_native_proguard.cfg", + root_build_dir), + rebase_path("//components/cronet/android/cronet_impl_native_proguard.cfg", + root_build_dir), rebase_path("//base/android/proguard/chromium_code.flags", root_build_dir), - rebase_path("//components/cronet/android/proguard.cfg", root_build_dir), ] } @@ -1102,7 +1107,6 @@ # not including any deps in cronet_package target otherwise. if (!(target_cpu == "arm" && arm_version == 7) || !arm_use_neon) { deps = [ - ":cronet_combine_proguard_flags", ":cronet_package_copy", ":cronet_package_copy_native_lib", ":cronet_package_copy_native_lib_unstripped",
diff --git a/components/cronet/android/cronet_impl_common_proguard.cfg b/components/cronet/android/cronet_impl_common_proguard.cfg new file mode 100644 index 0000000..531394a --- /dev/null +++ b/components/cronet/android/cronet_impl_common_proguard.cfg
@@ -0,0 +1,6 @@ +# Proguard config for apps that depend on cronet_impl_common_java.jar. + +# This constructor is called using the reflection from Cronet API (cronet_api.jar). +-keep class org.chromium.net.impl.CronetEngineBuilderImpl { + public <init>(android.content.Context); +} \ No newline at end of file
diff --git a/components/cronet/android/proguard.cfg b/components/cronet/android/cronet_impl_native_proguard.cfg similarity index 77% rename from components/cronet/android/proguard.cfg rename to components/cronet/android/cronet_impl_native_proguard.cfg index 1d6c8e17..9ee247f 100644 --- a/components/cronet/android/proguard.cfg +++ b/components/cronet/android/cronet_impl_native_proguard.cfg
@@ -1,13 +1,8 @@ +# Proguard config for apps that depend on cronet_impl_native_java.jar. + -keep class org.chromium.net.impl.CronetUrlRequest$HeadersList -keep class org.chromium.net.impl.ChromiumUrlRequest$ResponseHeadersMap -# This constructor is called by the reflection from Cronet API. It cannot be -# annotated with @org.chromium.base.annotations.AccessedByNative in order to -# avoid the dependency on Chromium-Base Java classes. --keep class org.chromium.net.impl.CronetEngineBuilderImpl { - public <init>(android.content.Context); -} - # Suppress unnecessary warnings. -dontnote org.chromium.net.ProxyChangeListener$ProxyReceiver -dontnote org.chromium.net.AndroidKeyStore
diff --git a/components/cronet/android/cronet_impl_platform_proguard.cfg b/components/cronet/android/cronet_impl_platform_proguard.cfg new file mode 100644 index 0000000..3e9d42c --- /dev/null +++ b/components/cronet/android/cronet_impl_platform_proguard.cfg
@@ -0,0 +1,7 @@ +# Proguard config for apps that depend on cronet_impl_platform_java.jar. + +# This constructor is called using the reflection from the Cronet common +# implementation (cronet_impl_platform_java.jar). +-keep class org.chromium.net.impl.JavaCronetEngine { + public <init>(java.lang.String); +} \ No newline at end of file
diff --git a/components/metrics/data_use_tracker.cc b/components/metrics/data_use_tracker.cc index d97462a..b9b9bda0 100644 --- a/components/metrics/data_use_tracker.cc +++ b/components/metrics/data_use_tracker.cc
@@ -22,24 +22,10 @@ const int kDefaultUMAWeeklyQuotaBytes = 204800; const double kDefaultUMARatio = 0.05; -// This function is for forwarding metrics usage pref changes to the appropriate -// callback on the appropriate thread. -// TODO(gayane): Reduce the frequency of posting tasks from IO to UI thread. -void UpdateMetricsUsagePrefs( - const UpdateUsagePrefCallbackType& update_on_ui_callback, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - const std::string& service_name, - int message_size, - bool is_cellular) { - ui_task_runner->PostTask( - FROM_HERE, base::Bind(update_on_ui_callback, service_name, message_size, - is_cellular)); -} - } // namespace DataUseTracker::DataUseTracker(PrefService* local_state) - : local_state_(local_state), weak_ptr_factory_(this) {} + : local_state_(local_state) {} DataUseTracker::~DataUseTracker() {} @@ -59,15 +45,17 @@ registry->RegisterDictionaryPref(metrics::prefs::kUmaCellDataUse); } -UpdateUsagePrefCallbackType DataUseTracker::GetDataUseForwardingCallback( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner) { - DCHECK(ui_task_runner->RunsTasksOnCurrentThread()); +void DataUseTracker::UpdateMetricsUsagePrefs(const std::string& service_name, + int message_size, + bool is_cellular) { + DCHECK(thread_checker_.CalledOnValidThread()); - return base::Bind( - &UpdateMetricsUsagePrefs, - base::Bind(&DataUseTracker::UpdateMetricsUsagePrefsOnUIThread, - weak_ptr_factory_.GetWeakPtr()), - ui_task_runner); + if (!is_cellular) + return; + + UpdateUsagePref(prefs::kUserCellDataUse, message_size); + if (service_name == "UMA") + UpdateUsagePref(prefs::kUmaCellDataUse, message_size); } bool DataUseTracker::ShouldUploadLogOnCellular(int log_bytes) { @@ -98,20 +86,6 @@ uma_ratio; } -void DataUseTracker::UpdateMetricsUsagePrefsOnUIThread( - const std::string& service_name, - int message_size, - bool is_celllular) { - DCHECK(thread_checker_.CalledOnValidThread()); - - if (!is_celllular) - return; - - UpdateUsagePref(prefs::kUserCellDataUse, message_size); - if (service_name == "UMA") - UpdateUsagePref(prefs::kUmaCellDataUse, message_size); -} - void DataUseTracker::UpdateUsagePref(const std::string& pref_name, int message_size) { DCHECK(thread_checker_.CalledOnValidThread());
diff --git a/components/metrics/data_use_tracker.h b/components/metrics/data_use_tracker.h index b6441ec..e5eb2ba 100644 --- a/components/metrics/data_use_tracker.h +++ b/components/metrics/data_use_tracker.h
@@ -10,9 +10,6 @@ #include "base/callback.h" #include "base/gtest_prod_util.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "base/sequenced_task_runner.h" #include "base/threading/thread_checker.h" #include "base/time/time.h" #include "components/prefs/pref_registry_simple.h" @@ -38,10 +35,10 @@ // Registers data use prefs using provided |registry|. static void RegisterPrefs(PrefRegistrySimple* registry); - // Returns a callback to data use pref updating function. Should be called on - // UI thread. - UpdateUsagePrefCallbackType GetDataUseForwardingCallback( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner); + // Updates data usage tracking prefs with the specified values. + void UpdateMetricsUsagePrefs(const std::string& service_name, + int message_size, + bool is_cellular); // Returns whether a log with provided |log_bytes| can be uploaded according // to data use ratio and UMA quota provided by variations. @@ -53,12 +50,6 @@ FRIEND_TEST_ALL_PREFIXES(DataUseTrackerTest, CheckComputeTotalDataUse); FRIEND_TEST_ALL_PREFIXES(DataUseTrackerTest, CheckCanUploadUMALog); - // Updates data usage prefs on UI thread according to what Prefservice - // expects. - void UpdateMetricsUsagePrefsOnUIThread(const std::string& service_name, - int message_size, - bool is_cellular); - // Updates provided |pref_name| for a current date with the given message // size. void UpdateUsagePref(const std::string& pref_name, int message_size); @@ -90,8 +81,6 @@ base::ThreadChecker thread_checker_; - base::WeakPtrFactory<DataUseTracker> weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(DataUseTracker); };
diff --git a/components/metrics/data_use_tracker_unittest.cc b/components/metrics/data_use_tracker_unittest.cc index ed32a4a..0cb9668 100644 --- a/components/metrics/data_use_tracker_unittest.cc +++ b/components/metrics/data_use_tracker_unittest.cc
@@ -109,7 +109,7 @@ int user_pref_value = 0; int uma_pref_value = 0; - data_use_tracker.UpdateMetricsUsagePrefsOnUIThread("", 2 * 100, true); + data_use_tracker.UpdateMetricsUsagePrefs("", 2 * 100, true); local_state.GetDictionary(prefs::kUserCellDataUse) ->GetInteger(kTodayStr, &user_pref_value); EXPECT_EQ(2 * 100, user_pref_value); @@ -117,7 +117,7 @@ ->GetInteger(kTodayStr, &uma_pref_value); EXPECT_EQ(0, uma_pref_value); - data_use_tracker.UpdateMetricsUsagePrefsOnUIThread("UMA", 100, true); + data_use_tracker.UpdateMetricsUsagePrefs("UMA", 100, true); local_state.GetDictionary(prefs::kUserCellDataUse) ->GetInteger(kTodayStr, &user_pref_value); EXPECT_EQ(3 * 100, user_pref_value);
diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index 8e8a1a6..cc0e457e 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc
@@ -538,14 +538,15 @@ log_manager_.StoreLog(log, MetricsLog::ONGOING_LOG); } -UpdateUsagePrefCallbackType MetricsService::GetDataUseForwardingCallback() { +void MetricsService::UpdateMetricsUsagePrefs(const std::string& service_name, + int message_size, + bool is_cellular) { DCHECK(IsSingleThreaded()); - if (data_use_tracker_) { - return data_use_tracker_->GetDataUseForwardingCallback( - base::ThreadTaskRunnerHandle::Get()); + data_use_tracker_->UpdateMetricsUsagePrefs(service_name, + message_size, + is_cellular); } - return UpdateUsagePrefCallbackType(); } void MetricsService::MergeHistogramDeltas() {
diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h index 47095f70..562f465 100644 --- a/components/metrics/metrics_service.h +++ b/components/metrics/metrics_service.h
@@ -201,9 +201,10 @@ // Pushes a log that has been generated by an external component. void PushExternalLog(const std::string& log); - // Returns a callback to data use pref updating function which can be called - // from any thread, but this function should be called on UI thread. - UpdateUsagePrefCallbackType GetDataUseForwardingCallback(); + // Updates data usage tracking prefs with the specified values. + void UpdateMetricsUsagePrefs(const std::string& service_name, + int message_size, + bool is_cellular); // Merge any data from metrics providers into the global StatisticsRecorder. void MergeHistogramDeltas();
diff --git a/components/reading_list/ios/reading_list_model.h b/components/reading_list/ios/reading_list_model.h index cae0226..c3eb2f4 100644 --- a/components/reading_list/ios/reading_list_model.h +++ b/components/reading_list/ios/reading_list_model.h
@@ -116,17 +116,6 @@ DISALLOW_COPY_AND_ASSIGN(ScopedReadingListBatchUpdate); }; - // TODO(crbug.com/664924): Remove temporary methods for transition. - - // Allows iterating through read entries in the model. Must be called on a - // singlerunloop to ensure no entry is returned twice and all entries are - // returned - virtual const ReadingListEntry& GetReadEntryAtIndex(size_t index) const = 0; - virtual const ReadingListEntry& GetUnreadEntryAtIndex(size_t index) const = 0; - virtual void MarkReadByURL(const GURL& url) = 0; - virtual void MarkUnreadByURL(const GURL& url) = 0; - virtual size_t read_size() const = 0; - protected: ReadingListModel(); virtual ~ReadingListModel();
diff --git a/components/reading_list/ios/reading_list_model_impl.cc b/components/reading_list/ios/reading_list_model_impl.cc index 4727b777..fb010a2 100644 --- a/components/reading_list/ios/reading_list_model_impl.cc +++ b/components/reading_list/ios/reading_list_model_impl.cc
@@ -13,13 +13,6 @@ #include "components/reading_list/ios/reading_list_pref_names.h" #include "url/gurl.h" -ReadingListModelImpl::Cache::Cache() - : read_entries(std::vector<GURL>()), - unread_entries(std::vector<GURL>()), - dirty(false) {} - -ReadingListModelImpl::Cache::~Cache() {} - ReadingListModelImpl::ReadingListModelImpl() : ReadingListModelImpl(nullptr, nullptr) {} @@ -28,7 +21,6 @@ PrefService* pref_service) : unread_entry_count_(0), read_entry_count_(0), - cache_(base::MakeUnique<struct Cache>()), pref_service_(pref_service), has_unseen_(false), loaded_(false), @@ -40,7 +32,6 @@ } else { loaded_ = true; entries_ = base::MakeUnique<ReadingListEntries>(); - cache_->dirty = true; } has_unseen_ = GetPersistentHasUnseen(); } @@ -51,7 +42,6 @@ std::unique_ptr<ReadingListEntries> entries) { DCHECK(CalledOnValidThread()); entries_ = std::move(entries); - cache_->dirty = true; for (auto& iterator : *entries_) { if (iterator.second.IsRead()) { read_entry_count_++; @@ -93,14 +83,6 @@ return unread_entry_count_; } -size_t ReadingListModelImpl::read_size() const { - DCHECK(CalledOnValidThread()); - DCHECK(read_entry_count_ + unread_entry_count_ == entries_->size()); - if (!loaded()) - return 0; - return read_entry_count_; -} - bool ReadingListModelImpl::HasUnseenEntries() const { DCHECK(CalledOnValidThread()); if (!loaded()) @@ -131,58 +113,6 @@ return GetMutableEntryFromURL(gurl); } -const ReadingListEntry& ReadingListModelImpl::GetReadEntryAtIndex( - size_t index) const { - DCHECK(CalledOnValidThread()); - DCHECK(loaded()); - DCHECK(index < read_entry_count_); - if (cache_->dirty) { - RebuildIndex(); - } - return *GetEntryByURL(cache_->read_entries[index]); -} - -const ReadingListEntry& ReadingListModelImpl::GetUnreadEntryAtIndex( - size_t index) const { - DCHECK(CalledOnValidThread()); - DCHECK(loaded()); - DCHECK(index < unread_entry_count_); - if (cache_->dirty) { - RebuildIndex(); - } - return *GetEntryByURL(cache_->unread_entries[index]); -} - -void ReadingListModelImpl::RebuildIndex() const { - DCHECK(CalledOnValidThread()); - DCHECK(loaded()); - if (!cache_->dirty) { - return; - } - cache_->dirty = false; - cache_->read_entries.clear(); - cache_->unread_entries.clear(); - for (auto& iterator : *entries_) { - if (iterator.second.IsRead()) { - cache_->read_entries.push_back(iterator.first); - } else { - cache_->unread_entries.push_back(iterator.first); - } - } - DCHECK(read_entry_count_ == cache_->read_entries.size()); - DCHECK(unread_entry_count_ == cache_->unread_entries.size()); - std::sort(cache_->read_entries.begin(), cache_->read_entries.end(), - [this](const GURL& left_url, const GURL& right_url) { - return this->entries_->at(left_url).UpdateTime() > - this->entries_->at(right_url).UpdateTime(); - }); - std::sort(cache_->unread_entries.begin(), cache_->unread_entries.end(), - [this](const GURL& left_url, const GURL& right_url) { - return this->entries_->at(left_url).UpdateTime() > - this->entries_->at(right_url).UpdateTime(); - }); -} - ReadingListEntry* ReadingListModelImpl::GetMutableEntryFromURL( const GURL& url) const { DCHECK(CalledOnValidThread()); @@ -210,7 +140,6 @@ } GURL url = entry->URL(); entries_->insert(std::make_pair(url, std::move(*entry))); - cache_->dirty = true; for (auto& observer : observers_) { observer.ReadingListDidAddEntry(this, url); observer.ReadingListDidApplyChanges(this); @@ -239,7 +168,6 @@ entry->MergeLocalStateFrom(*existing_entry); entries_->find(url)->second = std::move(*entry); - cache_->dirty = true; existing_entry = GetMutableEntryFromURL(url); if (existing_entry->IsRead()) { @@ -280,7 +208,6 @@ unread_entry_count_--; } entries_->erase(url); - cache_->dirty = true; for (auto& observer : observers_) observer.ReadingListDidApplyChanges(this); } @@ -305,7 +232,6 @@ if (storage_layer_) { storage_layer_->SaveEntry(*GetEntryByURL(url)); } - cache_->dirty = true; for (auto& observer : observers_) { observer.ReadingListDidAddEntry(this, url); @@ -315,14 +241,6 @@ return entries_->at(url); } -void ReadingListModelImpl::MarkReadByURL(const GURL& url) { - return SetReadStatus(url, true); -} - -void ReadingListModelImpl::MarkUnreadByURL(const GURL& url) { - return SetReadStatus(url, false); -} - void ReadingListModelImpl::SetReadStatus(const GURL& url, bool read) { DCHECK(CalledOnValidThread()); DCHECK(loaded()); @@ -346,7 +264,6 @@ } entry.SetRead(read); entry.MarkEntryUpdated(); - cache_->dirty = true; if (storage_layer_) { storage_layer_->SaveEntry(entry); }
diff --git a/components/reading_list/ios/reading_list_model_impl.h b/components/reading_list/ios/reading_list_model_impl.h index 1ff5056..c49d713 100644 --- a/components/reading_list/ios/reading_list_model_impl.h +++ b/components/reading_list/ios/reading_list_model_impl.h
@@ -46,7 +46,6 @@ size_t size() const override; size_t unread_size() const override; - size_t read_size() const override; bool HasUnseenEntries() const override; void ResetUnseenEntries() override; @@ -54,10 +53,6 @@ const std::vector<GURL> Keys() const override; const ReadingListEntry* GetEntryByURL(const GURL& gurl) const override; - const ReadingListEntry& GetUnreadEntryAtIndex(size_t index) const override; - const ReadingListEntry& GetReadEntryAtIndex(size_t index) const override; - void MarkReadByURL(const GURL& url) override; - void MarkUnreadByURL(const GURL& url) override; void RemoveEntryByURL(const GURL& url) override; @@ -121,17 +116,6 @@ size_t unread_entry_count_; size_t read_entry_count_; - // TODO(crbug.com/664924): Remove temporary cache and move it to - // ReadingListViewController. - struct Cache { - Cache(); - ~Cache(); - std::vector<GURL> read_entries; - std::vector<GURL> unread_entries; - bool dirty; - }; - std::unique_ptr<struct Cache> cache_; - std::unique_ptr<ReadingListModelStorage> storage_layer_; PrefService* pref_service_; bool has_unseen_;
diff --git a/components/reading_list/ios/reading_list_model_observer.h b/components/reading_list/ios/reading_list_model_observer.h index 44b0132..123ea0b 100644 --- a/components/reading_list/ios/reading_list_model_observer.h +++ b/components/reading_list/ios/reading_list_model_observer.h
@@ -64,19 +64,6 @@ // are applied and then this method is called. virtual void ReadingListDidApplyChanges(ReadingListModel* model) {} - // TODO(crbug.com/664924): Remove temporary methods - virtual void ReadingListWillRemoveUnreadEntry(const ReadingListModel* model, - size_t index) {} - - virtual void ReadingListWillRemoveReadEntry(const ReadingListModel* model, - size_t index) {} - - virtual void ReadingListWillAddUnreadEntry(const ReadingListModel* model, - const ReadingListEntry& entry) {} - - virtual void ReadingListWillAddReadEntry(const ReadingListModel* model, - const ReadingListEntry& entry) {} - protected: ReadingListModelObserver() {} virtual ~ReadingListModelObserver() {}
diff --git a/components/reading_list/ios/reading_list_model_unittest.mm b/components/reading_list/ios/reading_list_model_unittest.mm index 970bcc4..dff2d10 100644 --- a/components/reading_list/ios/reading_list_model_unittest.mm +++ b/components/reading_list/ios/reading_list_model_unittest.mm
@@ -558,38 +558,38 @@ TEST_F(ReadingListModelTest, UpdateReadEntryTitle) { const GURL gurl("http://example.com"); model_->AddEntry(gurl, "sample"); - model_->MarkReadByURL(gurl); - const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); + model_->SetReadStatus(gurl, true); + const ReadingListEntry* entry = model_->GetEntryByURL(gurl); ClearCounts(); model_->SetEntryTitle(gurl, "ping"); AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ("ping", entry.Title()); + EXPECT_EQ("ping", entry->Title()); } TEST_F(ReadingListModelTest, UpdateReadEntryState) { const GURL gurl("http://example.com"); model_->AddEntry(gurl, "sample"); - model_->MarkReadByURL(gurl); - const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); + model_->SetReadStatus(gurl, true); + const ReadingListEntry* entry = model_->GetEntryByURL(gurl); ClearCounts(); model_->SetEntryDistilledState(gurl, ReadingListEntry::PROCESSING); AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ(ReadingListEntry::PROCESSING, entry.DistilledState()); + EXPECT_EQ(ReadingListEntry::PROCESSING, entry->DistilledState()); } TEST_F(ReadingListModelTest, UpdateReadDistilledPath) { const GURL gurl("http://example.com"); model_->AddEntry(gurl, "sample"); - model_->MarkReadByURL(gurl); - const ReadingListEntry& entry = model_->GetReadEntryAtIndex(0); + model_->SetReadStatus(gurl, true); + const ReadingListEntry* entry = model_->GetEntryByURL(gurl); ClearCounts(); model_->SetEntryDistilledPath(gurl, base::FilePath("distilled/page.html")); AssertObserverCount(0, 0, 0, 0, 0, 0, 0, 1, 1); - EXPECT_EQ(ReadingListEntry::PROCESSED, entry.DistilledState()); - EXPECT_EQ(base::FilePath("distilled/page.html"), entry.DistilledPath()); + EXPECT_EQ(ReadingListEntry::PROCESSED, entry->DistilledState()); + EXPECT_EQ(base::FilePath("distilled/page.html"), entry->DistilledPath()); } // Tests that ReadingListModel calls CallbackModelBeingDeleted when destroyed.
diff --git a/components/safe_browsing/OWNERS b/components/safe_browsing/OWNERS new file mode 100644 index 0000000..b7fd72e --- /dev/null +++ b/components/safe_browsing/OWNERS
@@ -0,0 +1,6 @@ +mattm@chromium.org +nparker@chromium.org +shess@chromium.org + +# For componentization +timvolodine@chromium.org
diff --git a/components/safe_browsing/common/BUILD.gn b/components/safe_browsing/common/BUILD.gn new file mode 100644 index 0000000..47587637 --- /dev/null +++ b/components/safe_browsing/common/BUILD.gn
@@ -0,0 +1,21 @@ +# Copyright 2016 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. + +source_set("common") { + sources = [ + "safebrowsing_constants.cc", + "safebrowsing_constants.h", + "safebrowsing_message_generator.cc", + "safebrowsing_message_generator.h", + "safebrowsing_messages.h", + "safebrowsing_switches.cc", + "safebrowsing_switches.h", + ] + + deps = [ + "//base", + "//ipc", + "//url/ipc:url_ipc", + ] +}
diff --git a/components/safe_browsing/common/DEPS b/components/safe_browsing/common/DEPS new file mode 100644 index 0000000..acf92ab --- /dev/null +++ b/components/safe_browsing/common/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+ipc", + "+url" +]
diff --git a/components/safe_browsing/common/OWNERS b/components/safe_browsing/common/OWNERS new file mode 100644 index 0000000..6734395 --- /dev/null +++ b/components/safe_browsing/common/OWNERS
@@ -0,0 +1,4 @@ +jialiul@chromium.org + +per-file *_messages*.h=set noparent +per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/components/safe_browsing/common/safebrowsing_constants.cc b/components/safe_browsing/common/safebrowsing_constants.cc new file mode 100644 index 0000000..543f725e --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_constants.cc
@@ -0,0 +1,12 @@ +// Copyright 2016 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/safe_browsing/common/safebrowsing_constants.h" + +namespace safe_browsing { + +const base::FilePath::CharType kSafeBrowsingBaseFilename[] = + FILE_PATH_LITERAL("Safe Browsing"); + +} // namespace safe_browsing
diff --git a/components/safe_browsing/common/safebrowsing_constants.h b/components/safe_browsing/common/safebrowsing_constants.h new file mode 100644 index 0000000..17173cc --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_constants.h
@@ -0,0 +1,16 @@ +// Copyright 2016 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_SAFE_BROWSING_COMMON_SAFEBROWSING_CONSTANTS_H_ +#define COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_CONSTANTS_H_ + +#include "base/files/file_path.h" + +namespace safe_browsing { + +extern const base::FilePath::CharType kSafeBrowsingBaseFilename[]; + +} + +#endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_CONSTANTS_H_
diff --git a/components/safe_browsing/common/safebrowsing_message_generator.cc b/components/safe_browsing/common/safebrowsing_message_generator.cc new file mode 100644 index 0000000..8629de28 --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_message_generator.cc
@@ -0,0 +1,39 @@ +// Copyright 2016 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. + +// Get basic type definitions. +#define IPC_MESSAGE_IMPL +#include "components/safe_browsing/common/safebrowsing_message_generator.h" + +// Generate constructors. +#include "ipc/struct_constructor_macros.h" +#include "components/safe_browsing/common/safebrowsing_message_generator.h" + +// Generate destructors. +#include "ipc/struct_destructor_macros.h" +#include "components/safe_browsing/common/safebrowsing_message_generator.h" + +// Generate param traits size methods. +#include "ipc/param_traits_size_macros.h" +namespace IPC { +#include "components/safe_browsing/common/safebrowsing_message_generator.h" +} // namespace IPC + +// Generate param traits write methods. +#include "ipc/param_traits_write_macros.h" +namespace IPC { +#include "components/safe_browsing/common/safebrowsing_message_generator.h" +} // namespace IPC + +// Generate param traits read methods. +#include "ipc/param_traits_read_macros.h" +namespace IPC { +#include "components/safe_browsing/common/safebrowsing_message_generator.h" +} // namespace IPC + +// Generate param traits log methods. +#include "ipc/param_traits_log_macros.h" +namespace IPC { +#include "components/safe_browsing/common/safebrowsing_message_generator.h" +} // namespace IPC
diff --git a/components/safe_browsing/common/safebrowsing_message_generator.h b/components/safe_browsing/common/safebrowsing_message_generator.h new file mode 100644 index 0000000..8141e6d9c --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_message_generator.h
@@ -0,0 +1,7 @@ +// Copyright 2016 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. + +// Multiply-included file, hence no include guard. + +#include "components/safe_browsing/common/safebrowsing_messages.h"
diff --git a/chrome/common/safe_browsing/safebrowsing_messages.h b/components/safe_browsing/common/safebrowsing_messages.h similarity index 98% rename from chrome/common/safe_browsing/safebrowsing_messages.h rename to components/safe_browsing/common/safebrowsing_messages.h index 7391798..1432398 100644 --- a/chrome/common/safe_browsing/safebrowsing_messages.h +++ b/components/safe_browsing/common/safebrowsing_messages.h
@@ -9,6 +9,7 @@ #include "ipc/ipc_message_macros.h" #include "url/gurl.h" +#include "url/ipc/url_param_traits.h" #define IPC_MESSAGE_START SafeBrowsingMsgStart
diff --git a/components/safe_browsing/common/safebrowsing_switches.cc b/components/safe_browsing/common/safebrowsing_switches.cc new file mode 100644 index 0000000..04fb912f --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_switches.cc
@@ -0,0 +1,37 @@ +// Copyright 2016 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/safe_browsing/common/safebrowsing_switches.h" + +namespace safe_browsing { +namespace switches { + +// If present, safebrowsing only performs update when +// SafeBrowsingProtocolManager::ForceScheduleNextUpdate() is explicitly called. +// This is used for testing only. +const char kSbDisableAutoUpdate[] = "safebrowsing-disable-auto-update"; + +// TODO(lzheng): Remove this flag once the feature works fine +// (http://crbug.com/74848). +// +// Disables safebrowsing feature that checks download url and downloads +// content's hash to make sure the content are not malicious. +const char kSbDisableDownloadProtection[] = + "safebrowsing-disable-download-protection"; + +// Disables safebrowsing feature that checks for blacklisted extensions. +const char kSbDisableExtensionBlacklist[] = + "safebrowsing-disable-extension-blacklist"; + +// List of comma-separated sha256 hashes of executable files which the +// download-protection service should treat as "dangerous." For a file to +// show a warning, it also must be considered a dangerous filetype and not +// be whitelisted otherwise (by signature or URL) and must be on a supported +// OS. Hashes are in hex. This is used for manual testing when looking +// for ways to by-pass download protection. +const char kSbManualDownloadBlacklist[] = + "safebrowsing-manual-download-blacklist"; + +} // namespace switches +} // namespace safe_browsing
diff --git a/components/safe_browsing/common/safebrowsing_switches.h b/components/safe_browsing/common/safebrowsing_switches.h new file mode 100644 index 0000000..126795b --- /dev/null +++ b/components/safe_browsing/common/safebrowsing_switches.h
@@ -0,0 +1,19 @@ +// Copyright 2016 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_SAFE_BROWSING_COMMON_SAFEBROWSING_SWITCHES_H_ +#define COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_SWITCHES_H_ + +namespace safe_browsing { +namespace switches { + +extern const char kSbDisableAutoUpdate[]; +extern const char kSbDisableDownloadProtection[]; +extern const char kSbDisableExtensionBlacklist[]; +extern const char kSbManualDownloadBlacklist[]; + +} // namespace switches +} // namespace safe_browsing + +#endif // COMPONENTS_SAFE_BROWSING_COMMON_SAFEBROWSING_SWITCHES_H_
diff --git a/content/test/gpu/generate_buildbot_json.py b/content/test/gpu/generate_buildbot_json.py index ac09f63..d134dfc8 100755 --- a/content/test/gpu/generate_buildbot_json.py +++ b/content/test/gpu/generate_buildbot_json.py
@@ -856,6 +856,34 @@ 'args': ['--deqp-egl-display-type=angle-gl'] }, + 'angle_deqp_gles31_gl_tests': { + 'tester_configs': [ + { + 'fyi_only': True, + 'run_on_optional': False, + # Run on the Win/Linux Release NVIDIA bots. + 'build_configs': ['Release'], + 'swarming_dimension_sets': [ + { + 'gpu': '10de:104a', + 'os': 'Windows-2008ServerR2-SP1' + }, + { + 'gpu': '10de:104a', + 'os': 'Linux' + } + ], + } + ], + 'swarming': { + # TODO(geofflang): Increase the number of shards as more tests start to + # pass and runtime increases. + 'shards': 4, + }, + 'test': 'angle_deqp_gles31_tests', + 'args': ['--deqp-egl-display-type=angle-gl'] + }, + # Until we have more capacity, run angle_end2end_tests only on the # FYI waterfall, the ANGLE trybots (which mirror the FYI waterfall), # and the optional trybots (mainly used during ANGLE rolls).
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 35a18801..58de2127 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1210,6 +1210,8 @@ SYSTEM_DISPLAY_TOUCHCALIBRATIONSTART, SYSTEM_DISPLAY_TOUCHCALIBRATIONSET, SYSTEM_DISPLAY_TOUCHCALIBRATIONRESET, + CERTIFICATEPROVIDER_REQUESTPIN, + CERTIFICATEPROVIDER_STOPPINREQUEST, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/api/_behavior_features.json b/extensions/common/api/_behavior_features.json index 67171f7a..b05f1fc9e 100644 --- a/extensions/common/api/_behavior_features.json +++ b/extensions/common/api/_behavior_features.json
@@ -75,12 +75,19 @@ "channel": "stable", "component_extensions_auto_granted": false, "platforms": ["chromeos"], - "location": "external_component", "whitelist": [ "E24F1786D842E91E74C27929B0B3715A4689A473", // Gnubby component extension "6F9E349A0561C78A0D3F41496FE521C5151C7F71", // Gnubby app "8EBDF73405D0B84CEABB8C7513C9B9FA9F1DC2CE", // Genius app (help) - "3F50C3A83839D9C76334BCE81CDEC06174F266AF" // Virtual Keyboard + "06BE211D5F014BAB34BC22D9DDA09C63A81D828E", // Chrome OS XKB + "3F50C3A83839D9C76334BCE81CDEC06174F266AF", // Virtual Keyboard + "2F47B526FA71F44816618C41EC55E5EE9543FDCC", // Braille Keyboard + "86672C8D7A04E24EFB244BF96FE518C4C4809F73", // Speech synthesis + "1CF709D51B2B96CF79D00447300BD3BFBE401D21", // Mobile activation + "D519188F86D9ACCEE0412007B227D9936EB9676B", // Gaia auth extension + "40FF1103292F40C34066E023B8BE8CAE18306EAE", // Chromeos help + "3C654B3B6682CA194E75AD044CEDE927675DDEE8", // Easy unlock + "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E" // ChromeVox ] } ]
diff --git a/gpu/angle_deqp_tests_main.cc b/gpu/angle_deqp_tests_main.cc index 9814d70..daad62a 100644 --- a/gpu/angle_deqp_tests_main.cc +++ b/gpu/angle_deqp_tests_main.cc
@@ -19,7 +19,14 @@ } // namespace +// Defined in angle_deqp_gtest.cpp. Declared here so we don't need to make a +// header that we import in Chromium. +namespace angle { +void InitTestHarness(int* argc, char** argv); +} + int main(int argc, char** argv) { + angle::InitTestHarness(&argc, argv); base::CommandLine::Init(argc, argv); base::TestSuite test_suite(argc, argv); int rt = base::LaunchUnitTestsSerially(
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index b78c429..9f20f71d 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -76,6 +76,8 @@ {'name': 'cull_face'}, {'name': 'depth_test', 'state_flag': 'framebuffer_state_.clear_state_dirty'}, {'name': 'dither', 'default': True}, + {'name': 'framebuffer_srgb_ext', 'default': True, + 'extension_flag': 'ext_srgb_write_control'}, {'name': 'polygon_offset_fill'}, {'name': 'sample_alpha_to_coverage'}, {'name': 'sample_coverage'},
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc index 94192a6..5aa24fb 100644 --- a/gpu/command_buffer/service/context_state.cc +++ b/gpu/command_buffer/service/context_state.cc
@@ -221,7 +221,6 @@ pack_reverse_row_order(false), ignore_cached_state(false), fbo_binding_for_scissor_workaround_dirty(false), - framebuffer_srgb_(false), feature_info_(feature_info), error_state_(ErrorState::Create(error_state_client, logger)) { Initialize(); @@ -505,15 +504,8 @@ RestoreIndexedUniformBufferBindings(prev_state); RestoreGlobalState(prev_state); - if (!prev_state) { - if (feature_info_->feature_flags().desktop_srgb_support) { - framebuffer_srgb_ = false; - glDisable(GL_FRAMEBUFFER_SRGB); - } - } else if (framebuffer_srgb_ != prev_state->framebuffer_srgb_) { - // FRAMEBUFFER_SRGB will be restored lazily at render time. - framebuffer_srgb_ = prev_state->framebuffer_srgb_; - } + // FRAMEBUFFER_SRGB will be restored lazily at render time. + framebuffer_srgb_valid_ = false; } ErrorState* ContextState::GetErrorState() { @@ -706,10 +698,11 @@ } void ContextState::EnableDisableFramebufferSRGB(bool enable) { - if (framebuffer_srgb_ == enable) + if (framebuffer_srgb_valid_ && framebuffer_srgb_ == enable) return; EnableDisable(GL_FRAMEBUFFER_SRGB, enable); framebuffer_srgb_ = enable; + framebuffer_srgb_valid_ = true; } void ContextState::InitStateManual(const ContextState*) const {
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h index 72e4c6c2..6566974 100644 --- a/gpu/command_buffer/service/context_state.h +++ b/gpu/command_buffer/service/context_state.h
@@ -354,7 +354,11 @@ void InitStateManual(const ContextState* prev_state) const; - bool framebuffer_srgb_; + // EnableDisableFramebufferSRGB is called at very high frequency. Cache the + // true value of FRAMEBUFFER_SRGB, if we know it, to elide some of these + // calls. + bool framebuffer_srgb_valid_ = false; + bool framebuffer_srgb_ = false; // Generic vertex attrib base types: FLOAT, INT, or UINT. // Each base type is encoded into 2 bits, the lowest 2 bits for location 0,
diff --git a/gpu/command_buffer/service/context_state_autogen.h b/gpu/command_buffer/service/context_state_autogen.h index c0da2cd..38fae6e 100644 --- a/gpu/command_buffer/service/context_state_autogen.h +++ b/gpu/command_buffer/service/context_state_autogen.h
@@ -22,6 +22,8 @@ bool cached_depth_test; bool dither; bool cached_dither; + bool framebuffer_srgb_ext; + bool cached_framebuffer_srgb_ext; bool polygon_offset_fill; bool cached_polygon_offset_fill; bool sample_alpha_to_coverage; @@ -143,6 +145,12 @@ return; enable_flags.cached_dither = enable; break; + case GL_FRAMEBUFFER_SRGB_EXT: + if (enable_flags.cached_framebuffer_srgb_ext == enable && + !ignore_cached_state) + return; + enable_flags.cached_framebuffer_srgb_ext = enable; + break; case GL_POLYGON_OFFSET_FILL: if (enable_flags.cached_polygon_offset_fill == enable && !ignore_cached_state)
diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h index 6bc4a82..3569bbf 100644 --- a/gpu/command_buffer/service/context_state_impl_autogen.h +++ b/gpu/command_buffer/service/context_state_impl_autogen.h
@@ -21,6 +21,8 @@ cached_depth_test(false), dither(true), cached_dither(true), + framebuffer_srgb_ext(true), + cached_framebuffer_srgb_ext(true), polygon_offset_fill(false), cached_polygon_offset_fill(false), sample_alpha_to_coverage(false), @@ -167,6 +169,13 @@ if (prev_state->enable_flags.cached_dither != enable_flags.cached_dither) { EnableDisable(GL_DITHER, enable_flags.cached_dither); } + if (feature_info_->feature_flags().ext_srgb_write_control) { + if (prev_state->enable_flags.cached_framebuffer_srgb_ext != + enable_flags.cached_framebuffer_srgb_ext) { + EnableDisable(GL_FRAMEBUFFER_SRGB_EXT, + enable_flags.cached_framebuffer_srgb_ext); + } + } if (prev_state->enable_flags.cached_polygon_offset_fill != enable_flags.cached_polygon_offset_fill) { EnableDisable(GL_POLYGON_OFFSET_FILL, @@ -219,6 +228,10 @@ EnableDisable(GL_CULL_FACE, enable_flags.cached_cull_face); EnableDisable(GL_DEPTH_TEST, enable_flags.cached_depth_test); EnableDisable(GL_DITHER, enable_flags.cached_dither); + if (feature_info_->feature_flags().ext_srgb_write_control) { + EnableDisable(GL_FRAMEBUFFER_SRGB_EXT, + enable_flags.cached_framebuffer_srgb_ext); + } EnableDisable(GL_POLYGON_OFFSET_FILL, enable_flags.cached_polygon_offset_fill); EnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, @@ -433,6 +446,8 @@ return enable_flags.depth_test; case GL_DITHER: return enable_flags.dither; + case GL_FRAMEBUFFER_SRGB_EXT: + return enable_flags.framebuffer_srgb_ext; case GL_POLYGON_OFFSET_FILL: return enable_flags.polygon_offset_fill; case GL_SAMPLE_ALPHA_TO_COVERAGE: @@ -835,6 +850,12 @@ params[0] = static_cast<GLint>(enable_flags.dither); } return true; + case GL_FRAMEBUFFER_SRGB_EXT: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(enable_flags.framebuffer_srgb_ext); + } + return true; case GL_POLYGON_OFFSET_FILL: *num_written = 1; if (params) { @@ -1269,6 +1290,12 @@ params[0] = static_cast<GLfloat>(enable_flags.dither); } return true; + case GL_FRAMEBUFFER_SRGB_EXT: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(enable_flags.framebuffer_srgb_ext); + } + return true; case GL_POLYGON_OFFSET_FILL: *num_written = 1; if (params) {
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 77000c5..cd87ab2 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc
@@ -572,11 +572,13 @@ validators_.index_type.AddValue(GL_UNSIGNED_INT); } + bool has_srgb_framebuffer_support = false; if (gl_version_info_->IsAtLeastGL(3, 2) || (gl_version_info_->IsAtLeastGL(2, 0) && (extensions.Contains("GL_EXT_framebuffer_sRGB") || extensions.Contains("GL_ARB_framebuffer_sRGB")))) { feature_flags_.desktop_srgb_support = true; + has_srgb_framebuffer_support = true; } // With EXT_sRGB, unsized SRGB_EXT and SRGB_ALPHA_EXT are accepted by the // <format> and <internalformat> parameter of TexImage2D. GLES3 adds support @@ -599,6 +601,22 @@ GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT); validators_.texture_unsized_internal_format.AddValue(GL_SRGB_EXT); validators_.texture_unsized_internal_format.AddValue(GL_SRGB_ALPHA_EXT); + has_srgb_framebuffer_support = true; + } + if (gl_version_info_->is_es3) + has_srgb_framebuffer_support = true; + + if (has_srgb_framebuffer_support && !IsWebGLContext()) { + // GL_FRAMEBUFFER_SRGB_EXT is exposed by the GLES extension + // GL_EXT_sRGB_write_control (which is not part of the core, even in GLES3), + // and the desktop extension GL_ARB_framebuffer_sRGB (part of the core in + // 3.0). + if (feature_flags_.desktop_srgb_support || + extensions.Contains("GL_EXT_sRGB_write_control")) { + feature_flags_.ext_srgb_write_control = true; + AddExtensionString("GL_EXT_sRGB_write_control"); + validators_.capability.AddValue(GL_FRAMEBUFFER_SRGB_EXT); + } } // On desktop, GL_EXT_texture_sRGB is required regardless of GL version,
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index d72dfc1..8128c72 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -98,6 +98,7 @@ bool khr_debug = false; bool chromium_bind_generates_resource = false; bool angle_webgl_compatibility = false; + bool ext_srgb_write_control = false; }; FeatureInfo();
diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index 49b8d19..902a9531 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc
@@ -246,8 +246,11 @@ NOTREACHED(); break; } + // Note that because GL_EXT_sRGB is a substring of GL_EXT_sRGB_write_control, + // which is not part of the ES3 core, we have to be careful to search for + // "GL_EXT_sRGB ", and append a space to the end of the extension string. if (expect_ext_srgb) { - EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_sRGB")); + EXPECT_THAT(info_->extensions() + " ", HasSubstr("GL_EXT_sRGB ")); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_SRGB_EXT)); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_SRGB_ALPHA_EXT)); EXPECT_TRUE(info_->validators()->texture_internal_format.IsValid( @@ -259,7 +262,7 @@ EXPECT_TRUE(info_->validators()->framebuffer_parameter.IsValid( GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)); } else { - EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_EXT_sRGB"))); + EXPECT_THAT(info_->extensions() + " ", Not(HasSubstr("GL_EXT_sRGB "))); EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_SRGB_EXT)); EXPECT_FALSE(info_->validators()->texture_format.IsValid( GL_SRGB_ALPHA_EXT)); @@ -593,7 +596,7 @@ SetupInitExpectations("GL_EXT_sRGB GL_OES_rgb8_rgba8"); if (GetContextType() == CONTEXT_TYPE_OPENGLES3) { - EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_EXT_sRGB"))); + EXPECT_THAT(info_->extensions() + " ", Not(HasSubstr("GL_EXT_sRGB "))); EXPECT_FALSE(info_->validators()->texture_format.IsValid(GL_SRGB_EXT)); EXPECT_FALSE( info_->validators()->texture_format.IsValid(GL_SRGB_ALPHA_EXT)); @@ -606,7 +609,7 @@ EXPECT_FALSE(info_->validators()->framebuffer_parameter.IsValid( GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT)); } else { - EXPECT_THAT(info_->extensions(), HasSubstr("GL_EXT_sRGB")); + EXPECT_THAT(info_->extensions() + " ", HasSubstr("GL_EXT_sRGB ")); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_SRGB_EXT)); EXPECT_TRUE(info_->validators()->texture_format.IsValid(GL_SRGB_ALPHA_EXT)); EXPECT_TRUE( @@ -922,7 +925,7 @@ TEST_P(FeatureInfoTest, Initialize_sRGBGLES3) { SetupInitExpectationsWithGLVersion("", "", "OpenGL ES 3.0"); - EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_EXT_sRGB"))); + EXPECT_THAT(info_->extensions() + " ", Not(HasSubstr("GL_EXT_sRGB "))); EXPECT_FALSE(info_->validators()->texture_format.IsValid( GL_SRGB_EXT)); EXPECT_FALSE(info_->validators()->texture_format.IsValid(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 46dc896..f5c727b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -707,6 +707,7 @@ // Workarounds void OnFboChanged() const; void OnUseFramebuffer() const; + void UpdateFramebufferSRGB(Framebuffer* framebuffer); error::ContextLostReason GetContextLostReasonFromResetStatus( GLenum reset_status) const; @@ -3458,6 +3459,7 @@ DoBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); DoBindFramebuffer(GL_FRAMEBUFFER, 0); DoBindRenderbuffer(GL_RENDERBUFFER, 0); + UpdateFramebufferSRGB(nullptr); bool call_gl_clear = !surfaceless_ && !offscreen; #if defined(OS_ANDROID) @@ -4295,21 +4297,37 @@ Framebuffer* framebuffer = GetFramebufferInfoForTarget(target); bool valid = CheckFramebufferValid( framebuffer, target, GL_INVALID_FRAMEBUFFER_OPERATION, func_name); - if (valid && !features().chromium_framebuffer_multisample) + if (!valid) + return false; + + if (!features().chromium_framebuffer_multisample) OnUseFramebuffer(); - if (valid && feature_info_->feature_flags().desktop_srgb_support) { - // If framebuffer contains sRGB images, then enable FRAMEBUFFER_SRGB. - // Otherwise, disable FRAMEBUFFER_SRGB. Assume default fbo does not have - // sRGB image. - // In theory, we can just leave FRAMEBUFFER_SRGB on. However, many drivers - // behave incorrectly when all images are linear encoding, they still apply - // the sRGB conversion, but when at least one image is sRGB, then they - // behave correctly. - bool enable_framebuffer_srgb = - framebuffer && framebuffer->HasSRGBAttachments(); - state_.EnableDisableFramebufferSRGB(enable_framebuffer_srgb); + + UpdateFramebufferSRGB(framebuffer); + return true; +} + +void GLES2DecoderImpl::UpdateFramebufferSRGB(Framebuffer* framebuffer) { + // Manually set the value of FRAMEBUFFER_SRGB based on the state that was set + // by the client. + bool needs_enable_disable_framebuffer_srgb = false; + bool enable_framebuffer_srgb = true; + if (feature_info_->feature_flags().ext_srgb_write_control) { + needs_enable_disable_framebuffer_srgb = true; + enable_framebuffer_srgb &= state_.GetEnabled(GL_FRAMEBUFFER_SRGB); } - return valid; + // On desktop, enable FRAMEBUFFER_SRGB only if the framebuffer contains sRGB + // attachments. In theory, we can just leave FRAMEBUFFER_SRGB enabled, + // however, + // many drivers behave incorrectly when no attachments are sRGB. When at + // least one attachment is sRGB, then they behave correctly. + if (feature_info_->feature_flags().desktop_srgb_support) { + needs_enable_disable_framebuffer_srgb = true; + // Assume that the default fbo does not have an sRGB image. + enable_framebuffer_srgb &= framebuffer && framebuffer->HasSRGBAttachments(); + } + if (needs_enable_disable_framebuffer_srgb) + state_.EnableDisableFramebufferSRGB(enable_framebuffer_srgb); } bool GLES2DecoderImpl::CheckBoundReadFramebufferValid( @@ -7424,6 +7442,11 @@ // DrawElements* for old desktop GL. return; } + if (cap == GL_FRAMEBUFFER_SRGB) { + // Enable and Disable GL_FRAMEBUFFER_SRGB is done manually in + // CheckBoundDrawFramebufferValid. + return; + } glDisable(cap); } } @@ -7436,6 +7459,11 @@ // DrawElements* for old desktop GL. return; } + if (cap == GL_FRAMEBUFFER_SRGB) { + // Enable and Disable GL_FRAMEBUFFER_SRGB is done manually in + // CheckBoundDrawFramebufferValid. + return; + } glEnable(cap); } }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 0895cdd..1f961d1 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5140,6 +5140,14 @@ return true; } return false; + case GL_FRAMEBUFFER_SRGB_EXT: + state_.enable_flags.framebuffer_srgb_ext = enabled; + if (state_.enable_flags.cached_framebuffer_srgb_ext != enabled || + state_.ignore_cached_state) { + state_.enable_flags.cached_framebuffer_srgb_ext = enabled; + return true; + } + return false; case GL_POLYGON_OFFSET_FILL: state_.enable_flags.polygon_offset_fill = enabled; if (state_.enable_flags.cached_polygon_offset_fill != enabled ||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h index af2e41c..d155c35 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
@@ -17,6 +17,9 @@ ExpectEnableDisable(GL_CULL_FACE, false); ExpectEnableDisable(GL_DEPTH_TEST, false); ExpectEnableDisable(GL_DITHER, true); + if (group_->feature_info()->feature_flags().ext_srgb_write_control) { + ExpectEnableDisable(GL_FRAMEBUFFER_SRGB_EXT, true); + } ExpectEnableDisable(GL_POLYGON_OFFSET_FILL, false); ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_COVERAGE, false); ExpectEnableDisable(GL_SAMPLE_COVERAGE, false);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index bbc96b4..9352747 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -435,6 +435,13 @@ .Times(1) .RetiresOnSaturation(); + if (group_->feature_info()->feature_flags().ext_srgb_write_control || + group_->feature_info()->feature_flags().desktop_srgb_support) { + EXPECT_CALL(*gl_, Disable(GL_FRAMEBUFFER_SRGB)) + .Times(1) + .RetiresOnSaturation(); + } + // TODO(boliu): Remove OS_ANDROID once crbug.com/259023 is fixed and the // workaround has been reverted. #if !defined(OS_ANDROID)
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc index bf860a6..f10a919 100644 --- a/gpu/command_buffer/tests/gl_test_utils.cc +++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -71,9 +71,13 @@ } bool GLTestHelper::HasExtension(const char* extension) { - std::string extensions( - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); - return extensions.find(extension) != std::string::npos; + // Pad with an extra space to ensure that |extension| is not a substring of + // another extension. + std::string extensions = + std::string(reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))) + + " "; + std::string extension_padded = std::string(extension) + " "; + return extensions.find(extension_padded) != std::string::npos; } bool GLTestHelper::CheckGLError(const char* msg, int line) {
diff --git a/mash/BUILD.gn b/mash/BUILD.gn index b4337e0..c1eb630 100644 --- a/mash/BUILD.gn +++ b/mash/BUILD.gn
@@ -17,6 +17,7 @@ "//mash/login", "//mash/screenlock", "//mash/session", + "//mash/simple_wm", "//mash/task_viewer", ]
diff --git a/mash/common/BUILD.gn b/mash/common/BUILD.gn new file mode 100644 index 0000000..3f285f0 --- /dev/null +++ b/mash/common/BUILD.gn
@@ -0,0 +1,14 @@ +# Copyright 2016 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. + +source_set("common") { + sources = [ + "config.cc", + "config.h", + ] + + deps = [ + "//base", + ] +}
diff --git a/mash/common/config.cc b/mash/common/config.cc new file mode 100644 index 0000000..f4e14f7 --- /dev/null +++ b/mash/common/config.cc
@@ -0,0 +1,26 @@ +// Copyright 2016 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 "mash/common/config.h" + +#include "base/command_line.h" + +namespace mash { +namespace common { + +const char kWindowManagerSwitch[] = "window-manager"; + +std::string GetWindowManagerServiceName() { + if (base::CommandLine::ForCurrentProcess()->HasSwitch(kWindowManagerSwitch)) { + std::string service_name = + base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( + kWindowManagerSwitch); + return service_name; + } + // TODO(beng): move this constant to a mojom file in //ash. + return "ash"; +} + +} // namespace common +} // namespace mash
diff --git a/mash/common/config.h b/mash/common/config.h new file mode 100644 index 0000000..3f7e6e2 --- /dev/null +++ b/mash/common/config.h
@@ -0,0 +1,24 @@ +// Copyright 2016 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 MASH_COMMON_CONFIG_H_ +#define MASH_COMMON_CONFIG_H_ + +#include <string> + +namespace mash { +namespace common { + +// This file contains configuration functions that can be used by any mash +// service. + +// Returns the name of the window manager service to run. By default this will +// return "ash". A different value can be specified on the command line by +// passing --window-manager=<foo>. +std::string GetWindowManagerServiceName(); + +} // namespace common +} // namespace mash + +#endif // MASH_COMMON_CONFIG_H_
diff --git a/mash/login/BUILD.gn b/mash/login/BUILD.gn index 10efd20..3fc13dd 100644 --- a/mash/login/BUILD.gn +++ b/mash/login/BUILD.gn
@@ -19,6 +19,7 @@ "//ash/public/cpp", "//ash/public/interfaces", "//base", + "//mash/common", "//mash/init/public/interfaces", "//mash/login/public/interfaces", "//mojo/public/cpp/bindings",
diff --git a/mash/login/login.cc b/mash/login/login.cc index e428075a..d28929d 100644 --- a/mash/login/login.cc +++ b/mash/login/login.cc
@@ -13,6 +13,7 @@ #include "base/memory/ptr_util.h" #include "base/message_loop/message_loop.h" #include "base/strings/utf_string_conversions.h" +#include "mash/common/config.h" #include "mash/init/public/interfaces/constants.mojom.h" #include "mash/init/public/interfaces/init.mojom.h" #include "mash/login/public/interfaces/login.mojom.h" @@ -117,7 +118,8 @@ void ButtonPressed(views::Button* sender, const ui::Event& event) override; void StartWindowManager(const service_manager::Identity& identity) { - mash_wm_connection_ = connector_->Connect("ash"); + mash_wm_connection_ = + connector_->Connect(common::GetWindowManagerServiceName()); mash_wm_connection_->SetConnectionLostClosure( base::Bind(&UI::StartWindowManager, base::Unretained(this), identity)); window_manager_connection_ =
diff --git a/mash/session/BUILD.gn b/mash/session/BUILD.gn index 535adad4..0083be0a 100644 --- a/mash/session/BUILD.gn +++ b/mash/session/BUILD.gn
@@ -17,6 +17,7 @@ deps = [ "//base", "//content/public/common:service_names", + "//mash/common", "//mash/login/public/interfaces", "//mash/quick_launch/public/interfaces:constants", "//mash/screenlock/public/interfaces:constants",
diff --git a/mash/session/session.cc b/mash/session/session.cc index f72a9a35..a28ac33 100644 --- a/mash/session/session.cc +++ b/mash/session/session.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "content/public/common/service_names.mojom.h" +#include "mash/common/config.h" #include "mash/login/public/interfaces/constants.mojom.h" #include "mash/login/public/interfaces/login.mojom.h" #include "mash/quick_launch/public/interfaces/constants.mojom.h" @@ -99,7 +100,7 @@ void Session::StartWindowManager() { StartRestartableService( - "ash", + common::GetWindowManagerServiceName(), base::Bind(&Session::StartWindowManager, base::Unretained(this))); }
diff --git a/mash/simple_wm/BUILD.gn b/mash/simple_wm/BUILD.gn new file mode 100644 index 0000000..2145fde --- /dev/null +++ b/mash/simple_wm/BUILD.gn
@@ -0,0 +1,62 @@ +# Copyright 2016 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/ui.gni") +import("//services/service_manager/public/cpp/service.gni") +import("//services/service_manager/public/service_manifest.gni") +import("//tools/grit/repack.gni") + +service("simple_wm") { + testonly = true + + sources = [ + "main.cc", + ] + + deps = [ + ":lib", + "//base", + "//services/service_manager/public/cpp", + "//ui/views/mus:for_mojo_application", + ] + + resources = [ "$root_out_dir/views_mus_resources.pak" ] +} + +source_set("lib") { + testonly = true + sources = [ + "simple_wm.cc", + "simple_wm.h", + ] + + deps = [ + "//base", + "//services/service_manager/public/cpp", + "//services/ui/public/cpp", + "//services/ui/public/interfaces", + "//ui/aura", + "//ui/aura:test_support", + "//ui/display", + "//ui/display:test_support", + "//ui/gfx/geometry/mojo", + "//ui/views", + "//ui/views/mus:mus", + "//ui/wm", + ] + + public_deps = [ + "//skia", # Due to use of Sk types in service header. + ] + + data_deps = [ + ":manifest", + "//services/ui", + ] +} + +service_manifest("manifest") { + name = "simple_wm" + source = "manifest.json" +}
diff --git a/mash/simple_wm/main.cc b/mash/simple_wm/main.cc new file mode 100644 index 0000000..42311306 --- /dev/null +++ b/mash/simple_wm/main.cc
@@ -0,0 +1,12 @@ +// Copyright 2016 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 "mash/simple_wm/simple_wm.h" +#include "services/service_manager/public/c/main.h" +#include "services/service_manager/public/cpp/service_runner.h" + +MojoResult ServiceMain(MojoHandle service_request_handle) { + service_manager::ServiceRunner runner(new simple_wm::SimpleWM); + return runner.Run(service_request_handle); +}
diff --git a/mash/simple_wm/manifest.json b/mash/simple_wm/manifest.json new file mode 100644 index 0000000..32164e3 --- /dev/null +++ b/mash/simple_wm/manifest.json
@@ -0,0 +1,12 @@ +{ + "name": "simple_wm", + "display_name": "Simple Window Manager", + "interface_provider_specs": { + "service_manager:connector": { + "requires": { + "*": [ "app" ], + "ui": [ "ui:window_manager" ] + } + } + } +}
diff --git a/mash/simple_wm/simple_wm.cc b/mash/simple_wm/simple_wm.cc new file mode 100644 index 0000000..49917e2 --- /dev/null +++ b/mash/simple_wm/simple_wm.cc
@@ -0,0 +1,245 @@ +// Copyright 2016 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 "mash/simple_wm/simple_wm.h" + +#include "base/strings/utf_string_conversions.h" +#include "ui/aura/client/aura_constants.h" +#include "ui/display/screen_base.h" +#include "ui/gfx/canvas.h" +#include "ui/gfx/geometry/mojo/geometry.mojom.h" +#include "ui/views/controls/label.h" +#include "ui/views/mus/aura_init.h" +#include "ui/views/mus/mus_client.h" +#include "ui/views/widget/native_widget_aura.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" +#include "ui/wm/core/default_activation_client.h" + +namespace simple_wm { + +namespace { + +const int kNonClientTopHeight = 24; +const int kNonClientSize = 5; + +} // namespace + +class SimpleWM::FrameView : public views::WidgetDelegateView, + public aura::WindowObserver { + public: + explicit FrameView(aura::Window* client_window) + : client_window_(client_window) { + client_window_->AddObserver(this); + } + ~FrameView() override {} + + private: + // views::WidgetDelegateView: + base::string16 GetWindowTitle() const override { + base::string16* title = + client_window_->GetProperty(aura::client::kTitleKey); + if (!title) + return base::UTF8ToUTF16("(Window)"); + return *title; + } + void Layout() override { + // Client offsets are applied automatically by the window service. + gfx::Rect parent_bounds = GetWidget()->GetNativeWindow()->bounds(); + parent_bounds.set_origin(gfx::Point()); + client_window_->SetBounds(parent_bounds); + } + + // aura::WindowObserver: + void OnWindowPropertyChanged(aura::Window* window, const void* key, + intptr_t old) override { + if (key == aura::client::kTitleKey) + GetWidget()->UpdateWindowTitle(); + } + + aura::Window* client_window_; + + DISALLOW_COPY_AND_ASSIGN(FrameView); +}; + +SimpleWM::SimpleWM() {} + +SimpleWM::~SimpleWM() { + // WindowTreeHost uses state from WindowTreeClient, so destroy it first. + window_tree_host_.reset(); + + // WindowTreeClient destruction may callback to us. + window_tree_client_.reset(); + + gpu_service_.reset(); + + display::Screen::SetScreenInstance(nullptr); +} + +void SimpleWM::OnStart() { + CHECK(!started_); + started_ = true; + screen_ = base::MakeUnique<display::ScreenBase>(); + display::Screen::SetScreenInstance(screen_.get()); + aura_init_ = base::MakeUnique<views::AuraInit>( + context()->connector(), context()->identity(), "views_mus_resources.pak", + std::string(), nullptr, views::AuraInit::Mode::AURA_MUS_WINDOW_MANAGER); + gpu_service_ = ui::GpuService::Create(context()->connector(), nullptr); + compositor_context_factory_ = + base::MakeUnique<aura::MusContextFactory>(gpu_service_.get()); + aura::Env::GetInstance()->set_context_factory( + compositor_context_factory_.get()); + window_tree_client_ = base::MakeUnique<aura::WindowTreeClient>( + context()->connector(), this, this); + aura::Env::GetInstance()->SetWindowTreeClient(window_tree_client_.get()); + window_tree_client_->ConnectAsWindowManager(); +} + +bool SimpleWM::OnConnect( + const service_manager::ServiceInfo& remote_info, + service_manager::InterfaceRegistry* registry) { + return true; +} + +void SimpleWM::OnEmbed( + std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) { + // WindowTreeClients configured as the window manager should never get + // OnEmbed(). + NOTREACHED(); +} + +void SimpleWM::OnLostConnection(aura::WindowTreeClient* client) { + window_tree_host_.reset(); + window_tree_client_.reset(); +} + +void SimpleWM::OnEmbedRootDestroyed(aura::Window* root) { + // WindowTreeClients configured as the window manager should never get + // OnEmbedRootDestroyed(). + NOTREACHED(); +} + +void SimpleWM::OnPointerEventObserved(const ui::PointerEvent& event, + aura::Window* target) { + // Don't care. +} + +aura::client::CaptureClient* SimpleWM::GetCaptureClient() { + return wm_state_.capture_controller(); +} + +aura::PropertyConverter* SimpleWM::GetPropertyConverter() { + return &property_converter_; +} + +void SimpleWM::SetWindowManagerClient( + aura::WindowManagerClient* client) { + window_manager_client_ = client; +} + +bool SimpleWM::OnWmSetBounds(aura::Window* window, gfx::Rect* bounds) { + FrameView* frame_view = GetFrameViewForClientWindow(window); + frame_view->GetWidget()->SetBounds(*bounds); + return true; +} + +bool SimpleWM::OnWmSetProperty( + aura::Window* window, + const std::string& name, + std::unique_ptr<std::vector<uint8_t>>* new_data) { + return true; +} + +aura::Window* SimpleWM::OnWmCreateTopLevelWindow( + ui::mojom::WindowType window_type, + std::map<std::string, std::vector<uint8_t>>* properties) { + aura::Window* client_window = new aura::Window(nullptr); + SetWindowType(client_window, window_type); + client_window->Init(ui::LAYER_NOT_DRAWN); + + views::Widget* frame_widget = new views::Widget; + views::NativeWidgetAura* frame_native_widget = + new views::NativeWidgetAura(frame_widget, true); + views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); + FrameView* frame_view = new FrameView(client_window); + params.delegate = frame_view; + params.native_widget = frame_native_widget; + params.parent = root_; + params.bounds = gfx::Rect(10, 10, 500, 500); + frame_widget->Init(params); + frame_widget->Show(); + + frame_widget->GetNativeWindow()->AddChild(client_window); + + client_window_to_frame_view_[client_window] = frame_view; + // TODO(beng): probably need to observe client_window from now on so we can + // clean up this map. + + return client_window; +} + +void SimpleWM::OnWmClientJankinessChanged( + const std::set<aura::Window*>& client_windows, + bool janky) { + // Don't care. +} + +void SimpleWM::OnWmWillCreateDisplay(const display::Display& display) { + screen_->display_list().AddDisplay(display, + display::DisplayList::Type::PRIMARY); +} + +void SimpleWM::OnWmNewDisplay( + std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, + const display::Display& display) { + // Only handles a single root. + DCHECK(!root_); + window_tree_host_ = std::move(window_tree_host); + window_tree_host_->InitCompositor(); + root_ = window_tree_host_->window(); + DCHECK(window_manager_client_); + window_manager_client_->AddActivationParent(root_); + ui::mojom::FrameDecorationValuesPtr frame_decoration_values = + ui::mojom::FrameDecorationValues::New(); + frame_decoration_values->normal_client_area_insets.Set( + kNonClientTopHeight, kNonClientSize, kNonClientSize, kNonClientSize); + frame_decoration_values->max_title_bar_button_width = 0; + window_manager_client_->SetFrameDecorationValues( + std::move(frame_decoration_values)); + new wm::DefaultActivationClient(root_); + aura::client::SetFocusClient(root_, &focus_client_); +} + +void SimpleWM::OnWmDisplayRemoved( + aura::WindowTreeHostMus* window_tree_host) { + DCHECK_EQ(window_tree_host, window_tree_host_.get()); + root_ = nullptr; + window_tree_host_.reset(); +} + +void SimpleWM::OnWmDisplayModified(const display::Display& display) {} + +void SimpleWM::OnWmPerformMoveLoop( + aura::Window* window, + ui::mojom::MoveLoopSource source, + const gfx::Point& cursor_location, + const base::Callback<void(bool)>& on_done) { + // Don't care. +} + +void SimpleWM::OnWmCancelMoveLoop(aura::Window* window) {} + +void SimpleWM::OnWmSetClientArea( + aura::Window* window, + const gfx::Insets& insets, + const std::vector<gfx::Rect>& additional_client_areas) {} + +SimpleWM::FrameView* SimpleWM::GetFrameViewForClientWindow( + aura::Window* client_window) { + auto it = client_window_to_frame_view_.find(client_window); + return it != client_window_to_frame_view_.end() ? it->second : nullptr; +} + +} // namespace simple_wm +
diff --git a/mash/simple_wm/simple_wm.h b/mash/simple_wm/simple_wm.h new file mode 100644 index 0000000..ac7042ca --- /dev/null +++ b/mash/simple_wm/simple_wm.h
@@ -0,0 +1,116 @@ +// Copyright 2016 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 MASH_SIMPLE_WM_SIMPLE_WM_H_ +#define MASH_SIMPLE_WM_SIMPLE_WM_H_ + +#include <memory> +#include <utility> + +#include "base/memory/ptr_util.h" +#include "base/threading/thread_task_runner_handle.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/service_context.h" +#include "services/ui/public/cpp/gpu/gpu_service.h" +#include "ui/aura/env.h" +#include "ui/aura/mus/mus_context_factory.h" +#include "ui/aura/mus/property_converter.h" +#include "ui/aura/mus/property_utils.h" +#include "ui/aura/mus/window_manager_delegate.h" +#include "ui/aura/mus/window_tree_client.h" +#include "ui/aura/mus/window_tree_client_delegate.h" +#include "ui/aura/mus/window_tree_host_mus.h" +#include "ui/aura/test/test_focus_client.h" +#include "ui/aura/window.h" +#include "ui/display/display.h" +#include "ui/wm/core/capture_controller.h" +#include "ui/wm/core/wm_state.h" + +namespace display { +class ScreenBase; +} + +namespace views { +class AuraInit; +} + +namespace simple_wm { + +class SimpleWM : public service_manager::Service, + public aura::WindowTreeClientDelegate, + public aura::WindowManagerDelegate { + public: + SimpleWM(); + ~SimpleWM() override; + + private: + class FrameView; + + // service_manager::Service: + void OnStart() override; + bool OnConnect(const service_manager::ServiceInfo& remote_info, + service_manager::InterfaceRegistry* registry) override; + + // aura::WindowTreeClientDelegate: + void OnEmbed( + std::unique_ptr<aura::WindowTreeHostMus> window_tree_host) override; + void OnLostConnection(aura::WindowTreeClient* client) override; + void OnEmbedRootDestroyed(aura::Window* root) override; + void OnPointerEventObserved(const ui::PointerEvent& event, + aura::Window* target) override; + aura::client::CaptureClient* GetCaptureClient() override; + aura::PropertyConverter* GetPropertyConverter() override; + + // aura::WindowManagerDelegate: + void SetWindowManagerClient(aura::WindowManagerClient* client) override; + bool OnWmSetBounds(aura::Window* window, gfx::Rect* bounds) override; + bool OnWmSetProperty( + aura::Window* window, + const std::string& name, + std::unique_ptr<std::vector<uint8_t>>* new_data) override; + aura::Window* OnWmCreateTopLevelWindow( + ui::mojom::WindowType window_type, + std::map<std::string, std::vector<uint8_t>>* properties) override; + void OnWmClientJankinessChanged(const std::set<aura::Window*>& client_windows, + bool janky) override; + void OnWmWillCreateDisplay(const display::Display& display) override; + void OnWmNewDisplay(std::unique_ptr<aura::WindowTreeHostMus> window_tree_host, + const display::Display& display) override; + void OnWmDisplayRemoved(aura::WindowTreeHostMus* window_tree_host) override; + void OnWmDisplayModified(const display::Display& display) override; + void OnWmPerformMoveLoop(aura::Window* window, + ui::mojom::MoveLoopSource source, + const gfx::Point& cursor_location, + const base::Callback<void(bool)>& on_done) override; + void OnWmCancelMoveLoop(aura::Window* window) override; + void OnWmSetClientArea( + aura::Window* window, + const gfx::Insets& insets, + const std::vector<gfx::Rect>& additional_client_areas) override; + + FrameView* GetFrameViewForClientWindow(aura::Window* client_window); + + std::unique_ptr<views::AuraInit> aura_init_; + ::wm::WMState wm_state_; + std::unique_ptr<display::ScreenBase> screen_; + aura::PropertyConverter property_converter_; + aura::test::TestFocusClient focus_client_; + std::unique_ptr<aura::WindowTreeHostMus> window_tree_host_; + aura::Window* root_ = nullptr; + aura::WindowManagerClient* window_manager_client_ = nullptr; + std::unique_ptr<aura::WindowTreeClient> window_tree_client_; + std::unique_ptr<ui::GpuService> gpu_service_; + std::unique_ptr<aura::MusContextFactory> compositor_context_factory_; + std::map<aura::Window*, FrameView*> client_window_to_frame_view_; + + bool started_ = false; + + DISALLOW_COPY_AND_ASSIGN(SimpleWM); +}; + +} // namespace simple_wm + +#endif // MASH_SIMPLE_WM_SIMPLE_WM_H_
diff --git a/pdf/pdf.cc b/pdf/pdf.cc index e60c4bd..e6cf5480 100644 --- a/pdf/pdf.cc +++ b/pdf/pdf.cc
@@ -82,7 +82,8 @@ } #if defined(OS_WIN) -bool RenderPDFPageToDC(void* pdf_handle, +bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, int page_number, HDC dc, int dpi, @@ -106,8 +107,8 @@ pp::Rect(bounds_origin_x, bounds_origin_y, bounds_width, bounds_height), fit_to_bounds, stretch_to_bounds, keep_aspect_ratio, center_in_bounds, autorotate); - bool ret = - engine_exports->RenderPDFPageToDC(pdf_handle, page_number, settings, dc); + bool ret = engine_exports->RenderPDFPageToDC(pdf_buffer, buffer_size, + page_number, settings, dc); if (!g_sdk_initialized_via_pepper) ShutdownSDK(); @@ -127,49 +128,40 @@ bool GetPDFDocInfo(const void* pdf_buffer, int buffer_size, int* page_count, - double* max_page_width, - void** pdf_handle) { + double* max_page_width) { if (!g_sdk_initialized_via_pepper) { if (!InitializeSDK()) return false; } PDFEngineExports* engine_exports = PDFEngineExports::Get(); bool ret = engine_exports->GetPDFDocInfo(pdf_buffer, buffer_size, page_count, - max_page_width, pdf_handle); + max_page_width); if (!g_sdk_initialized_via_pepper) ShutdownSDK(); return ret; } -void ReleasePDFHandle(void* pdf_handle) { - if (!g_sdk_initialized_via_pepper) { - if (!InitializeSDK()) - return; - } - PDFEngineExports* engine_exports = PDFEngineExports::Get(); - engine_exports->ReleasePDFHandle(pdf_handle); - if (!g_sdk_initialized_via_pepper) - ShutdownSDK(); -} - -bool GetPDFPageSizeByIndex(void* pdf_handle, +bool GetPDFPageSizeByIndex(const void* pdf_buffer, + int pdf_buffer_size, int page_number, double* width, double* height) { if (!g_sdk_initialized_via_pepper) { - if (!InitializeSDK()) + if (!chrome_pdf::InitializeSDK()) return false; } - PDFEngineExports* engine_exports = PDFEngineExports::Get(); - bool ret = engine_exports->GetPDFPageSizeByIndex(pdf_handle, page_number, - width, height); + chrome_pdf::PDFEngineExports* engine_exports = + chrome_pdf::PDFEngineExports::Get(); + bool ret = engine_exports->GetPDFPageSizeByIndex(pdf_buffer, pdf_buffer_size, + page_number, width, height); if (!g_sdk_initialized_via_pepper) - ShutdownSDK(); + chrome_pdf::ShutdownSDK(); return ret; } -bool RenderPDFPageToBitmap(void* pdf_handle, +bool RenderPDFPageToBitmap(const void* pdf_buffer, + int pdf_buffer_size, int page_number, void* bitmap_buffer, int bitmap_width, @@ -184,8 +176,8 @@ PDFEngineExports::RenderingSettings settings( dpi, dpi, pp::Rect(bitmap_width, bitmap_height), true, false, true, true, autorotate); - bool ret = engine_exports->RenderPDFPageToBitmap(pdf_handle, page_number, - settings, bitmap_buffer); + bool ret = engine_exports->RenderPDFPageToBitmap( + pdf_buffer, pdf_buffer_size, page_number, settings, bitmap_buffer); if (!g_sdk_initialized_via_pepper) ShutdownSDK();
diff --git a/pdf/pdf.h b/pdf/pdf.h index 2c01124..c785b551 100644 --- a/pdf/pdf.h +++ b/pdf/pdf.h
@@ -36,7 +36,9 @@ const void* PPP_GetInterface(const char* interface_name); #if defined(OS_WIN) -// |pdf_handle| is the handle to the PDF document. +// |pdf_buffer| is the buffer that contains the entire PDF document to be +// rendered. +// |buffer_size| is the size of |pdf_buffer| in bytes. // |page_number| is the 0-based index of the page to be rendered. // |dc| is the device context to render into. // |dpi| and |dpi_y| is the resolution. If the value is -1, the dpi from the DC @@ -61,7 +63,8 @@ // |autorotate| specifies whether the final image should be rotated to match // the output bound. // Returns false if the document or the page number are not valid. -bool RenderPDFPageToDC(void* pdf_handle, +bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, int page_number, HDC dc, int dpi, @@ -81,35 +84,32 @@ void SetPDFUseGDIPrinting(bool enable); #endif // defined(OS_WIN) -// All the out parameters are optional and can be NULL. +// |page_count| and |max_page_width| are optional and can be NULL. // Returns false if the document is not valid. -// Returns true on success. In which case, if |pdf_handle| is not NULL, then -// the handle is guaranteed to be valid and not NULL. The caller takes -// ownership of |pdf_handle| and must call ReleasePDFHandle() on it when done. bool GetPDFDocInfo(const void* pdf_buffer, int buffer_size, int* page_count, - double* max_page_width, - void** pdf_handle); - -// Releases the handle received from GetPDFDocInfo(). -// |pdf_handle| can be NULL. -void ReleasePDFHandle(void* pdf_handle); + double* max_page_width); // Gets the dimensions of a specific page in a document. -// |pdf_handle| is the handle to the PDF document. +// |pdf_buffer| is the buffer that contains the entire PDF document to be +// rendered. +// |pdf_buffer_size| is the size of |pdf_buffer| in bytes. // |page_number| is the page number that the function will get the dimensions // of. // |width| is the output for the width of the page in points. // |height| is the output for the height of the page in points. // Returns false if the document or the page number are not valid. -bool GetPDFPageSizeByIndex(void* pdf_handle, +bool GetPDFPageSizeByIndex(const void* pdf_buffer, + int pdf_buffer_size, int page_number, double* width, double* height); // Renders PDF page into 4-byte per pixel BGRA color bitmap. -// |pdf_handle| is the handle to the PDF document. +// |pdf_buffer| is the buffer that contains the entire PDF document to be +// rendered. +// |pdf_buffer_size| is the size of |pdf_buffer| in bytes. // |page_number| is the 0-based index of the page to be rendered. // |bitmap_buffer| is the output buffer for bitmap. // |bitmap_width| is the width of the output bitmap. @@ -118,7 +118,8 @@ // |autorotate| specifies whether the final image should be rotated to match // the output bound. // Returns false if the document or the page number are not valid. -bool RenderPDFPageToBitmap(void* pdf_handle, +bool RenderPDFPageToBitmap(const void* pdf_buffer, + int pdf_buffer_size, int page_number, void* bitmap_buffer, int bitmap_width,
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 4c7ce63..4bb62b3 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -333,8 +333,9 @@ static PDFEngineExports* Get(); #if defined(OS_WIN) - // See the definitions of the corresponding functions in pdf.h for details. - virtual bool RenderPDFPageToDC(void* pdf_handle, + // See the definition of RenderPDFPageToDC in pdf.cc for details. + virtual bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, int page_number, const RenderingSettings& settings, HDC dc) = 0; @@ -345,7 +346,9 @@ virtual void SetPDFUseGDIPrinting(bool enable) = 0; #endif // defined(OS_WIN) - virtual bool RenderPDFPageToBitmap(void* pdf_handle, + // See the definition of RenderPDFPageToBitmap in pdf.cc for details. + virtual bool RenderPDFPageToBitmap(const void* pdf_buffer, + int pdf_buffer_size, int page_number, const RenderingSettings& settings, void* bitmap_buffer) = 0; @@ -353,12 +356,11 @@ virtual bool GetPDFDocInfo(const void* pdf_buffer, int buffer_size, int* page_count, - double* max_page_width, - void** pdf_handle) = 0; + double* max_page_width) = 0; - virtual void ReleasePDFHandle(void* pdf_handle) = 0; - - virtual bool GetPDFPageSizeByIndex(void* pdf_handle, + // See the definition of GetPDFPageSizeByIndex in pdf.cc for details. + virtual bool GetPDFPageSizeByIndex(const void* pdf_buffer, + int pdf_buffer_size, int page_number, double* width, double* height) = 0;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 0853d79..80f1fd6 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -4007,17 +4007,19 @@ } #if defined(OS_WIN) -bool PDFiumEngineExports::RenderPDFPageToDC(void* pdf_handle, +bool PDFiumEngineExports::RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, int page_number, const RenderingSettings& settings, HDC dc) { - FPDF_DOCUMENT doc = pdf_handle; + FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr); if (!doc) return false; FPDF_PAGE page = FPDF_LoadPage(doc, page_number); - if (!page) + if (!page) { + FPDF_CloseDocument(doc); return false; - + } RenderingSettings new_settings = settings; // calculate the page size if (new_settings.dpi_x == -1) @@ -4071,6 +4073,7 @@ } RestoreDC(dc, save_state); FPDF_ClosePage(page); + FPDF_CloseDocument(doc); return true; } @@ -4086,16 +4089,20 @@ #endif // defined(OS_WIN) bool PDFiumEngineExports::RenderPDFPageToBitmap( - void* pdf_handle, + const void* pdf_buffer, + int pdf_buffer_size, int page_number, const RenderingSettings& settings, void* bitmap_buffer) { - FPDF_DOCUMENT doc = pdf_handle; + FPDF_DOCUMENT doc = + FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr); if (!doc) return false; FPDF_PAGE page = FPDF_LoadPage(doc, page_number); - if (!page) + if (!page) { + FPDF_CloseDocument(doc); return false; + } pp::Rect dest; int rotate = CalculatePosition(page, settings, &dest); @@ -4114,49 +4121,48 @@ FPDF_ANNOT | FPDF_PRINTING | FPDF_NO_CATCH); FPDFBitmap_Destroy(bitmap); FPDF_ClosePage(page); + FPDF_CloseDocument(doc); return true; } bool PDFiumEngineExports::GetPDFDocInfo(const void* pdf_buffer, int buffer_size, int* page_count, - double* max_page_width, - void** pdf_handle) { + double* max_page_width) { FPDF_DOCUMENT doc = FPDF_LoadMemDocument(pdf_buffer, buffer_size, nullptr); if (!doc) return false; - int page_count_local = FPDF_GetPageCount(doc); - if (page_count) + if (page_count) { *page_count = page_count_local; - + } if (max_page_width) { *max_page_width = 0; for (int page_number = 0; page_number < page_count_local; page_number++) { double page_width = 0; double page_height = 0; FPDF_GetPageSizeByIndex(doc, page_number, &page_width, &page_height); - *max_page_width = std::max(*max_page_width, page_width); + if (page_width > *max_page_width) { + *max_page_width = page_width; + } } } - - if (pdf_handle) - *pdf_handle = doc; // Caller takes ownership. - else - FPDF_CloseDocument(pdf_handle); + FPDF_CloseDocument(doc); return true; } -void PDFiumEngineExports::ReleasePDFHandle(void* pdf_handle) { - FPDF_CloseDocument(pdf_handle); -} - -bool PDFiumEngineExports::GetPDFPageSizeByIndex(void* pdf_handle, +bool PDFiumEngineExports::GetPDFPageSizeByIndex(const void* pdf_buffer, + int pdf_buffer_size, int page_number, double* width, double* height) { - FPDF_DOCUMENT doc = pdf_handle; - return doc && FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; + FPDF_DOCUMENT doc = + FPDF_LoadMemDocument(pdf_buffer, pdf_buffer_size, nullptr); + if (!doc) + return false; + bool success = FPDF_GetPageSizeByIndex(doc, page_number, width, height) != 0; + FPDF_CloseDocument(doc); + return success; } } // namespace chrome_pdf
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index 4795b16..0334a602 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -771,7 +771,8 @@ // PDFEngineExports: #if defined(OS_WIN) - bool RenderPDFPageToDC(void* pdf_handle, + bool RenderPDFPageToDC(const void* pdf_buffer, + int buffer_size, int page_number, const RenderingSettings& settings, HDC dc) override; @@ -780,17 +781,17 @@ void SetPDFUseGDIPrinting(bool enable) override; #endif // defined(OS_WIN) - bool RenderPDFPageToBitmap(void* pdf_handle, + bool RenderPDFPageToBitmap(const void* pdf_buffer, + int pdf_buffer_size, int page_number, const RenderingSettings& settings, void* bitmap_buffer) override; bool GetPDFDocInfo(const void* pdf_buffer, int buffer_size, int* page_count, - double* max_page_width, - void** pdf_handle) override; - void ReleasePDFHandle(void* pdf_handle) override; - bool GetPDFPageSizeByIndex(void* pdf_handle, + double* max_page_width) override; + bool GetPDFPageSizeByIndex(const void* pdf_buffer, + int pdf_buffer_size, int page_number, double* width, double* height) override;
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 227f8c1..a31706b 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -4385,6 +4385,24 @@ "args": [ "--deqp-egl-display-type=angle-gl" ], + "name": "angle_deqp_gles31_gl_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Linux" + } + ], + "shards": 4 + }, + "test": "angle_deqp_gles31_tests", + "use_xvfb": false + }, + { + "args": [ + "--deqp-egl-display-type=angle-gl" + ], "name": "angle_deqp_gles3_gl_tests", "swarming": { "can_use_on_swarming_builders": true, @@ -13450,6 +13468,24 @@ }, { "args": [ + "--deqp-egl-display-type=angle-gl" + ], + "name": "angle_deqp_gles31_gl_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "10de:104a", + "os": "Windows-2008ServerR2-SP1" + } + ], + "shards": 4 + }, + "test": "angle_deqp_gles31_tests", + "use_xvfb": false + }, + { + "args": [ "--deqp-egl-display-type=angle-d3d11" ], "name": "angle_deqp_gles3_d3d11_tests",
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 0c109f5..b94763bd 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -35,12 +35,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "ash_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "aura_unittests" }, { @@ -250,15 +244,6 @@ "test": "keyboard_unittests" }, { - "args": [ - "--override-use-gl-with-osmesa-for-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "mash_unittests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -562,12 +547,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "ash_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "aura_unittests" }, { @@ -1022,12 +1001,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "ash_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "aura_unittests" }, { @@ -1243,15 +1216,6 @@ "test": "keyboard_unittests" }, { - "args": [ - "--override-use-gl-with-osmesa-for-tests" - ], - "swarming": { - "can_use_on_swarming_builders": true - }, - "test": "mash_unittests" - }, - { "swarming": { "can_use_on_swarming_builders": true }, @@ -1509,12 +1473,6 @@ "swarming": { "can_use_on_swarming_builders": true }, - "test": "ash_unittests" - }, - { - "swarming": { - "can_use_on_swarming_builders": true - }, "test": "aura_unittests" }, {
diff --git a/testing/buildbot/filters/site-per-process.browser_tests.filter b/testing/buildbot/filters/site-per-process.browser_tests.filter index bcc584f..f0b0ba2 100644 --- a/testing/buildbot/filters/site-per-process.browser_tests.filter +++ b/testing/buildbot/filters/site-per-process.browser_tests.filter
@@ -18,3 +18,6 @@ # crbug.com/669299: Wrong view frame source with --site-per-process -ChromeNavigationBrowserTest.TestViewFrameSource + +# crbug.com/670362: Flaky failure (expected MouseDown not found) +-DevToolsPixelOutputTests.TestLatencyInfoInstrumentation
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 4947dc9..c6d44074 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -103,6 +103,11 @@ "type": "raw", "args": [], }, + "angle_deqp_gles31_tests": { + "label": "//third_party/angle/src/tests:angle_deqp_gles31_tests", + "type": "raw", + "args": [], + }, "angle_end2end_tests": { "label": "//third_party/angle/src/tests:angle_end2end_tests", "type": "raw",
diff --git a/third_party/WebKit/LayoutTests/LeakExpectations b/third_party/WebKit/LayoutTests/LeakExpectations index c4b857c7..365b239 100644 --- a/third_party/WebKit/LayoutTests/LeakExpectations +++ b/third_party/WebKit/LayoutTests/LeakExpectations
@@ -37,6 +37,8 @@ crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/touch-scroll-customization.html [ Leak ] crbug.com/410974 virtual/scroll_customization/fast/scroll-behavior/scroll-customization/scrollstate-distribute-to-scroll-chain-descendant.html [ Leak ] +crbug.com/670324 fast/speech/scripted/speechrecognition-restart-onend.html [ Leak ] + # ----------------------------------------------------------------- # Untriaged but known real leaks. # -----------------------------------------------------------------
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index babcb0e..3ff58b2 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -1627,6 +1627,7 @@ crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/upload-progress-events.html [ Failure Timeout ] crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/workers/upload-onprogress-event.html [ Failure ] crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/upload-onloadend-event-after-abort.html [ Timeout ] +crbug.com/659917 virtual/mojo-loading/http/tests/xmlhttprequest/workers/xmlhttprequest-response-type-blob-sync.html [ Pass Timeout ] crbug.com/669357 virtual/mojo-loading/http/tests/inspector/network/network-fetch.html [ Failure ] crbug.com/669357 virtual/mojo-loading/http/tests/inspector-protocol/network-data-length.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha-expected.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha-expected.html new file mode 100644 index 0000000..f043213 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha-expected.html
@@ -0,0 +1,40 @@ +<html> +<body> +<canvas id="canvas" width="600" height="100" ></canvas> +<script> +var canvas = document.createElement("canvas"); +canvas.width = canvas.height = 100; +var context = canvas.getContext("2d"); +context.fillStyle = 'green'; +context.fillRect(0, 0, 100, 100); +var canvas2 = document.createElement("canvas"); +var context2 = canvas2.getContext("2d"); +var drawCanvas = document.getElementById("canvas"); +var drawCtx = drawCanvas.getContext("2d"); + +context2.globalAlpha = 0.0; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 0, 0, 100, 100); + +context2.globalAlpha = 0.2; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 100, 0, 100, 100); + +context2.globalAlpha = 0.4; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 200, 0, 100, 100); + +context2.globalAlpha = 0.6; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 300, 0, 100, 100); + +context2.globalAlpha = 0.8; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 400, 0, 100, 100); + +context2.globalAlpha = 1.0; +context2.drawImage(canvas, 0, 0); +drawCtx.drawImage(canvas2, 0, 0, 100, 100, 500, 0, 100, 100); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha.html b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha.html new file mode 100644 index 0000000..982e1d23 --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/canvas/OffscreenCanvas-2d-globalAlpha.html
@@ -0,0 +1,40 @@ +<html> +<body> +<canvas id="canvas" width="600" height="100" ></canvas> +<script> +var canvas = document.getElementById("canvas"); +var context = canvas.getContext("2d"); + +var offscreenCanvas1 = new OffscreenCanvas(100, 100); +var ctx1 = offscreenCanvas1.getContext('2d'); +ctx1.fillStyle = 'green'; +ctx1.fillRect(0, 0, 100, 100); +var offscreenCanvas2 = new OffscreenCanvas(100, 100); +var ctx2 = offscreenCanvas2.getContext('2d'); + +ctx2.globalAlpha = 0.0; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 0, 0, 100, 100); + +ctx2.globalAlpha = 0.2; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 100, 0, 100, 100); + +ctx2.globalAlpha = 0.4; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 200, 0, 100, 100); + +ctx2.globalAlpha = 0.6; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 300, 0, 100, 100); + +ctx2.globalAlpha = 0.8; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 400, 0, 100, 100); + +ctx2.globalAlpha = 1.0; +ctx2.drawImage(offscreenCanvas1, 0, 0); +context.drawImage(offscreenCanvas2, 0, 0, 100, 100, 500, 0, 100, 100); +</script> +</body> +</html>
diff --git a/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-clone.html b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-clone.html new file mode 100644 index 0000000..16ed9c0c --- /dev/null +++ b/third_party/WebKit/LayoutTests/fast/mediastream/MediaStreamTrack-clone.html
@@ -0,0 +1,39 @@ +<!DOCTYPE HTML> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<canvas id="canvas"/> +<script> + +createTrack = function() { + ac = new AudioContext(); + var osc = ac.createOscillator(); + var dest = ac.createMediaStreamDestination(); + osc.connect(dest); + return dest.stream.getAudioTracks()[0]; +} + +test(t => { + track = createTrack(); + var original_id = track.id; + track_clone = track.clone(); + assert_not_equals(track.id, track_clone.id); +}, "Cloned MediaStreamTracks have new IDs"); + +test(t => { + track = createTrack(); + assert_true(track.enabled); + track.enabled = false; + assert_false(track.enabled); + + track_clone = track.clone(); + assert_false(track_clone.enabled, + "Clones of disabled tracks should still be disabled."); + track_clone.enabled = true; + assert_not_equals(track.enabled, track_clone.enabled, + "Tracks enabled status should not be linked."); +}, "Clones of disabled MediaStreamTracks are still disabled."); + +// TODO(pbos): Add tests that make sure muted and stopped properties are +// carried over. Part of crbug:669212. + +</script>
diff --git a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 419d0ea..087e8a8 100644 --- a/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -486,6 +486,7 @@ interface OffscreenCanvasRenderingContext2D getter canvas getter fillStyle + getter globalAlpha getter globalCompositeOperation getter imageSmoothingEnabled getter imageSmoothingQuality @@ -535,6 +536,7 @@ method transform method translate setter fillStyle + setter globalAlpha setter globalCompositeOperation setter imageSmoothingEnabled setter imageSmoothingQuality
diff --git a/third_party/WebKit/LayoutTests/platform/linux/http/tests/preload/dynamic_remove_preload_href-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/http/tests/preload/dynamic_remove_preload_href-expected.txt deleted file mode 100644 index effbabc..0000000 --- a/third_party/WebKit/LayoutTests/platform/linux/http/tests/preload/dynamic_remove_preload_href-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -CONSOLE WARNING: line 14: <link rel=preload> has an invalid `href` value -This is a testharness.js-based test. -FAIL Makes sure that dynamically removed preloaded resource stop downloading assert_equals: expected 3 but got 4 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png index b4290cd..42920c6 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.png Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt index c92da46..22d1a362 100644 --- a/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt +++ b/third_party/WebKit/LayoutTests/platform/win/fast/forms/search/search-rtl-expected.txt
@@ -37,19 +37,19 @@ text run at (0,0) width 37: "PASS" layer at (23,45) size 157x16 LayoutBlockFlow {DIV} at (0,0) size 157x16 - LayoutText {#text} at (14,0) size 143x16 - text run at (14,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" - text run at (37,0) width 21: "she" - text run at (58,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " - text run at (104,0) width 14: "he" + LayoutText {#text} at (31,0) size 126x16 + text run at (31,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" + text run at (54,0) width 9: "B" + text run at (63,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " + text run at (109,0) width 9: "A" text run at (118,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} " layer at (23,67) size 227x16 LayoutBlockFlow {DIV} at (0,0) size 227x16 - LayoutText {#text} at (84,0) size 143x16 - text run at (84,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" - text run at (107,0) width 21: "she" - text run at (128,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " - text run at (174,0) width 14: "he" + LayoutText {#text} at (101,0) size 126x16 + text run at (101,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" + text run at (124,0) width 9: "B" + text run at (133,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " + text run at (179,0) width 9: "A" text run at (188,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} " layer at (23,89) size 157x16 LayoutBlockFlow {DIV} at (0,0) size 157x16
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.png b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.png deleted file mode 100644 index 42920c6..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.txt deleted file mode 100644 index 22d1a362..0000000 --- a/third_party/WebKit/LayoutTests/platform/win7/fast/forms/search/search-rtl-expected.txt +++ /dev/null
@@ -1,62 +0,0 @@ -layer at (0,0) size 800x600 - LayoutView at (0,0) size 800x600 -layer at (0,0) size 800x600 - LayoutBlockFlow {HTML} at (0,0) size 800x600 - LayoutBlockFlow {BODY} at (8,8) size 784x576 - LayoutBlockFlow {P} at (0,0) size 784x18 - LayoutText {#text} at (0,0) size 54x17 - text run at (0,0) width 54: "Test for " - LayoutInline {I} at (0,0) size 703x17 - LayoutInline {A} at (0,0) size 304x17 [color=#0000EE] - LayoutText {#text} at (53,0) size 304x17 - text run at (53,0) width 304: "http://bugs.webkit.org/show_bug.cgi?id=11916" - LayoutText {#text} at (356,0) size 400x17 - text run at (356,0) width 5: " " - text run at (360,0) width 396: "REGRESSION (SearchField): RTL search fields are mixed up" - LayoutText {#text} at (755,0) size 5x17 - text run at (755,0) width 5: "." - LayoutBlockFlow {P} at (0,34) size 784x66 - LayoutTextControl {INPUT} at (0,0) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutFlexibleBox {DIV} at (3,3) size 169x16 - LayoutBlockFlow {DIV} at (12,0) size 157x16 - LayoutText {#text} at (175,2) size 4x17 - text run at (175,2) width 4: " " - LayoutBR {BR} at (0,0) size 0x0 - LayoutTextControl {INPUT} at (0,22) size 245x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutFlexibleBox {DIV} at (3,3) size 239x16 - LayoutBlockFlow {DIV} at (12,0) size 227x16 - LayoutText {#text} at (245,24) size 4x17 - text run at (245,24) width 4: " " - LayoutBR {BR} at (0,0) size 0x0 - LayoutTextControl {INPUT} at (0,44) size 175x22 [bgcolor=#FFFFFF] [border: (2px inset #EEEEEE)] - LayoutFlexibleBox {DIV} at (3,3) size 169x16 - LayoutBlockFlow {DIV} at (12,0) size 157x16 - LayoutText {#text} at (0,0) size 0x0 - LayoutBlockFlow {P} at (0,116) size 784x18 - LayoutText {#text} at (0,0) size 37x17 - text run at (0,0) width 37: "PASS" -layer at (23,45) size 157x16 - LayoutBlockFlow {DIV} at (0,0) size 157x16 - LayoutText {#text} at (31,0) size 126x16 - text run at (31,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" - text run at (54,0) width 9: "B" - text run at (63,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " - text run at (109,0) width 9: "A" - text run at (118,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} " -layer at (23,67) size 227x16 - LayoutBlockFlow {DIV} at (0,0) size 227x16 - LayoutText {#text} at (101,0) size 126x16 - text run at (101,0) width 23 RTL: " \x{5D5}\x{5D6}\x{5D4}\x{5D5}" - text run at (124,0) width 9: "B" - text run at (133,0) width 46 RTL: " \x{5D5}\x{5D4}\x{5D9}\x{5D0} \x{5D6}\x{5D4} " - text run at (179,0) width 9: "A" - text run at (188,0) width 39 RTL: "\x{5D4}\x{5D5}\x{5D0} \x{5D6}\x{5D4} " -layer at (23,89) size 157x16 - LayoutBlockFlow {DIV} at (0,0) size 157x16 -layer at (11,49) size 9x9 transparent - LayoutBlockFlow {DIV} at (0,3.50) size 9x9 -layer at (11,71) size 9x9 transparent - LayoutBlockFlow {DIV} at (0,3.50) size 9x9 -layer at (11,93) size 9x9 transparent - LayoutBlockFlow {DIV} at (0,3.50) size 9x9 -caret: position 0 of child 0 {DIV} of child 0 {DIV} of child 0 {DIV} of {#document-fragment} of child 9 {INPUT} of child 3 {P} of body
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 9812097..f7e4f6a 100644 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/service-worker-navigation-preload/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -493,6 +493,7 @@ interface OffscreenCanvasRenderingContext2D getter canvas getter fillStyle + getter globalAlpha getter globalCompositeOperation getter imageSmoothingEnabled getter imageSmoothingQuality @@ -542,6 +543,7 @@ method transform method translate setter fillStyle + setter globalAlpha setter globalCompositeOperation setter imageSmoothingEnabled setter imageSmoothingQuality
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index a6730407..f7914d1 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -503,6 +503,7 @@ [Worker] attribute @@toStringTag [Worker] getter canvas [Worker] getter fillStyle +[Worker] getter globalAlpha [Worker] getter globalCompositeOperation [Worker] getter imageSmoothingEnabled [Worker] getter imageSmoothingQuality @@ -552,6 +553,7 @@ [Worker] method transform [Worker] method translate [Worker] setter fillStyle +[Worker] setter globalAlpha [Worker] setter globalCompositeOperation [Worker] setter imageSmoothingEnabled [Worker] setter imageSmoothingQuality
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt index 4f1230b..085f5e3 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-expected.txt
@@ -4367,6 +4367,7 @@ getter canvas getter fillStyle getter filter + getter globalAlpha getter globalCompositeOperation getter imageSmoothingEnabled getter imageSmoothingQuality @@ -4417,6 +4418,7 @@ method translate setter fillStyle setter filter + setter globalAlpha setter globalCompositeOperation setter imageSmoothingEnabled setter imageSmoothingQuality
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt index a5cc7547..54c6ae4 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -498,6 +498,7 @@ [Worker] attribute @@toStringTag [Worker] getter canvas [Worker] getter fillStyle +[Worker] getter globalAlpha [Worker] getter globalCompositeOperation [Worker] getter imageSmoothingEnabled [Worker] getter imageSmoothingQuality @@ -547,6 +548,7 @@ [Worker] method transform [Worker] method translate [Worker] setter fillStyle +[Worker] setter globalAlpha [Worker] setter globalCompositeOperation [Worker] setter imageSmoothingEnabled [Worker] setter imageSmoothingQuality
diff --git a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp index ede7f72..920d5b80 100644 --- a/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp +++ b/third_party/WebKit/Source/core/html/parser/CSSPreloadScanner.cpp
@@ -257,7 +257,7 @@ : ScanOnly), m_preloader(preloader), m_resource(toCSSStyleSheetResource(resource)) { - m_resource->addClient(this); + m_resource->addClient(this, Resource::DontMarkAsReferenced); } CSSPreloaderResourceClient::~CSSPreloaderResourceClient() {}
diff --git a/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp b/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp index ff92e2b..428b8935 100644 --- a/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp +++ b/third_party/WebKit/Source/core/html/parser/CSSPreloadScannerTest.cpp
@@ -58,6 +58,7 @@ const char* data = "@import url('http://127.0.0.1/preload.css');"; resource->appendData(data, strlen(data)); + EXPECT_EQ(Resource::PreloadNotReferenced, resource->getPreloadResult()); EXPECT_EQ(1u, resourceClient->m_preloads.size()); EXPECT_EQ("http://127.0.0.1/preload.css", resourceClient->m_preloads.front()->resourceURL());
diff --git a/third_party/WebKit/Source/modules/mediacapturefromelement/CanvasCaptureMediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediacapturefromelement/CanvasCaptureMediaStreamTrack.cpp index 4c8d7d9..6a8fdaa8 100644 --- a/third_party/WebKit/Source/modules/mediacapturefromelement/CanvasCaptureMediaStreamTrack.cpp +++ b/third_party/WebKit/Source/modules/mediacapturefromelement/CanvasCaptureMediaStreamTrack.cpp
@@ -40,8 +40,7 @@ CanvasCaptureMediaStreamTrack* CanvasCaptureMediaStreamTrack::clone( ExecutionContext* context) { - MediaStreamComponent* clonedComponent = - MediaStreamComponent::create(component()->source()); + MediaStreamComponent* clonedComponent = component()->clone(); CanvasCaptureMediaStreamTrack* clonedTrack = new CanvasCaptureMediaStreamTrack(*this, clonedComponent); MediaStreamCenter::instance().didCreateMediaStreamTrack(clonedComponent);
diff --git a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp index 0e4d5d1..f27b7db 100644 --- a/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp +++ b/third_party/WebKit/Source/modules/mediastream/MediaStreamTrack.cpp
@@ -139,8 +139,9 @@ } MediaStreamTrack* MediaStreamTrack::clone(ExecutionContext* context) { - MediaStreamComponent* clonedComponent = - MediaStreamComponent::create(component()->source()); + // TODO(pbos): Make sure m_readyState and m_stopped carries over on cloned + // tracks. + MediaStreamComponent* clonedComponent = component()->clone(); MediaStreamTrack* clonedTrack = MediaStreamTrack::create(context, clonedComponent); MediaStreamCenter::instance().didCreateMediaStreamTrack(clonedComponent);
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp index 0042689..64819e62 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.cpp
@@ -14,30 +14,11 @@ #include "platform/network/ResourceRequest.h" #include "platform/weborigin/KURL.h" #include "public/platform/WebURLRequest.h" -#include "public/platform/modules/notifications/WebNotificationConstants.h" -#include "skia/ext/image_operations.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "wtf/CurrentTime.h" #include "wtf/Threading.h" #include <memory> -#define NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, type_name, value, max) \ - case NotificationImageLoader::Type::type_name: { \ - DEFINE_THREAD_SAFE_STATIC_LOCAL( \ - CustomCountHistogram, metric##type_name##Histogram, \ - new CustomCountHistogram("Notifications." #metric "." #type_name, \ - 1 /* min */, max, 50 /* buckets */)); \ - metric##type_name##Histogram.count(value); \ - break; \ - } - -#define NOTIFICATION_HISTOGRAM_COUNTS(metric, type, value, max) \ - switch (type) { \ - NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Image, value, max) \ - NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Icon, value, max) \ - NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, Badge, value, max) \ - NOTIFICATION_PER_TYPE_HISTOGRAM_COUNTS(metric, ActionIcon, value, max) \ - } - namespace { // 99.9% of all images were fetched successfully in 90 seconds. @@ -47,53 +28,11 @@ namespace blink { -NotificationImageLoader::NotificationImageLoader(Type type) - : m_type(type), m_stopped(false), m_startTime(0.0) {} +NotificationImageLoader::NotificationImageLoader() + : m_stopped(false), m_startTime(0.0) {} NotificationImageLoader::~NotificationImageLoader() {} -// static -SkBitmap NotificationImageLoader::scaleDownIfNeeded(const SkBitmap& image, - Type type) { - int maxWidthPx = 0, maxHeightPx = 0; - switch (type) { - case Type::Image: - maxWidthPx = kWebNotificationMaxImageWidthPx; - maxHeightPx = kWebNotificationMaxImageHeightPx; - break; - case Type::Icon: - maxWidthPx = kWebNotificationMaxIconSizePx; - maxHeightPx = kWebNotificationMaxIconSizePx; - break; - case Type::Badge: - maxWidthPx = kWebNotificationMaxBadgeSizePx; - maxHeightPx = kWebNotificationMaxBadgeSizePx; - break; - case Type::ActionIcon: - maxWidthPx = kWebNotificationMaxActionIconSizePx; - maxHeightPx = kWebNotificationMaxActionIconSizePx; - break; - } - DCHECK_GT(maxWidthPx, 0); - DCHECK_GT(maxHeightPx, 0); - // TODO(peter): Explore doing the scaling on a background thread. - if (image.width() > maxWidthPx || image.height() > maxHeightPx) { - double scale = std::min(static_cast<double>(maxWidthPx) / image.width(), - static_cast<double>(maxHeightPx) / image.height()); - double startTime = monotonicallyIncreasingTimeMS(); - // TODO(peter): Try using RESIZE_BETTER for large images. - SkBitmap scaledImage = - skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST, - std::lround(scale * image.width()), - std::lround(scale * image.height())); - NOTIFICATION_HISTOGRAM_COUNTS(LoadScaleDownTime, type, - monotonicallyIncreasingTimeMS() - startTime, - 1000 * 10 /* 10 seconds max */); - return scaledImage; - } - return image; -} - void NotificationImageLoader::start( ExecutionContext* executionContext, const KURL& url, @@ -150,13 +89,19 @@ if (m_stopped) return; - NOTIFICATION_HISTOGRAM_COUNTS(LoadFinishTime, m_type, - monotonicallyIncreasingTimeMS() - m_startTime, - 1000 * 60 * 60 /* 1 hour max */); + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, finishedTimeHistogram, + new CustomCountHistogram("Notifications.Icon.LoadFinishTime", 1, + 1000 * 60 * 60 /* 1 hour max */, + 50 /* buckets */)); + finishedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); if (m_data) { - NOTIFICATION_HISTOGRAM_COUNTS(LoadFileSize, m_type, m_data->size(), - 10000000 /* ~10mb max */); + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, fileSizeHistogram, + new CustomCountHistogram("Notifications.Icon.FileSize", 1, + 10000000 /* ~10mb max */, 50 /* buckets */)); + fileSizeHistogram.count(m_data->size()); std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( m_data, true /* dataComplete */, ImageDecoder::AlphaPremultiplied, @@ -175,9 +120,12 @@ } void NotificationImageLoader::didFail(const ResourceError& error) { - NOTIFICATION_HISTOGRAM_COUNTS(LoadFailTime, m_type, - monotonicallyIncreasingTimeMS() - m_startTime, - 1000 * 60 * 60 /* 1 hour max */); + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, failedTimeHistogram, + new CustomCountHistogram("Notifications.Icon.LoadFailTime", 1, + 1000 * 60 * 60 /* 1 hour max */, + 50 /* buckets */)); + failedTimeHistogram.count(monotonicallyIncreasingTimeMS() - m_startTime); runCallbackWithEmptyBitmap(); }
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h index 46e6be4..ea0cc3d 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoader.h
@@ -10,11 +10,12 @@ #include "modules/ModulesExport.h" #include "platform/SharedBuffer.h" #include "platform/heap/Handle.h" -#include "third_party/skia/include/core/SkBitmap.h" #include "wtf/Functional.h" #include "wtf/RefPtr.h" #include <memory> +class SkBitmap; + namespace blink { class ExecutionContext; @@ -27,20 +28,13 @@ : public GarbageCollectedFinalized<NotificationImageLoader>, public ThreadableLoaderClient { public: - // Type names are used in UMAs, so do not rename. - enum class Type { Image, Icon, Badge, ActionIcon }; - // The bitmap may be empty if the request failed or the image data could not // be decoded. using ImageCallback = Function<void(const SkBitmap&)>; - explicit NotificationImageLoader(Type); + NotificationImageLoader(); ~NotificationImageLoader() override; - // Scales down |image| according to its type and returns result. If it is - // already small enough, |image| is returned unchanged. - static SkBitmap scaleDownIfNeeded(const SkBitmap& image, Type); - // Asynchronously downloads an image from the given url, decodes the loaded // data, and passes the bitmap to the callback. Times out if the load takes // too long and ImageCallback is invoked with an empty bitmap. @@ -62,7 +56,6 @@ private: void runCallbackWithEmptyBitmap(); - Type m_type; bool m_stopped; double m_startTime; RefPtr<SharedBuffer> m_data;
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp index 4072119..bcb59f4 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationImageLoaderTest.cpp
@@ -7,7 +7,6 @@ #include "core/dom/ExecutionContext.h" #include "core/fetch/MemoryCache.h" #include "core/testing/DummyPageHolder.h" -#include "platform/testing/HistogramTester.h" #include "platform/testing/TestingPlatformSupport.h" #include "platform/testing/URLTestHelpers.h" #include "public/platform/Platform.h" @@ -36,9 +35,7 @@ public: NotificationImageLoaderTest() : m_page(DummyPageHolder::create()), - // Use an arbitrary type, since it only affects which UMA bucket we use. - m_loader( - new NotificationImageLoader(NotificationImageLoader::Type::Icon)) {} + m_loader(new NotificationImageLoader()) {} ~NotificationImageLoaderTest() override { m_loader->stop(); @@ -73,9 +70,6 @@ ExecutionContext* context() const { return &m_page->document(); } LoadState loaded() const { return m_loaded; } - protected: - HistogramTester m_histogramTester; - private: std::unique_ptr<DummyPageHolder> m_page; Persistent<NotificationImageLoader> m_loader; @@ -85,18 +79,8 @@ TEST_F(NotificationImageLoaderTest, SuccessTest) { KURL url = registerMockedURL(kIcon500x500); loadImage(url); - m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0); - m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0); - m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0); Platform::current()->getURLLoaderMockFactory()->serveAsynchronousRequests(); EXPECT_EQ(LoadState::kLoadSuccessful, loaded()); - m_histogramTester.expectUniqueSample("Notifications.LoadFileSize.Icon", 7439, - 1); - m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0); - // Should log a non-zero finish time. - m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 1); - m_histogramTester.expectBucketCount("Notifications.LoadFinishTime.Icon", 0, - 0); } TEST_F(NotificationImageLoaderTest, TimeoutTest) { @@ -110,20 +94,12 @@ // result in a timeout. testingPlatform.runForPeriodSeconds(kImageFetchTimeoutInMs / 1000 - 1); EXPECT_EQ(LoadState::kNotLoaded, loaded()); - m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0); - m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0); - m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 0); // Now advance time until a timeout should be expected. testingPlatform.runForPeriodSeconds(2); // If the loader times out, it calls the callback and returns an empty bitmap. EXPECT_EQ(LoadState::kLoadFailed, loaded()); - m_histogramTester.expectTotalCount("Notifications.LoadFinishTime.Icon", 0); - m_histogramTester.expectTotalCount("Notifications.LoadFileSize.Icon", 0); - // Should log a non-zero failure time. - m_histogramTester.expectTotalCount("Notifications.LoadFailTime.Icon", 1); - m_histogramTester.expectBucketCount("Notifications.LoadFailTime.Icon", 0, 0); } } // namspace
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp index fb717c2..7c4a01cd 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp +++ b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.cpp
@@ -6,14 +6,47 @@ #include "platform/Histogram.h" #include "platform/weborigin/KURL.h" +#include "public/platform/modules/notifications/WebNotificationConstants.h" #include "public/platform/modules/notifications/WebNotificationData.h" #include "public/platform/modules/notifications/WebNotificationResources.h" +#include "skia/ext/image_operations.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "wtf/CurrentTime.h" #include "wtf/Threading.h" #include <cmath> namespace blink { +namespace { + +// Scales down |image| to fit within |maxWidthPx|x|maxHeightPx| if it is larger +// and returns the result. Otherwise does nothing and returns |image| unchanged. +// TODO(mvanouwerkerk): Explore doing the scaling on a background thread. +SkBitmap scaleDownIfNeeded(const SkBitmap& image, + int maxWidthPx, + int maxHeightPx) { + if (image.width() > maxWidthPx || image.height() > maxHeightPx) { + double scale = std::min(static_cast<double>(maxWidthPx) / image.width(), + static_cast<double>(maxHeightPx) / image.height()); + DEFINE_THREAD_SAFE_STATIC_LOCAL( + CustomCountHistogram, scaleTimeHistogram, + new CustomCountHistogram("Notifications.Icon.ScaleDownTime", 1, + 1000 * 10 /* 10 seconds max */, + 50 /* buckets */)); + double startTime = monotonicallyIncreasingTimeMS(); + // TODO(peter): Try using RESIZE_BETTER for large images. + SkBitmap scaledImage = + skia::ImageOperations::Resize(image, skia::ImageOperations::RESIZE_BEST, + std::lround(scale * image.width()), + std::lround(scale * image.height())); + scaleTimeHistogram.count(monotonicallyIncreasingTimeMS() - startTime); + return scaledImage; + } + return image; +} + +} // namespace + NotificationResourcesLoader::NotificationResourcesLoader( std::unique_ptr<CompletionCallback> completionCallback) : m_started(false), @@ -36,23 +69,19 @@ // TODO(johnme): ensure image is not loaded when it will not be used. // TODO(mvanouwerkerk): ensure no badge is loaded when it will not be used. - loadImage(executionContext, NotificationImageLoader::Type::Image, - notificationData.image, + loadImage(executionContext, notificationData.image, WTF::bind(&NotificationResourcesLoader::didLoadImage, wrapWeakPersistent(this))); - loadImage(executionContext, NotificationImageLoader::Type::Icon, - notificationData.icon, + loadImage(executionContext, notificationData.icon, WTF::bind(&NotificationResourcesLoader::didLoadIcon, wrapWeakPersistent(this))); - loadImage(executionContext, NotificationImageLoader::Type::Badge, - notificationData.badge, + loadImage(executionContext, notificationData.badge, WTF::bind(&NotificationResourcesLoader::didLoadBadge, wrapWeakPersistent(this))); m_actionIcons.resize(numActions); for (size_t i = 0; i < numActions; i++) - loadImage(executionContext, NotificationImageLoader::Type::ActionIcon, - notificationData.actions[i].icon, + loadImage(executionContext, notificationData.actions[i].icon, WTF::bind(&NotificationResourcesLoader::didLoadActionIcon, wrapWeakPersistent(this), i)); } @@ -79,7 +108,6 @@ void NotificationResourcesLoader::loadImage( ExecutionContext* executionContext, - NotificationImageLoader::Type type, const KURL& url, std::unique_ptr<NotificationImageLoader::ImageCallback> imageCallback) { if (url.isNull() || url.isEmpty() || !url.isValid()) { @@ -87,26 +115,26 @@ return; } - NotificationImageLoader* imageLoader = new NotificationImageLoader(type); + NotificationImageLoader* imageLoader = new NotificationImageLoader(); m_imageLoaders.append(imageLoader); imageLoader->start(executionContext, url, std::move(imageCallback)); } void NotificationResourcesLoader::didLoadImage(const SkBitmap& image) { - m_image = NotificationImageLoader::scaleDownIfNeeded( - image, NotificationImageLoader::Type::Image); + m_image = scaleDownIfNeeded(image, kWebNotificationMaxImageWidthPx, + kWebNotificationMaxImageHeightPx); didFinishRequest(); } void NotificationResourcesLoader::didLoadIcon(const SkBitmap& image) { - m_icon = NotificationImageLoader::scaleDownIfNeeded( - image, NotificationImageLoader::Type::Icon); + m_icon = scaleDownIfNeeded(image, kWebNotificationMaxIconSizePx, + kWebNotificationMaxIconSizePx); didFinishRequest(); } void NotificationResourcesLoader::didLoadBadge(const SkBitmap& image) { - m_badge = NotificationImageLoader::scaleDownIfNeeded( - image, NotificationImageLoader::Type::Badge); + m_badge = scaleDownIfNeeded(image, kWebNotificationMaxBadgeSizePx, + kWebNotificationMaxBadgeSizePx); didFinishRequest(); } @@ -114,8 +142,9 @@ const SkBitmap& image) { DCHECK_LT(actionIndex, m_actionIcons.size()); - m_actionIcons[actionIndex] = NotificationImageLoader::scaleDownIfNeeded( - image, NotificationImageLoader::Type::ActionIcon); + m_actionIcons[actionIndex] = + scaleDownIfNeeded(image, kWebNotificationMaxActionIconSizePx, + kWebNotificationMaxActionIconSizePx); didFinishRequest(); }
diff --git a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h index 4ab17e9..8f11042 100644 --- a/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h +++ b/third_party/WebKit/Source/modules/notifications/NotificationResourcesLoader.h
@@ -56,7 +56,6 @@ private: void loadImage(ExecutionContext*, - NotificationImageLoader::Type, const KURL&, std::unique_ptr<NotificationImageLoader::ImageCallback>); void didLoadImage(const SkBitmap& image);
diff --git a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl index e088931..02c13f4 100644 --- a/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl +++ b/third_party/WebKit/Source/modules/offscreencanvas2d/OffscreenCanvasRenderingContext2D.idl
@@ -63,6 +63,7 @@ void resetTransform(); // compositing + attribute unrestricted double globalAlpha; // (default 1.0) attribute DOMString globalCompositeOperation; // (default source-over) // image smoothing
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp index 40f4631..0bc3ea179 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp
@@ -227,7 +227,40 @@ if (m_frameBufferCache.size() <= 1) return 0; - return clearCacheExceptTwoFrames(clearExceptFrame, kNotFound); + // We expect that after this call, we'll be asked to decode frames after this + // one. So we want to avoid clearing frames such that those requests would + // force re-decoding from the beginning of the image. There are two cases in + // which preserving |clearCacheExcept| frame is not enough to avoid that: + // + // 1. |clearExceptFrame| is not yet sufficiently decoded to decode subsequent + // frames. We need the previous frame to sufficiently decode this frame. + // 2. The disposal method of |clearExceptFrame| is DisposeOverwritePrevious. + // In that case, we need to keep the required previous frame in the cache + // to prevent re-decoding that frame when |clearExceptFrame| is disposed. + // + // If either 1 or 2 is true, store the required previous frame in + // |clearExceptFrame2| so it won't be cleared. + size_t clearExceptFrame2 = kNotFound; + if (clearExceptFrame < m_frameBufferCache.size()) { + const ImageFrame& frame = m_frameBufferCache[clearExceptFrame]; + if (!frameStatusSufficientForSuccessors(clearExceptFrame) || + frame.getDisposalMethod() == ImageFrame::DisposeOverwritePrevious) + clearExceptFrame2 = frame.requiredPreviousFrameIndex(); + } + + // Now |clearExceptFrame2| indicates the frame that |clearExceptFrame| + // depends on, as described above. But if decoding is skipping forward past + // intermediate frames, this frame may be insufficiently decoded. So we need + // to keep traversing back through the required previous frames until we find + // the nearest ancestor that is sufficiently decoded. Preserving that will + // minimize the amount of future decoding needed. + while (clearExceptFrame2 < m_frameBufferCache.size() && + !frameStatusSufficientForSuccessors(clearExceptFrame2)) { + clearExceptFrame2 = + m_frameBufferCache[clearExceptFrame2].requiredPreviousFrameIndex(); + } + + return clearCacheExceptTwoFrames(clearExceptFrame, clearExceptFrame2); } size_t ImageDecoder::clearCacheExceptTwoFrames(size_t clearExceptFrame1,
diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h index 04a5ccb..9124bb8 100644 --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.h
@@ -267,10 +267,21 @@ bool failed() const { return m_failed; } - // Clears decoded pixel data from all frames except the provided frame. + // Clears decoded pixel data from all frames except the provided frame. If + // subsequent frames depend on this frame's required previous frame, then that + // frame is also kept in cache to prevent re-decoding from the beginning. // Callers may pass WTF::kNotFound to clear all frames. // Note: If |m_frameBufferCache| contains only one frame, it won't be cleared. // Returns the number of bytes of frame data actually cleared. + // + // This is a virtual method because MockImageDecoder needs to override it in + // order to run the test ImageFrameGeneratorTest::clearMultiFrameDecode. + // + // @TODO Let MockImageDecoder override ImageFrame::clearFrameBuffer instead, + // so this method can be made non-virtual. It is used in the test + // ImageFrameGeneratorTest::clearMultiFrameDecode. The test needs to + // be modified since two frames may be kept in cache, instead of + // always just one, with this clearCacheExceptFrame implementation. virtual size_t clearCacheExceptFrame(size_t); // If the image has a cursor hot-spot, stores it in the argument @@ -379,6 +390,26 @@ // future decodes to purge old frames as it goes. void updateAggressivePurging(size_t index); + // The method is only relevant for multi-frame images. + // + // This method indicates whether the provided frame has enough data to decode + // successive frames that depend on it. It is used by clearCacheExceptFrame + // to determine which frame to keep in cache when the indicated frame is not + // yet sufficiently decoded. + // + // The default condition is that the frame status needs to be FramePartial or + // FrameComplete, since the data of previous frames is copied in + // initFrameBuffer() before setting the status to FramePartial. For WebP, + // however, the status needs to be FrameComplete since the complete buffer is + // used to do alpha blending in WEBPImageDecoder::applyPostProcessing(). + // + // Before calling this, verify that frame |index| exists by checking that + // |index| is smaller than |m_frameBufferCache|.size(). + virtual bool frameStatusSufficientForSuccessors(size_t index) { + DCHECK(index < m_frameBufferCache.size()); + return m_frameBufferCache[index].getStatus() != ImageFrame::FrameEmpty; + } + private: enum class SniffResult { JPEG, PNG, GIF, WEBP, ICO, BMP, Invalid };
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp index b09870a..2693402 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -233,42 +233,6 @@ return true; } -size_t GIFImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) { - // We expect that after this call, we'll be asked to decode frames after - // this one. So we want to avoid clearing frames such that those requests - // would force re-decoding from the beginning of the image. - // - // When |clearExceptFrame| is e.g. DisposeKeep, simply not clearing that - // frame is sufficient, as the next frame will be based on it, and in - // general future frames can't be based on anything previous. - // - // However, if this frame is DisposeOverwritePrevious, then subsequent - // frames will depend on this frame's required previous frame. In this - // case, we need to preserve both this frame and that one. - size_t clearExceptFrame2 = kNotFound; - if (clearExceptFrame < m_frameBufferCache.size()) { - const ImageFrame& frame = m_frameBufferCache[clearExceptFrame]; - if ((frame.getStatus() != ImageFrame::FrameEmpty) && - (frame.getDisposalMethod() == ImageFrame::DisposeOverwritePrevious)) { - clearExceptFrame2 = clearExceptFrame; - clearExceptFrame = frame.requiredPreviousFrameIndex(); - } - } - - // Now |clearExceptFrame| indicates the frame that future frames will - // depend on. But if decoding is skipping forward past intermediate frames, - // this frame may be FrameEmpty. So we need to keep traversing back through - // the required previous frames until we find the nearest non-empty - // ancestor. Preserving that will minimize the amount of future decoding - // needed. - while ((clearExceptFrame < m_frameBufferCache.size()) && - (m_frameBufferCache[clearExceptFrame].getStatus() == - ImageFrame::FrameEmpty)) - clearExceptFrame = - m_frameBufferCache[clearExceptFrame].requiredPreviousFrameIndex(); - return clearCacheExceptTwoFrames(clearExceptFrame, clearExceptFrame2); -} - void GIFImageDecoder::clearFrameBuffer(size_t frameIndex) { if (m_reader && m_frameBufferCache[frameIndex].getStatus() == ImageFrame::FramePartial) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h index b4b5c35..0f68eb0 100644 --- a/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/gif/GIFImageDecoder.h
@@ -55,7 +55,6 @@ int repetitionCount() const override; bool frameIsCompleteAtIndex(size_t) const override; float frameDurationAtIndex(size_t) const override; - size_t clearCacheExceptFrame(size_t) override; // CAUTION: setFailed() deletes |m_reader|. Be careful to avoid // accessing deleted memory, especially when calling this from inside // GIFImageReader!
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp index a3fa61c..bbfec45 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp
@@ -269,35 +269,6 @@ ImageFrame::BlendAtopPreviousFrame; } -size_t WEBPImageDecoder::clearCacheExceptFrame(size_t clearExceptFrame) { - // Don't clear if there are no frames, or only one. - if (m_frameBufferCache.size() <= 1) - return 0; - - // If |clearExceptFrame| has status FrameComplete, we only preserve that - // frame. Otherwise, we *also* preserve the most recent previous frame with - // status FrameComplete whose data will be required to decode - // |clearExceptFrame|, either in initFrameBuffer() or ApplyPostProcessing(). - // This frame index is stored in |clearExceptFrame2|. All other frames can - // be cleared. - size_t clearExceptFrame2 = kNotFound; - if (clearExceptFrame < m_frameBufferCache.size() && - m_frameBufferCache[clearExceptFrame].getStatus() != - ImageFrame::FrameComplete) { - clearExceptFrame2 = - m_frameBufferCache[clearExceptFrame].requiredPreviousFrameIndex(); - } - - while ((clearExceptFrame2 < m_frameBufferCache.size()) && - (m_frameBufferCache[clearExceptFrame2].getStatus() != - ImageFrame::FrameComplete)) { - clearExceptFrame2 = - m_frameBufferCache[clearExceptFrame2].requiredPreviousFrameIndex(); - } - - return clearCacheExceptTwoFrames(clearExceptFrame, clearExceptFrame2); -} - void WEBPImageDecoder::clearFrameBuffer(size_t frameIndex) { if (m_demux && m_demuxState >= WEBP_DEMUX_PARSED_HEADER && m_frameBufferCache[frameIndex].getStatus() == ImageFrame::FramePartial) {
diff --git a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h index d33de58..946d7cc 100644 --- a/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h +++ b/third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h
@@ -53,7 +53,6 @@ int repetitionCount() const override; bool frameIsCompleteAtIndex(size_t) const override; float frameDurationAtIndex(size_t) const override; - size_t clearCacheExceptFrame(size_t) override; private: // ImageDecoder: @@ -66,6 +65,17 @@ size_t dataSize, size_t frameIndex); + // For WebP images, the frame status needs to be FrameComplete to decode + // subsequent frames that depend on frame |index|. The reason for this is that + // WebP uses the previous frame for alpha blending, in applyPostProcessing(). + // + // Before calling this, verify that frame |index| exists by checking that + // |index| is smaller than |m_frameBufferCache|.size(). + bool frameStatusSufficientForSuccessors(size_t index) override { + DCHECK(index < m_frameBufferCache.size()); + return m_frameBufferCache[index].getStatus() == ImageFrame::FrameComplete; + } + WebPIDecoder* m_decoder; WebPDecBuffer m_decoderBuffer; int m_formatFlags;
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp index 6793c6fc..22b8da2 100644 --- a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp +++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.cpp
@@ -50,11 +50,27 @@ MediaStreamComponent::MediaStreamComponent(const String& id, MediaStreamSource* source) - : m_source(source), m_id(id), m_enabled(true), m_muted(false) { + : MediaStreamComponent(id, source, true, false) {} + +MediaStreamComponent::MediaStreamComponent(const String& id, + MediaStreamSource* source, + bool enabled, + bool muted) + : m_source(source), m_id(id), m_enabled(enabled), m_muted(muted) { DCHECK(m_id.length()); ThreadState::current()->registerPreFinalizer(this); } +MediaStreamComponent* MediaStreamComponent::clone() const { + MediaStreamComponent* clonedComponent = new MediaStreamComponent( + createCanonicalUUIDString(), source(), m_enabled, m_muted); + // TODO(pbos): Clone |m_trackData| as well. + // TODO(pbos): Move properties from MediaStreamTrack here so that they are + // also cloned. Part of crbug:669212 since stopped is currently not carried + // over, nor is ended(). + return clonedComponent; +} + void MediaStreamComponent::dispose() { m_trackData.reset(); }
diff --git a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h index 8aa26e9..635bc82 100644 --- a/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h +++ b/third_party/WebKit/Source/platform/mediastream/MediaStreamComponent.h
@@ -66,6 +66,8 @@ static MediaStreamComponent* create(MediaStreamSource*); static MediaStreamComponent* create(const String& id, MediaStreamSource*); + MediaStreamComponent* clone() const; + // |m_trackData| may hold pointers to GC objects indirectly, and it may touch // eagerly finalized objects in destruction. // So this class runs pre-finalizer to finalize |m_trackData| promptly. @@ -93,6 +95,10 @@ private: MediaStreamComponent(const String& id, MediaStreamSource*); + MediaStreamComponent(const String& id, + MediaStreamSource*, + bool enabled, + bool muted); // AudioSourceProviderImpl wraps a WebAudioSourceProvider::provideInput() // calls into chromium to get a rendered audio stream.
diff --git a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp index 3c39350..305cfbe 100644 --- a/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp +++ b/tools/clang/rewrite_to_chrome_style/RewriteToChromeStyle.cpp
@@ -62,6 +62,14 @@ VariadicDynCastAllOfMatcher<clang::Expr, clang::UnresolvedMemberExpr> unresolvedMemberExpr; +const clang::ast_matchers::internal:: + VariadicDynCastAllOfMatcher<clang::Expr, clang::DependentScopeDeclRefExpr> + dependentScopeDeclRefExpr; + +const clang::ast_matchers::internal:: + VariadicDynCastAllOfMatcher<clang::Expr, clang::CXXDependentScopeMemberExpr> + cxxDependentScopeMemberExpr; + AST_MATCHER(clang::FunctionDecl, isOverloadedOperator) { return Node.isOverloadedOperator(); } @@ -165,6 +173,34 @@ return MatchAllOverriddenMethods(Node, InnerMatcher, Finder, Builder); } +// Matches |T::m| and/or |x->T::m| and/or |x->m| CXXDependentScopeMemberExpr +// if member |m| comes from a type that matches the InnerMatcher. +AST_MATCHER_P(clang::CXXDependentScopeMemberExpr, + hasMemberFromType, + clang::ast_matchers::internal::Matcher<clang::QualType>, + InnerMatcher) { + // Given |T::m| and/or |x->T::m| and/or |x->m| ... + if (clang::NestedNameSpecifier* nestedNameSpecifier = Node.getQualifier()) { + // ... if |T| is present, then InnerMatcher has to match |T|. + clang::QualType qualType(nestedNameSpecifier->getAsType(), 0); + return InnerMatcher.matches(qualType, Finder, Builder); + } else { + // ... if there is no |T|, then InnerMatcher has to match the type of |x|. + clang::Expr* base_expr = Node.isImplicitAccess() ? nullptr : Node.getBase(); + return base_expr && + InnerMatcher.matches(base_expr->getType(), Finder, Builder); + } +} + +// Matches |const Class<T>&| QualType if InnerMatcher matches |Class<T>|. +AST_MATCHER_P(clang::QualType, + hasBaseType, + clang::ast_matchers::internal::Matcher<clang::Type>, + InnerMatcher) { + const clang::Type* type = Node.getTypePtrOrNull(); + return type && InnerMatcher.matches(*type, Finder, Builder); +} + bool IsMethodOverrideOf(const clang::CXXMethodDecl& decl, const char* class_name) { if (decl.getParent()->getQualifiedNameAsString() == class_name) @@ -531,6 +567,24 @@ }; template <> +struct TargetNodeTraits<clang::DependentScopeDeclRefExpr> { + static clang::SourceLocation GetLoc( + const clang::DependentScopeDeclRefExpr& expr) { + return expr.getLocation(); + } + static const char* GetName() { return "expr"; } +}; + +template <> +struct TargetNodeTraits<clang::CXXDependentScopeMemberExpr> { + static clang::SourceLocation GetLoc( + const clang::CXXDependentScopeMemberExpr& expr) { + return expr.getMemberLoc(); + } + static const char* GetName() { return "expr"; } +}; + +template <> struct TargetNodeTraits<clang::CXXCtorInitializer> { static clang::SourceLocation GetLoc(const clang::CXXCtorInitializer& init) { assert(init.isWritten()); @@ -677,10 +731,45 @@ } clang::DeclarationName GetUnresolvedName( + const clang::DependentScopeDeclRefExpr& expr) { + return expr.getDeclName(); +} + +clang::DeclarationName GetUnresolvedName( + const clang::CXXDependentScopeMemberExpr& expr) { + return expr.getMember(); +} + +clang::DeclarationName GetUnresolvedName( const clang::UnresolvedUsingValueDecl& decl) { return decl.getDeclName(); } +// Returns whether |expr_node| is used as a callee in the AST (i.e. if +// |expr_node| needs to resolve to a method or a function). +bool IsCallee(const clang::Expr& expr, clang::ASTContext& context) { + auto matcher = stmt(hasParent(callExpr(callee(equalsNode(&expr))))); + return IsMatching(matcher, expr, context); +} + +// Returns whether |decl| will be used as a callee in the AST (i.e. if the value +// brought by the using declaration will resolve to a method or a function). +bool IsCallee(const clang::UnresolvedUsingValueDecl& decl, + clang::ASTContext& /* context */) { + // Caller (i.e. GuessNameForUnresolvedDependentNode) should have already + // filtered out fields before calling |IsCallee|. + clang::IdentifierInfo* info = GetUnresolvedName(decl).getAsIdentifierInfo(); + assert(info); + bool name_looks_like_a_field = info->getName().startswith(kBlinkFieldPrefix); + assert(!name_looks_like_a_field); + + // Looking just at clang::UnresolvedUsingValueDecl, we cannot tell whether it + // refers to something callable or not. Since fields should have been already + // filtered out before calling IsCallee (see the assert above), let's assume + // that |using Base::foo| refers to a method. + return true; +} + template <typename TargetNode> class UnresolvedRewriterBase : public RewriterBase<TargetNode> { public: @@ -690,13 +779,33 @@ : RewriterBase<TargetNode>(replacements) {} void run(const MatchFinder::MatchResult& result) override { - const TargetNode& expr = Base::GetTargetNode(result); - llvm::StringRef old_name = GetUnresolvedName(expr).getAsString(); - std::string new_name; - if (GuessNameForUnresolvedDependentNode(expr, *result.Context, old_name, - new_name)) { - Base::AddReplacement(result, old_name, std::move(new_name)); + const TargetNode& node = Base::GetTargetNode(result); + + clang::DeclarationName decl_name = GetUnresolvedName(node); + switch (decl_name.getNameKind()) { + // Do not rewrite this: + // return operator T*(); + // into this: + // return Operator type - parameter - 0 - 0 * T * (); + case clang::DeclarationName::NameKind::CXXConversionFunctionName: + case clang::DeclarationName::NameKind::CXXOperatorName: + case clang::DeclarationName::NameKind::CXXLiteralOperatorName: + return; + default: + break; } + + // Make sure there is an old name + extract the old name. + clang::IdentifierInfo* info = GetUnresolvedName(node).getAsIdentifierInfo(); + if (!info) + return; + llvm::StringRef old_name = info->getName(); + + // Try to guess a new name. + std::string new_name; + if (GuessNameForUnresolvedDependentNode(node, *result.Context, old_name, + new_name)) + Base::AddReplacement(result, old_name, std::move(new_name)); } private: @@ -706,13 +815,16 @@ // a specific decl until template instantiation - at the point of rename, one // cannot tell whether the node will eventually resolve to a field / method / // constant / etc. + // + // The method returns false if no renaming should be done. + // Otherwise the method returns true and sets |new_name|. bool GuessNameForUnresolvedDependentNode(const TargetNode& node, clang::ASTContext& context, llvm::StringRef old_name, std::string& new_name) { // |m_fieldName| -> |field_name_|. if (old_name.startswith(kBlinkFieldPrefix)) { - std::string field_name = old_name.str().substr(strlen(kBlinkFieldPrefix)); + std::string field_name = old_name.substr(strlen(kBlinkFieldPrefix)); if (field_name.find('_') == std::string::npos) { new_name = CamelCaseToUnderscoreCase(field_name) + "_"; return true; @@ -720,10 +832,10 @@ } // |T::myMethod(...)| -> |T::MyMethod(...)|. - if ((old_name.find('_') == std::string::npos) && + if ((old_name.find('_') == std::string::npos) && IsCallee(node, context) && !IsBlacklistedFunctionOrMethodName(old_name)) { new_name = old_name; - new_name[0] = clang::toUppercase(new_name[0]); + new_name[0] = clang::toUppercase(old_name[0]); return true; } @@ -742,6 +854,12 @@ using UnresolvedUsingValueDeclRewriter = UnresolvedRewriterBase<clang::UnresolvedUsingValueDecl>; +using DependentScopeDeclRefExprRewriter = + UnresolvedRewriterBase<clang::DependentScopeDeclRefExpr>; + +using CXXDependentScopeMemberExprRewriter = + UnresolvedRewriterBase<clang::CXXDependentScopeMemberExpr>; + } // namespace static llvm::cl::extrahelp common_help(CommonOptionsParser::HelpMessage); @@ -1068,6 +1186,62 @@ UsingDeclRewriter using_decl_rewriter(&replacements); match_finder.addMatcher(using_decl_matcher, &using_decl_rewriter); + // Matches any QualType that refers to a blink type: + // - const blink::Foo& + // - blink::Foo* + // - blink::Foo<T> + // - ... + // TODO(lukasza): The matchers below can be simplified after + // https://llvm.org/bugs/show_bug.cgi?id=30331 is fixed. + // Simplified matchers: + // auto blink_qual_type_base_matcher = + // qualType(hasDeclaration(in_blink_namespace)); + // auto blink_qual_type_matcher = qualType(anyOf( + // blink_qual_type_base_matcher, + // pointsTo(blink_qual_type_base_matcher), + // references(blink_qual_type_base_matcher))); + auto blink_qual_type_bug_workaround_matcher1 = hasBaseType( + anyOf(enumType(hasDeclaration(in_blink_namespace)), + recordType(hasDeclaration(in_blink_namespace)), + templateSpecializationType(hasDeclaration(in_blink_namespace)), + templateTypeParmType(hasDeclaration(in_blink_namespace)), + typedefType(hasDeclaration(in_blink_namespace)))); + auto blink_qual_type_base_matcher = + qualType(anyOf(blink_qual_type_bug_workaround_matcher1, + hasBaseType(elaboratedType( + namesType(blink_qual_type_bug_workaround_matcher1))))); + auto blink_qual_type_matcher = + qualType(anyOf(blink_qual_type_base_matcher, pointsTo(in_blink_namespace), + references(in_blink_namespace))); + + // Template-dependent decl lookup ======== + // Given + // template <typename T> void f() { T::foo(); } + // matches |T::foo|. + auto dependent_scope_decl_ref_expr_matcher = + expr(id("expr", dependentScopeDeclRefExpr(has(nestedNameSpecifier( + specifiesType(blink_qual_type_matcher)))))); + DependentScopeDeclRefExprRewriter dependent_scope_decl_ref_expr_rewriter( + &replacements); + match_finder.addMatcher(dependent_scope_decl_ref_expr_matcher, + &dependent_scope_decl_ref_expr_rewriter); + + // Template-dependent member lookup ======== + // Given + // template <typename T> + // class Foo { + // void f() { T::foo(); } + // void g(T x) { x.bar(); } + // }; + // matches |T::foo| and |x.bar|. + auto cxx_dependent_scope_member_expr_matcher = + expr(id("expr", cxxDependentScopeMemberExpr( + hasMemberFromType(blink_qual_type_matcher)))); + CXXDependentScopeMemberExprRewriter cxx_dependent_scope_member_expr_rewriter( + &replacements); + match_finder.addMatcher(cxx_dependent_scope_member_expr_matcher, + &cxx_dependent_scope_member_expr_rewriter); + std::unique_ptr<clang::tooling::FrontendActionFactory> factory = clang::tooling::newFrontendActionFactory(&match_finder); int result = tool.run(factory.get());
diff --git a/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc index faef4ec..e0f87b1 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/fields-expected.cc
@@ -145,6 +145,14 @@ !kIsGarbageCollected ? kRefCountedLifetime : kGarbageCollectedLifetime; }; +template <typename T> +struct GenericHashTraitsBase { + // We don't want to capitalize fields in type traits + // (i.e. the |value| -> |kValue| rename is undesirable below). + // This problem is prevented by IsCallee heuristic. + static const int kWeakHandlingFlag = TypeTrait2<T>::value ? 123 : 456; +}; + }; // namespace WTF void F() {
diff --git a/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc b/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc index 726c521..d93d986 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/fields-original.cc
@@ -142,6 +142,14 @@ !isGarbageCollected ? RefCountedLifetime : GarbageCollectedLifetime; }; +template <typename T> +struct GenericHashTraitsBase { + // We don't want to capitalize fields in type traits + // (i.e. the |value| -> |kValue| rename is undesirable below). + // This problem is prevented by IsCallee heuristic. + static const int kWeakHandlingFlag = TypeTrait2<T>::value ? 123 : 456; +}; + }; // namespace WTF void F() {
diff --git a/tools/clang/rewrite_to_chrome_style/tests/function-templates-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/function-templates-expected.cc index 69a33495..8d064a1 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/function-templates-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/function-templates-expected.cc
@@ -21,14 +21,11 @@ public: template <typename U, typename V> Checked(const Checked<U, V>& rhs) { - // This (incorrectly) doesn't get rewritten, since it's not instantiated. In - // this case, the AST representation contains a bunch of - // CXXDependentScopeMemberExpr nodes. - if (rhs.hasOverflowed()) - this->overflowed(); - if (!IsInBounds<T>(rhs.m_value)) - this->overflowed(); - value_ = static_cast<T>(rhs.m_value); + if (rhs.HasOverflowed()) + this->Overflowed(); + if (!IsInBounds<T>(rhs.value_)) + this->Overflowed(); + value_ = static_cast<T>(rhs.value_); } bool HasOverflowed() const { return false; } @@ -40,11 +37,28 @@ template <typename To, typename From> To Bitwise_cast(From from) { - static_assert(sizeof(To) == sizeof(From)); + static_assert(sizeof(To) == sizeof(From), "msg"); return reinterpret_cast<To>(from); } } // namespace WTF +namespace mojo { + +template <typename U> +struct ArrayTraits; + +template <typename U> +struct ArrayTraits<WTF::Checked<U, int>> { + static bool HasOverflowed(WTF::Checked<U, int>& input) { + // |hasOverflowed| below should be rewritten to |HasOverflowed| + // (because this is a method of WTF::Checked; it doesn't matter + // that we are not in WTF namespace *here*). + return input.HasOverflowed(); + } +}; + +} // namespace mojo + using WTF::Bitwise_cast; using WTF::SafeCast;
diff --git a/tools/clang/rewrite_to_chrome_style/tests/function-templates-original.cc b/tools/clang/rewrite_to_chrome_style/tests/function-templates-original.cc index 71267b0..80e244b 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/function-templates-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/function-templates-original.cc
@@ -21,9 +21,6 @@ public: template<typename U, typename V> Checked(const Checked<U, V>& rhs){ - // This (incorrectly) doesn't get rewritten, since it's not instantiated. In - // this case, the AST representation contains a bunch of - // CXXDependentScopeMemberExpr nodes. if (rhs.hasOverflowed()) this->overflowed(); if (!isInBounds<T>(rhs.m_value)) @@ -40,11 +37,28 @@ template<typename To, typename From> To bitwise_cast(From from) { - static_assert(sizeof(To) == sizeof(From)); + static_assert(sizeof(To) == sizeof(From), "msg"); return reinterpret_cast<To>(from); } } // namespace WTF +namespace mojo { + +template <typename U> +struct ArrayTraits; + +template <typename U> +struct ArrayTraits<WTF::Checked<U, int>> { + static bool HasOverflowed(WTF::Checked<U, int>& input) { + // |hasOverflowed| below should be rewritten to |HasOverflowed| + // (because this is a method of WTF::Checked; it doesn't matter + // that we are not in WTF namespace *here*). + return input.hasOverflowed(); + } +}; + +} // namespace mojo + using WTF::bitwise_cast; using WTF::safeCast;
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc index a7f42051..18e4512 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/template-expected.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <type_traits> + namespace not_blink { void function(int x) {} @@ -9,6 +11,7 @@ class Class { public: void method() {} + virtual void virtualMethod() {} template <typename T> void methodTemplate(T) {} template <typename T> @@ -18,6 +21,17 @@ template <typename T> void functionTemplate(T x) {} +template <typename T = Class> +void functionTemplate2() { + T::staticMethodTemplate(123); +} + +template <typename T = Class> +class TemplatedClass { + public: + void anotherMethod() { T::staticMethodTemplate(123); } +}; + } // not_blink namespace blink { @@ -180,4 +194,90 @@ } // namespace test_unnamed_arg +namespace cxx_dependent_scope_member_expr_testing { + +class PartitionAllocator { + public: + static void Method() {} +}; + +template <typename Allocator = PartitionAllocator> +class Vector { + public: + // https://crbug.com/582315: |Allocator::method| is a + // CXXDependentScopeMemberExpr. + void AnotherMethod() { + if (std::is_class<Allocator>::value) // Shouldn't rename |value| + Allocator::Method(); // Should rename |method| -> |Method|. + } +}; + +template <typename Allocator = PartitionAllocator> +void Test() { + // https://crbug.com/582315: |Allocator::method| is a + // DependentScopeDeclRefExpr. + if (std::is_class<Allocator>::value) // Shouldn't rename |value|. + Allocator::Method(); // Should rename |method|. +} + +class InterceptingCanvasBase : public ::not_blink::Class { + public: + virtual void VirtualMethodInBlink(){}; +}; + +template <typename DerivedCanvas> +class InterceptingCanvas : public InterceptingCanvasBase { + public: + void virtualMethod() override { + this->Class::virtualMethod(); // https://crbug.com/582315#c19 + this->InterceptingCanvasBase::VirtualMethodInBlink(); + } +}; + +template <typename T> +class ThreadSpecific { + public: + T* operator->(); + operator T*(); +}; + +template <typename T> +inline ThreadSpecific<T>::operator T*() { + return nullptr; +} + +template <typename T> +inline T* ThreadSpecific<T>::operator->() { + return operator T*(); +} + +class Class { + public: + virtual void VirtualMethodInBlink() {} +}; + +} // namespace cxx_dependent_scope_member_expr_testing + } // namespace blink + +namespace not_blink { + +namespace cxx_dependent_scope_member_expr_testing { + +class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class { + public: + virtual void virtualMethod() {} +}; + +template <typename T> +class Derived : public Base { + public: + void virtualMethod() override { + this->Class::VirtualMethodInBlink(); + this->Base::virtualMethod(); + } +}; + +} // namespace cxx_dependent_scope_member_expr_testing + +} // namespace not_blink
diff --git a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc index cf22188..e8b9345 100644 --- a/tools/clang/rewrite_to_chrome_style/tests/template-original.cc +++ b/tools/clang/rewrite_to_chrome_style/tests/template-original.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <type_traits> + namespace not_blink { void function(int x) {} @@ -9,6 +11,7 @@ class Class { public: void method() {} + virtual void virtualMethod() {} template <typename T> void methodTemplate(T) {} template <typename T> @@ -18,6 +21,17 @@ template <typename T> void functionTemplate(T x) {} +template <typename T = Class> +void functionTemplate2() { + T::staticMethodTemplate(123); +} + +template <typename T = Class> +class TemplatedClass { + public: + void anotherMethod() { T::staticMethodTemplate(123); } +}; + } // not_blink namespace blink { @@ -180,4 +194,90 @@ } // namespace test_unnamed_arg +namespace cxx_dependent_scope_member_expr_testing { + +class PartitionAllocator { + public: + static void method() {} +}; + +template <typename Allocator = PartitionAllocator> +class Vector { + public: + // https://crbug.com/582315: |Allocator::method| is a + // CXXDependentScopeMemberExpr. + void anotherMethod() { + if (std::is_class<Allocator>::value) // Shouldn't rename |value| + Allocator::method(); // Should rename |method| -> |Method|. + } +}; + +template <typename Allocator = PartitionAllocator> +void test() { + // https://crbug.com/582315: |Allocator::method| is a + // DependentScopeDeclRefExpr. + if (std::is_class<Allocator>::value) // Shouldn't rename |value|. + Allocator::method(); // Should rename |method|. +} + +class InterceptingCanvasBase : public ::not_blink::Class { + public: + virtual void virtualMethodInBlink(){}; +}; + +template <typename DerivedCanvas> +class InterceptingCanvas : public InterceptingCanvasBase { + public: + void virtualMethod() override { + this->Class::virtualMethod(); // https://crbug.com/582315#c19 + this->InterceptingCanvasBase::virtualMethodInBlink(); + } +}; + +template <typename T> +class ThreadSpecific { + public: + T* operator->(); + operator T*(); +}; + +template <typename T> +inline ThreadSpecific<T>::operator T*() { + return nullptr; +} + +template <typename T> +inline T* ThreadSpecific<T>::operator->() { + return operator T*(); +} + +class Class { + public: + virtual void virtualMethodInBlink() {} +}; + +} // namespace cxx_dependent_scope_member_expr_testing + } // namespace blink + +namespace not_blink { + +namespace cxx_dependent_scope_member_expr_testing { + +class Base : public ::blink::cxx_dependent_scope_member_expr_testing::Class { + public: + virtual void virtualMethod() {} +}; + +template <typename T> +class Derived : public Base { + public: + void virtualMethod() override { + this->Class::virtualMethodInBlink(); + this->Base::virtualMethod(); + } +}; + +} // namespace cxx_dependent_scope_member_expr_testing + +} // namespace not_blink
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 079207c..41da607 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -39352,17 +39352,11 @@ </histogram> <histogram name="Notifications.Icon.FileSize" units="bytes"> - <obsolete> - Deprecated Nov 2016 in favor of Notifications.LoadFileSize.* - </obsolete> <owner>peter@chromium.org</owner> <summary>The number of bytes loaded for a Web Notification icon.</summary> </histogram> <histogram name="Notifications.Icon.LoadFailTime" units="ms"> - <obsolete> - Deprecated Nov 2016 in favor of Notifications.LoadFailTime.* - </obsolete> <owner>peter@chromium.org</owner> <summary> The number of milliseconds it took to fail loading an icon for a Web @@ -39371,9 +39365,6 @@ </histogram> <histogram name="Notifications.Icon.LoadFinishTime" units="ms"> - <obsolete> - Deprecated Nov 2016 in favor of Notifications.LoadFinishTime.* - </obsolete> <owner>peter@chromium.org</owner> <summary> The number of milliseconds it took to finish successfully loading an icon @@ -39382,9 +39373,6 @@ </histogram> <histogram name="Notifications.Icon.ScaleDownTime" units="ms"> - <obsolete> - Deprecated Nov 2016 in favor of Notifications.LoadScaleDownTime.* - </obsolete> <owner>peter@chromium.org</owner> <summary> The number of milliseconds it took to scale down an icon for a Web @@ -39392,45 +39380,6 @@ </summary> </histogram> -<histogram name="Notifications.LoadFailTime" units="ms"> -<!-- Name completed by histogram_suffixes name="NotificationImageTypes" --> - - <owner>johnme@chromium.org</owner> - <summary> - The number of milliseconds it took to fail loading an icon/image for a Web - Notification. - </summary> -</histogram> - -<histogram name="Notifications.LoadFileSize" units="bytes"> -<!-- Name completed by histogram_suffixes name="NotificationImageTypes" --> - - <owner>johnme@chromium.org</owner> - <summary> - The number of bytes loaded for a Web Notification icon/image. - </summary> -</histogram> - -<histogram name="Notifications.LoadFinishTime" units="ms"> -<!-- Name completed by histogram_suffixes name="NotificationImageTypes" --> - - <owner>johnme@chromium.org</owner> - <summary> - The number of milliseconds it took to finish successfully loading an - icon/image for a Web Notification. - </summary> -</histogram> - -<histogram name="Notifications.LoadScaleDownTime" units="ms"> -<!-- Name completed by histogram_suffixes name="NotificationImageTypes" --> - - <owner>johnme@chromium.org</owner> - <summary> - The number of milliseconds it took to scale down an icon/image for a Web - Notification. - </summary> -</histogram> - <histogram name="Notifications.PerNotificationActions" enum="NotificationActionType"> <owner>dewittj@chromium.org</owner> @@ -84511,6 +84460,8 @@ <int value="1149" label="SYSTEM_DISPLAY_TOUCHCALIBRATIONSTART"/> <int value="1150" label="SYSTEM_DISPLAY_TOUCHCALIBRATIONSET"/> <int value="1151" label="SYSTEM_DISPLAY_TOUCHCALIBRATIONRESET"/> + <int value="1152" label="CERTIFICATEPROVIDER_REQUESTPIN"/> + <int value="1153" label="CERTIFICATEPROVIDER_STOPPINREQUEST"/> </enum> <enum name="ExtensionIconState" type="int"> @@ -110806,17 +110757,6 @@ <affected-histogram name="Notifications.Display"/> </histogram_suffixes> -<histogram_suffixes name="NotificationImageTypes" separator="."> - <suffix name="ActionIcon"/> - <suffix name="Badge"/> - <suffix name="Icon"/> - <suffix name="Image"/> - <affected-histogram name="Notifications.LoadFailTime"/> - <affected-histogram name="Notifications.LoadFileSize"/> - <affected-histogram name="Notifications.LoadFinishTime"/> - <affected-histogram name="Notifications.LoadScaleDownTime"/> -</histogram_suffixes> - <histogram_suffixes name="NQE.Accuracy.Metric.Accuracy.DiffPositiveOrNegative" separator="."> <suffix name="Negative"
diff --git a/ui/views/mus/aura_init.cc b/ui/views/mus/aura_init.cc index 38d7ae84..ec928419f 100644 --- a/ui/views/mus/aura_init.cc +++ b/ui/views/mus/aura_init.cc
@@ -55,9 +55,10 @@ Mode mode) : resource_file_(resource_file), resource_file_200_(resource_file_200), - env_(aura::Env::CreateInstance(mode == Mode::AURA_MUS - ? aura::Env::Mode::MUS - : aura::Env::Mode::LOCAL)), + env_(aura::Env::CreateInstance( + (mode == Mode::AURA_MUS || mode == Mode::AURA_MUS_WINDOW_MANAGER) + ? aura::Env::Mode::MUS + : aura::Env::Mode::LOCAL)), views_delegate_(new MusViewsDelegate) { if (mode == Mode::AURA_MUS) { mus_client_ =
diff --git a/ui/views/mus/aura_init.h b/ui/views/mus/aura_init.h index c028a7e..3558d73 100644 --- a/ui/views/mus/aura_init.h +++ b/ui/views/mus/aura_init.h
@@ -43,8 +43,12 @@ // Indicates AuraInit should target using aura with mus. AURA_MUS, + // Indicates AuraInit should target using aura with mus, for a Window + // Manager client. + AURA_MUS_WINDOW_MANAGER, + // Indicates AuraInit should target using ui::Window. - UI, + UI }; // |resource_file| is the file to load strings and 1x icons from.